Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

virtio_net: fix virtnet_open and virtnet_probe competing for try_fill_recv

In function virtnet_open() and virtnet_probe(), func try_fill_recv() may
be executed at the same time. VQ in virtqueue_add() has not been protected
well and BUG_ON will be triggered when virito_net.ko being removed.

Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

wangyunjian and committed by
David S. Miller
f00e35e2 bae5499c

+2 -16
+2 -16
drivers/net/virtio_net.c
··· 1925 1925 1926 1926 virtio_device_ready(vdev); 1927 1927 1928 - /* Last of all, set up some receive buffers. */ 1929 - for (i = 0; i < vi->curr_queue_pairs; i++) { 1930 - try_fill_recv(vi, &vi->rq[i], GFP_KERNEL); 1931 - 1932 - /* If we didn't even get one input buffer, we're useless. */ 1933 - if (vi->rq[i].vq->num_free == 1934 - virtqueue_get_vring_size(vi->rq[i].vq)) { 1935 - free_unused_bufs(vi); 1936 - err = -ENOMEM; 1937 - goto free_recv_bufs; 1938 - } 1939 - } 1940 - 1941 1928 vi->nb.notifier_call = &virtnet_cpu_callback; 1942 1929 err = register_hotcpu_notifier(&vi->nb); 1943 1930 if (err) { 1944 1931 pr_debug("virtio_net: registering cpu notifier failed\n"); 1945 - goto free_recv_bufs; 1932 + goto free_unregister_netdev; 1946 1933 } 1947 1934 1948 1935 /* Assume link up if device can't report link status, ··· 1947 1960 1948 1961 return 0; 1949 1962 1950 - free_recv_bufs: 1963 + free_unregister_netdev: 1951 1964 vi->vdev->config->reset(vdev); 1952 1965 1953 - free_receive_bufs(vi); 1954 1966 unregister_netdev(dev); 1955 1967 free_vqs: 1956 1968 cancel_delayed_work_sync(&vi->refill);