Re: [PATCH] IB/cm: Fix possible use-after-free in ib_cm_cleanup()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux