On Tue, Aug 25, 2026 at 5:40 PM Daehyeon Ko <[email protected]> wrote:
>
> vmci_transport_recv_stream_cb() looks up sockets first by the full source
> and destination tuple, then by destination only in the bound table. The
> fallback can select a non-listening socket without checking whether the
> packet came from its stored peer.
>
> This was reproduced with two VMCI contexts. A RST from the context not
> stored in a TCP_SYN_SENT socket reset that socket after it was selected by
> the destination-only lookup.
>
> VMCI can process notification packets in bottom-half context when the
> socket is not owned by user context, or defer packets to a workqueue. Use
> vsock_check_source() after taking the socket lock in the bottom-half path,
> and recheck after lock_sock() in the workqueue path. Listening sockets
> continue to accept packets from any source.
>
> Reply with a RST addressed from the received packet before dropping a
> source that fails validation. This preserves the existing reset behavior
> for bound non-listening and concurrently closed sockets without directing
> the reset to a connected socket's stored peer.
>
> Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
> Reported-by: Sashiko <[email protected]>
> Closes: 
> https://lore.kernel.org/netdev/[email protected]/
> Cc: [email protected]
> Suggested-by: Stefano Garzarella <[email protected]>
> Suggested-by: Paolo Abeni <[email protected]>
> Assisted-by: Codex:gpt-5.6-sol
> Signed-off-by: Daehyeon Ko <[email protected]>

Reviewed-by: Vishnu Dasa <[email protected]>

Thanks!

> ---
>  net/vmw_vsock/vmci_transport.c | 34 ++++++++++++++++++++++++++++------
>  1 file changed, 28 insertions(+), 6 deletions(-)
>
> diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
> index 1c4ee039c..1f186e8f8 100644
> --- a/net/vmw_vsock/vmci_transport.c
> +++ b/net/vmw_vsock/vmci_transport.c
> @@ -680,11 +680,13 @@ static int vmci_transport_recv_stream_cb(void *data, 
> struct vmci_datagram *dg)
>         struct vmci_transport_packet *pkt;
>         struct vsock_sock *vsk;
>         bool bh_process_pkt;
> +       bool drop_pkt;
>         int err;
>
>         sk = NULL;
>         err = VMCI_SUCCESS;
>         bh_process_pkt = false;
> +       drop_pkt = false;
>
>         /* Ignore incoming packets from resources that aren't vsock
>          * implementations.
> @@ -765,17 +767,29 @@ static int vmci_transport_recv_stream_cb(void *data, 
> struct vmci_datagram *dg)
>         bh_lock_sock(sk);
>
>         if (!sock_owned_by_user(sk)) {
> -               /* The local context ID may be out of date, update it. */
> -               vsk->local_addr.svm_cid = dst.svm_cid;
> +               if (sk->sk_state != TCP_LISTEN &&
> +                   !vsock_check_source(vsk, &vmci_transport, &src)) {
> +                       drop_pkt = true;
> +                       err = VMCI_ERROR_NO_ACCESS;
> +               } else {
> +                       /* The local context ID may be out of date, update 
> it. */
> +                       vsk->local_addr.svm_cid = dst.svm_cid;
>
> -               if (sk->sk_state == TCP_ESTABLISHED)
> -                       vmci_trans(vsk)->notify_ops->handle_notify_pkt(
> -                                       sk, pkt, true, &dst, &src,
> -                                       &bh_process_pkt);
> +                       if (sk->sk_state == TCP_ESTABLISHED)
> +                               
> vmci_trans(vsk)->notify_ops->handle_notify_pkt(sk, pkt, true,
> +                                                                             
>  &dst, &src,
> +                                                                             
>  &bh_process_pkt);
> +               }
>         }
>
>         bh_unlock_sock(sk);
>
> +       if (drop_pkt) {
> +               if (vmci_transport_send_reset_bh(&dst, &src, pkt) < 0)
> +                       pr_err("unable to send reset\n");
> +               goto out;
> +       }
> +
>         if (!bh_process_pkt) {
>                 struct vmci_transport_recv_pkt_info *recv_pkt_info;
>
> @@ -900,6 +914,7 @@ static void vmci_transport_recv_pkt_work(struct 
> work_struct *work)
>  {
>         struct vmci_transport_recv_pkt_info *recv_pkt_info;
>         struct vmci_transport_packet *pkt;
> +       struct sockaddr_vm src;
>         struct sock *sk;
>
>         recv_pkt_info =
> @@ -908,6 +923,12 @@ static void vmci_transport_recv_pkt_work(struct 
> work_struct *work)
>         pkt = &recv_pkt_info->pkt;
>
>         lock_sock(sk);
> +       vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
> +       if (sk->sk_state != TCP_LISTEN &&
> +           !vsock_check_source(vsock_sk(sk), &vmci_transport, &src)) {
> +               vmci_transport_reply_reset(pkt);
> +               goto out;
> +       }
>
>         /* The local context ID may be out of date. */
>         vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
> @@ -937,6 +958,7 @@ static void vmci_transport_recv_pkt_work(struct 
> work_struct *work)
>                 break;
>         }
>
> +out:
>         release_sock(sk);
>         kfree(recv_pkt_info);
>         /* Release reference obtained in the stream callback when we fetched

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to