Advertise VIRTIO_VSOCK_F_DGRAM and record whether the device
negotiated it. Gate datagram socket initialization and destination
checks on the negotiated feature and the transport's supported network
namespace mode.

Perform device capability checks at socket creation without requiring
a remote address, which is not yet known for an unconnected datagram
socket. The common virtio implementation provides the datagram data
path.

Signed-off-by: Sergio Lopez <[email protected]>
---
 net/vmw_vsock/virtio_transport.c | 42 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
index 4f9aa9c4c3aa..762e77895f28 100644
--- a/net/vmw_vsock/virtio_transport.c
+++ b/net/vmw_vsock/virtio_transport.c
@@ -57,6 +57,7 @@ struct virtio_vsock {
 
        u32 guest_cid;
        bool seqpacket_allow;
+       bool dgram_allow;
 
        /* These fields are used only in tx path in function
         * 'virtio_transport_send_pkt_work()', so to save
@@ -547,6 +548,18 @@ bool virtio_transport_stream_allow(struct vsock_sock *vsk, 
u32 cid, u32 port)
 
 static bool virtio_transport_seqpacket_allow(struct vsock_sock *vsk,
                                             u32 remote_cid);
+static bool virtio_transport_dgram_allow_check(struct vsock_sock *vsk,
+                                              u32 cid, u32 port);
+
+static int virtio_transport_socket_init(struct vsock_sock *vsk,
+                                       struct vsock_sock *psk)
+{
+       if (sk_vsock(vsk)->sk_type == SOCK_DGRAM &&
+           !virtio_transport_dgram_allow_check(vsk, 0, 0))
+               return -ESOCKTNOSUPPORT;
+
+       return virtio_transport_do_socket_init(vsk, psk);
+}
 
 static bool virtio_transport_has_remote_cid(struct vsock_sock *vsk, u32 cid)
 {
@@ -561,7 +574,7 @@ static struct virtio_transport virtio_transport = {
                .get_local_cid            = virtio_transport_get_local_cid,
                .has_remote_cid           = virtio_transport_has_remote_cid,
 
-               .init                     = virtio_transport_do_socket_init,
+               .init                     = virtio_transport_socket_init,
                .destruct                 = virtio_transport_destruct,
                .release                  = virtio_transport_release,
                .connect                  = virtio_transport_connect,
@@ -571,7 +584,7 @@ static struct virtio_transport virtio_transport = {
                .dgram_bind               = virtio_transport_dgram_bind,
                .dgram_dequeue            = virtio_transport_dgram_dequeue,
                .dgram_enqueue            = virtio_transport_dgram_enqueue,
-               .dgram_allow              = virtio_transport_dgram_allow,
+               .dgram_allow              = virtio_transport_dgram_allow_check,
 
                .stream_dequeue           = virtio_transport_stream_dequeue,
                .stream_enqueue           = virtio_transport_stream_enqueue,
@@ -629,6 +642,25 @@ virtio_transport_seqpacket_allow(struct vsock_sock *vsk, 
u32 remote_cid)
        return seqpacket_allow;
 }
 
+static bool
+virtio_transport_dgram_allow_check(struct vsock_sock *vsk, u32 cid, u32 port)
+{
+       struct virtio_vsock *vsock;
+       bool dgram_allow;
+
+       if (!vsock_net_mode_global(vsk))
+               return false;
+
+       dgram_allow = false;
+       rcu_read_lock();
+       vsock = rcu_dereference(the_virtio_vsock);
+       if (vsock)
+               dgram_allow = vsock->dgram_allow;
+       rcu_read_unlock();
+
+       return dgram_allow;
+}
+
 static void virtio_transport_rx_work(struct work_struct *work)
 {
        struct virtio_vsock *vsock =
@@ -835,6 +867,9 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
        if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_SEQPACKET))
                vsock->seqpacket_allow = true;
 
+       if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_DGRAM))
+               vsock->dgram_allow = true;
+
        vdev->priv = vsock;
 
        ret = virtio_vsock_vqs_init(vsock);
@@ -932,7 +967,8 @@ static struct virtio_device_id id_table[] = {
 };
 
 static unsigned int features[] = {
-       VIRTIO_VSOCK_F_SEQPACKET
+       VIRTIO_VSOCK_F_SEQPACKET,
+       VIRTIO_VSOCK_F_DGRAM,
 };
 
 static struct virtio_driver virtio_vsock_driver = {

-- 
2.56.0


Reply via email to