On Wed, Oct 13, 2021 at 05:30:16PM +0800, Wang Hai wrote: > This module's remove path calls cancel_delayed_work(). However, that > function does not wait until the work function finishes. This means > that the callback function may still be running after the driver's > remove function has finished, which would result in a use-after-free. > > Fix by calling cancel_delayed_work_sync(), which ensures that > the work is properly cancelled, no longer running, and unable > to re-schedule itself. > > Fixes: 8575329d4f85 ("IB/cm: Fix timewait crash after module unload") > Reported-by: Hulk Robot <hulkci@xxxxxxxxxx> > Signed-off-by: Wang Hai <wanghai38@xxxxxxxxxx> > drivers/infiniband/core/cm.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c > index c903b74f46a4..ae0af63f3271 100644 > +++ b/drivers/infiniband/core/cm.c > @@ -4508,7 +4508,7 @@ static void __exit ib_cm_cleanup(void) > > spin_lock_irq(&cm.lock); > list_for_each_entry(timewait_info, &cm.timewait_list, list) > - cancel_delayed_work(&timewait_info->work.work); > + cancel_delayed_work_sync(&timewait_info->work.work); > spin_unlock_irq(&cm.lock); No, this will deadlock: static int cm_timewait_handler(struct cm_work *work) { struct cm_timewait_info *timewait_info; struct cm_id_private *cm_id_priv; timewait_info = container_of(work, struct cm_timewait_info, work); spin_lock_irq(&cm.lock); ^^^^^^^^^^^^ Holds the same lock What is your bug? The destroy_wq() a few lines below will flush out all the work so it is already not possible that work can still exist after the driver's remove function has finished. Jason