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: stable@kernel.org Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
a91714312e
commit
fb4554c223
|
@ -1450,13 +1450,9 @@ err:
|
||||||
return ERR_PTR(r);
|
return ERR_PTR(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ptr_ring *get_tap_ptr_ring(int fd)
|
static struct ptr_ring *get_tap_ptr_ring(struct file *file)
|
||||||
{
|
{
|
||||||
struct ptr_ring *ring;
|
struct ptr_ring *ring;
|
||||||
struct file *file = fget(fd);
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
return NULL;
|
|
||||||
ring = tun_get_tx_ring(file);
|
ring = tun_get_tx_ring(file);
|
||||||
if (!IS_ERR(ring))
|
if (!IS_ERR(ring))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1465,7 +1461,6 @@ static struct ptr_ring *get_tap_ptr_ring(int fd)
|
||||||
goto out;
|
goto out;
|
||||||
ring = NULL;
|
ring = NULL;
|
||||||
out:
|
out:
|
||||||
fput(file);
|
|
||||||
return ring;
|
return ring;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1552,8 +1547,12 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
|
||||||
r = vhost_net_enable_vq(n, vq);
|
r = vhost_net_enable_vq(n, vq);
|
||||||
if (r)
|
if (r)
|
||||||
goto err_used;
|
goto err_used;
|
||||||
if (index == VHOST_NET_VQ_RX)
|
if (index == VHOST_NET_VQ_RX) {
|
||||||
nvq->rx_ring = get_tap_ptr_ring(fd);
|
if (sock)
|
||||||
|
nvq->rx_ring = get_tap_ptr_ring(sock->file);
|
||||||
|
else
|
||||||
|
nvq->rx_ring = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
oldubufs = nvq->ubufs;
|
oldubufs = nvq->ubufs;
|
||||||
nvq->ubufs = ubufs;
|
nvq->ubufs = ubufs;
|
||||||
|
|
Loading…
Reference in New Issue