On Tue, Sep 15, 2026 at 05:47:02PM +0200, Stefano Garzarella wrote:
> On Wed, Sep 02, 2026 at 04:00:49PM -0700, Bobby Eshleman wrote:
> > From: Bobby Eshleman <[email protected]>
> > 
> > virtio-vsock did not have namespace support (the device was always
> > accessible to any global namespace).
> > 
> > Make the virtio-vsock device assignable to a namespace and initialize it
> > to init_net. Because virtio-vsock and init_net are both hardcoded to
> > global mode, nothing changes until the assign ioctl is issued.
> > 
> > When the device's local-mode namespace is being destroyed, received
> > packets are reset until new valid a namespace has been assigned and/or
> > automatically returned to, and the next RX batch begins (in
> > virtio_transport_rx_work). They are reset rather than dropped because
> > vsock does not retransmit, so a silent drop would leave the host waiting
> > for a timeout, and a connection request arriving in that window has no
> > socket whose teardown would tell it otherwise. This requires making
> > virtio_transport_reset_no_sock() available outside of the common code.
> > 
> > When a device is assigned to a namespace, every already established
> > vsock socket that is no longer able to reach the device is forcibly
> > reset. For that reason, adding new sockets to the connected table must
> > be performed atomically with regards to namespace assignment. This
> > ensures that when the socket is added to the connected table that it
> > actually passes the new reachability conditions set by ns assignment. If
> > it wins the race to the table and does NOT pass the reachability tests,
> > then the reset sweep will correctly catch it. This is the purpose
> > of the new helper 'vsock_maybe_set_connected()'.
> > 
> > Signed-off-by: Bobby Eshleman <[email protected]>
> > ---
> > include/linux/virtio_vsock.h            |  2 ++
> > net/vmw_vsock/virtio_transport.c        | 28 ++++++++++++++++++++++------
> > net/vmw_vsock/virtio_transport_common.c | 28 +++++++++++++++++++++-------
> > 3 files changed, 45 insertions(+), 13 deletions(-)
> > 
> > diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
> > index f91704731057..9c68ce1d7fb4 100644
> > --- a/include/linux/virtio_vsock.h
> > +++ b/include/linux/virtio_vsock.h
> > @@ -286,6 +286,8 @@ void virtio_transport_inc_tx_pkt(struct 
> > virtio_vsock_sock *vvs, struct sk_buff *
> > u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 wanted);
> > void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit);
> > void virtio_transport_deliver_tap_pkt(struct sk_buff *skb);
> > +int virtio_transport_reset_no_sock(const struct virtio_transport *t,
> > +                              struct sk_buff *skb, struct net *net);
> > int virtio_transport_purge_skbs(void *vsk, struct sk_buff_head *list);
> > int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t 
> > read_actor);
> > int virtio_transport_notify_set_rcvlowat(struct vsock_sock *vsk, int val);
> > diff --git a/net/vmw_vsock/virtio_transport.c 
> > b/net/vmw_vsock/virtio_transport.c
> > index 4f9aa9c4c3aa..a453a4f828dc 100644
> > --- a/net/vmw_vsock/virtio_transport.c
> > +++ b/net/vmw_vsock/virtio_transport.c
> > @@ -540,9 +540,14 @@ static bool virtio_transport_msgzerocopy_allow(void)
> >     return true;
> > }
> > 
> > +static bool virtio_transport_netns_assign_allow(void)
> > +{
> > +   return true;
> > +}
> > +
> > bool virtio_transport_stream_allow(struct vsock_sock *vsk, u32 cid, u32 
> > port)
> > {
> > -   return vsock_net_mode_global(vsk);
> > +   return vsock_g2h_net_reachable(sock_net(sk_vsock(vsk)));
> > }
> > 
> > static bool virtio_transport_seqpacket_allow(struct vsock_sock *vsk,
> > @@ -587,6 +592,7 @@ static struct virtio_transport virtio_transport = {
> >             .seqpacket_has_data       = virtio_transport_seqpacket_has_data,
> > 
> >             .msgzerocopy_allow        = virtio_transport_msgzerocopy_allow,
> > +           .netns_assign_allow       = virtio_transport_netns_assign_allow,
> > 
> >             .notify_poll_in           = virtio_transport_notify_poll_in,
> >             .notify_poll_out          = virtio_transport_notify_poll_out,
> > @@ -616,7 +622,7 @@ virtio_transport_seqpacket_allow(struct vsock_sock 
> > *vsk, u32 remote_cid)
> >     struct virtio_vsock *vsock;
> >     bool seqpacket_allow;
> > 
> > -   if (!vsock_net_mode_global(vsk))
> > +   if (!vsock_g2h_net_reachable(sock_net(sk_vsock(vsk))))
> >             return false;
> > 
> >     seqpacket_allow = false;
> > @@ -634,6 +640,9 @@ static void virtio_transport_rx_work(struct work_struct 
> > *work)
> >     struct virtio_vsock *vsock =
> >             container_of(work, struct virtio_vsock, rx_work);
> >     struct virtqueue *vq;
> > +   struct net *net;
> > +
> > +   net = vsock_g2h_net_get();
> > 
> >     mutex_lock(&vsock->rx_lock);
> > 
> > @@ -682,10 +691,14 @@ static void virtio_transport_rx_work(struct 
> > work_struct *work)
> > 
> >                     virtio_transport_deliver_tap_pkt(skb);
> > 
> > -                   /* Force virtio-transport into global mode since it
> > -                    * does not yet support local-mode namespacing.
> > -                    */
> > -                   virtio_transport_recv_pkt(&virtio_transport, skb, NULL);
> > +                   if (unlikely(!net)) {
> > +                           virtio_transport_reset_no_sock(
> > +                                   &virtio_transport, skb, &init_net);
> 
> Why init_net?

This parameter is actually unused by virtio_transport_reset_no_sock(),
its call to virtio_transport_send_pkt(), and even the eventual call to
virtio_transport_deliver_tap_pkt()... so maybe NULL w/ a comment would
be better?

> 
> > +                           kfree_skb(skb);
> > +                           continue;
> > +                   }
> > +
> > +                   virtio_transport_recv_pkt(&virtio_transport, skb, net);
> >             }
> >     } while (!virtqueue_enable_cb(vq));
> > 
> > @@ -694,6 +707,9 @@ static void virtio_transport_rx_work(struct work_struct 
> > *work)
> >             virtio_vsock_rx_fill(vsock);
> > out_nofill:
> >     mutex_unlock(&vsock->rx_lock);
> > +
> > +   if (net)
> > +           put_net(net);
> 
> put_net() should handle NULL net, right?

It does, and somehow I forgot that.

Thanks,
Bobby

Reply via email to