ABBA deadlock occurs in the following scenario: CPU0 CPU1 ---- ---- n_vclocks_store() lock(&ptp->n_vclocks_mux) [1] pc_clock_adjtime() lock(&clk->rwsem) [2] ... ptp_clock_freerun() ptp_vclock_in_use() lock(&ptp->n_vclocks_mux) [3] ptp_clock_unregister() posix_clock_unregister() lock(&clk->rwsem) [4] To solve this with minimal patches, we should change ptp_clock_freerun() to briefly release the read lock before calling ptp_vclock_in_use() and then re-lock it when we're done. Reported-by: syzbot+7cfb66a237c4a5fb22ad@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7cfb66a237c4a5fb22ad Fixes: 73f37068d540 ("ptp: support ptp physical/virtual clocks conversion") Signed-off-by: Jeongjun Park --- drivers/ptp/ptp_private.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h index a6aad743c282..e2c37e968c88 100644 --- a/drivers/ptp/ptp_private.h +++ b/drivers/ptp/ptp_private.h @@ -124,10 +124,16 @@ static inline bool ptp_vclock_in_use(struct ptp_clock *ptp) /* Check if ptp clock shall be free running */ static inline bool ptp_clock_freerun(struct ptp_clock *ptp) { + bool ret = false; + if (ptp->has_cycles) - return false; + return ret; + + up_read(&ptp->clock.rwsem); + ret = ptp_vclock_in_use(ptp); + down_read(&ptp->clock.rwsem); - return ptp_vclock_in_use(ptp); + return ret; } extern const struct class ptp_class; --