Skip to content

Commit b0c057c

Browse files
mstsirkindavem330
authored andcommitted
vhost: fix a theoretical race in device cleanup
vhost_zerocopy_callback accesses VQ right after it drops a ubuf reference. In theory, this could race with device removal which waits on the ubuf kref, and crash on use after free. Do all accesses within rcu read side critical section, and synchronize on release. Since callbacks are always invoked from bh, synchronize_rcu_bh seems enough and will help release complete a bit faster. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 0ad8b48 commit b0c057c

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

drivers/vhost/net.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
308308
struct vhost_virtqueue *vq = ubufs->vq;
309309
int cnt;
310310

311+
rcu_read_lock_bh();
312+
311313
/* set len to mark this desc buffers done DMA */
312314
vq->heads[ubuf->desc].len = success ?
313315
VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
@@ -322,6 +324,8 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
322324
*/
323325
if (cnt <= 1 || !(cnt % 16))
324326
vhost_poll_queue(&vq->poll);
327+
328+
rcu_read_unlock_bh();
325329
}
326330

327331
/* Expects to be always run from workqueue - which acts as
@@ -799,6 +803,8 @@ static int vhost_net_release(struct inode *inode, struct file *f)
799803
fput(tx_sock->file);
800804
if (rx_sock)
801805
fput(rx_sock->file);
806+
/* Make sure no callbacks are outstanding */
807+
synchronize_rcu_bh();
802808
/* We do an extra flush before freeing memory,
803809
* since jobs can re-queue themselves. */
804810
vhost_net_flush(n);

0 commit comments

Comments
 (0)