On Thu, 2023-11-30 at 20:09 +0800, Heng Qi wrote: > > 在 2023/11/30 下午5:33, Paolo Abeni 写道: > > On Mon, 2023-11-27 at 10:55 +0800, Heng Qi wrote: > > > @@ -4738,11 +4881,14 @@ static void remove_vq_common(struct virtnet_info *vi) > > > static void virtnet_remove(struct virtio_device *vdev) > > > { > > > struct virtnet_info *vi = vdev->priv; > > > + int i; > > > > > > virtnet_cpu_notif_remove(vi); > > > > > > /* Make sure no work handler is accessing the device. */ > > > flush_work(&vi->config_work); > > > + for (i = 0; i < vi->max_queue_pairs; i++) > > > + cancel_work(&vi->rq[i].dim.work); > > If the dim work is still running here, what prevents it from completing > > after the following unregister/free netdev? > > Yes, no one here is trying to stop it, So it will cause UaF, right? > the situation is like > unregister/free netdev > when rss are being set, so I think this is ok. Could you please elaborate more the point? > > It looks like you want need to call cancel_work_sync here? > > In v4, Yinjun Zhang mentioned that _sync() can cause deadlock[1]. > Therefore, cancel_work() is used here instead of cancel_work_sync() to > avoid possible deadlock. > > [1] > https://lore.kernel.org/all/20231122092939.1005591-1-yinjun.zhang@xxxxxxxxxxxx/ Here the call to cancel_work() happens while the caller does not held the rtnl lock, the deadlock reported above will not be triggered. > > Additionally the later remove_vq_common() will needless call > > cancel_work() again; > > Yes. remove_vq_common() now does not call cancel_work(). I'm sorry, I missread the context in a previous chunk. The other point should still apply. Cheers, Paolo