Skip to content

Commit fb4554c

Browse files
author
Al Viro
committed
Fix double fget() in vhost_net_set_backend()
Descriptor table is a shared resource; two fget() on the same descriptor may return different struct file references. get_tap_ptr_ring() is called after we'd found (and pinned) the socket we'll be using and it tries to find the private tun/tap data structures associated with it. Redoing the lookup by the same file descriptor we'd used to get the socket is racy - we need to same struct file. Thanks to Jason for spotting a braino in the original variant of patch - I'd missed the use of fd == -1 for disabling backend, and in that case we can end up with sock == NULL and sock != oldsock. Cc: [email protected] Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Jason Wang <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent a917143 commit fb4554c

File tree

1 file changed

+7
-8
lines changed

1 file changed

+7
-8
lines changed

drivers/vhost/net.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,13 +1450,9 @@ static struct socket *get_raw_socket(int fd)
14501450
return ERR_PTR(r);
14511451
}
14521452

1453-
static struct ptr_ring *get_tap_ptr_ring(int fd)
1453+
static struct ptr_ring *get_tap_ptr_ring(struct file *file)
14541454
{
14551455
struct ptr_ring *ring;
1456-
struct file *file = fget(fd);
1457-
1458-
if (!file)
1459-
return NULL;
14601456
ring = tun_get_tx_ring(file);
14611457
if (!IS_ERR(ring))
14621458
goto out;
@@ -1465,7 +1461,6 @@ static struct ptr_ring *get_tap_ptr_ring(int fd)
14651461
goto out;
14661462
ring = NULL;
14671463
out:
1468-
fput(file);
14691464
return ring;
14701465
}
14711466

@@ -1552,8 +1547,12 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
15521547
r = vhost_net_enable_vq(n, vq);
15531548
if (r)
15541549
goto err_used;
1555-
if (index == VHOST_NET_VQ_RX)
1556-
nvq->rx_ring = get_tap_ptr_ring(fd);
1550+
if (index == VHOST_NET_VQ_RX) {
1551+
if (sock)
1552+
nvq->rx_ring = get_tap_ptr_ring(sock->file);
1553+
else
1554+
nvq->rx_ring = NULL;
1555+
}
15571556

15581557
oldubufs = nvq->ubufs;
15591558
nvq->ubufs = ubufs;

0 commit comments

Comments
 (0)