Expose VIRTIO_VSOCK_F_DGRAM in the vhost feature bitmap and retain the negotiated value for each guest. Keep datagrams disabled until the feature is negotiated. Use a vhost-specific datagram destination check to look up the guest in the socket's network namespace and require its negotiated datagram feature. The common virtio implementation supplies the bind and message operations; destination validation remains in connect() and sendmsg(), where the remote CID is available. Signed-off-by: Sergio Lopez --- drivers/vhost/vsock.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 0cb87971d749..eb2fbdb721aa 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -32,7 +32,8 @@ static const int vhost_vsock_bits[] = { VHOST_FEATURES, VIRTIO_F_ACCESS_PLATFORM, - VIRTIO_VSOCK_F_SEQPACKET + VIRTIO_VSOCK_F_SEQPACKET, + VIRTIO_VSOCK_F_DGRAM, }; #define VHOST_VSOCK_FEATURES VHOST_FEATURES_U64(vhost_vsock_bits, 0) @@ -62,6 +63,7 @@ struct vhost_vsock { u32 guest_cid; bool seqpacket_allow; bool ever_started; /* set on first SET_RUNNING(1); never cleared */ + bool dgram_allow; }; static u32 vhost_transport_get_local_cid(void) @@ -436,6 +438,8 @@ static bool vhost_transport_msgzerocopy_allow(void) static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk, u32 remote_cid); +static bool vhost_transport_dgram_allow(struct vsock_sock *vsk, + u32 cid, u32 port); static bool vhost_transport_stream_allow(struct vsock_sock *vsk, u32 cid, u32 port) @@ -460,7 +464,7 @@ static struct virtio_transport vhost_transport = { .dgram_enqueue = virtio_transport_dgram_enqueue, .dgram_dequeue = virtio_transport_dgram_dequeue, .dgram_bind = virtio_transport_dgram_bind, - .dgram_allow = virtio_transport_dgram_allow, + .dgram_allow = vhost_transport_dgram_allow, .stream_enqueue = virtio_transport_stream_enqueue, .stream_dequeue = virtio_transport_stream_dequeue, @@ -516,6 +520,24 @@ static bool vhost_transport_seqpacket_allow(struct vsock_sock *vsk, return seqpacket_allow; } +static bool vhost_transport_dgram_allow(struct vsock_sock *vsk, + u32 cid, u32 port) +{ + struct net *net = sock_net(sk_vsock(vsk)); + struct vhost_vsock *vsock; + bool dgram_allow = false; + + rcu_read_lock(); + vsock = vhost_vsock_get(cid, net); + + if (vsock) + dgram_allow = vsock->dgram_allow; + + rcu_read_unlock(); + + return dgram_allow; +} + static void vhost_vsock_handle_tx_kick(struct vhost_work *work) { struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, @@ -737,6 +759,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file) vsock->guest_cid = 0; /* no CID assigned yet */ vsock->seqpacket_allow = false; vsock->ever_started = false; + vsock->dgram_allow = false; atomic_set(&vsock->queued_replies, 0); @@ -890,6 +913,7 @@ static int vhost_vsock_set_features(struct vhost_vsock *vsock, u64 features) } vsock->seqpacket_allow = features & (1ULL << VIRTIO_VSOCK_F_SEQPACKET); + vsock->dgram_allow = features & (1ULL << VIRTIO_VSOCK_F_DGRAM); for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) { vq = &vsock->vqs[i]; -- 2.56.0