Re: [PATCH net] vsock/virtio: validate packet source for connected sockets
Bobby Eshleman <[email protected]>
| Newsgroups | org.kernel.vger.kvm,dev.linux.lists.virtualization,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Aug 13, 2026 at 09:12:36PM +0900, Daehyeon Ko wrote:
> virtio_transport_recv_pkt() first looks up a socket using the full source
> and destination tuple. If that misses, it falls back to a bound-socket
> lookup using only the destination address. The fallback is needed for
> listening and connecting sockets, but it can also select an established
> socket that remains in the bound table.
>
> As a result, a packet from an unrelated source can be dispatched to a
> non-listening socket. In TCP_SYN_SENT, a source-blind RESPONSE marks the
> selected socket established while retaining its original remote address.
> Subsequent RW packets can likewise be delivered through the
> destination-only fallback.
>
> This was reproduced with two capless processes under different UIDs. The
> attacker discovered the victim tuple through unprivileged AF_VSOCK
> sock_diag and injected a chosen 16-byte payload into the victim established
> loopback socket. The legitimate peer received none of those bytes.
>
> After taking the socket lock, verify that packets for non-listening sockets
> come from the peer stored in remote_addr. Listening sockets continue to
> accept packets from any source.
>
> Fixes: 06a8fc78367d ("VSOCK: Introduce virtio_vsock_common.ko")
> Cc: [email protected]
> Signed-off-by: Daehyeon Ko <[email protected]>
> ---
> net/vmw_vsock/virtio_transport_common.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> index 8becad812..f73e0406a 100644
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -1822,11 +1822,15 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
>
> lock_sock(sk);
>
> - /* Check if sk has been closed or assigned to another transport before
> - * lock_sock (note: listener sockets are not assigned to any transport)
> + /* Check if sk has been closed, assigned to another transport, or if the
> + * packet is from a different peer than the one connected to sk. These
> + * properties could have changed before lock_sock. Listener sockets are
> + * not assigned to any transport and accept packets from any peer.
> */
> if (sock_flag(sk, SOCK_DONE) ||
> - (sk->sk_state != TCP_LISTEN && vsk->transport != &t->transport)) {
> + (sk->sk_state != TCP_LISTEN &&
> + (vsk->transport != &t->transport ||
> + !vsock_addr_equals_addr(&src, &vsk->remote_addr)))) {
Does this equality work for loopback, when the CID may be
VMADDR_CID_LOCAL and/or VMADDR_CID_HOST on host or the guest CID in
guest?
Best,
Bobby