The current DPDK vhost socket user and group permissions are derived
during creation from the DPDK library. This patch adds an action, post
socket creation, to change the socket permissions and ownership to
support multi-user systems.

This is especially useful when using vhost-user sockets from qemu, which
currently requires manual intervention to change the vhost-user sockets
allowing the qemu user access.

Signed-off-by: Aaron Conole <acon...@redhat.com>
---
 INSTALL.DPDK.md   | 17 +++++++++++++++
 lib/netdev-dpdk.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/INSTALL.DPDK.md b/INSTALL.DPDK.md
index b9d92d0..86f934c 100644
--- a/INSTALL.DPDK.md
+++ b/INSTALL.DPDK.md
@@ -554,6 +554,23 @@ have arbitrary names.
 
     `./vswitchd/ovs-vsctl set Open_vSwitch . other_config:vhost_sock_dir=path`
 
+  - You may specify optional user:group and permissions for the vhost-user
+    sockets. If these are not present, the default ownership is the executing
+    user and group for ovs-vswitchd, and the default permissions are `0600`.
+
+    To change the vhost-user ownership, you may modify the `vhost_sock_owners`
+    entry in the ovsdb like:
+
+    `./vswitchd/ovs-vsctl set Open_vSwitch . \
+                          other_config:vhost_sock_owners=[user][:group]`
+
+    To change the vhost-user permissions, you may modify the octal value
+    `vhost_sock_permissions` entry in the ovsdb like:
+
+    `./vswitchd/ovs-vsctl set Open_vSwitch . \
+                          other_config:vhost_sock_permissions=permissions`
+
+
 DPDK vhost-user VM configuration:
 ---------------------------------
 Follow the steps below to attach vhost-user port(s) to a VM.
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 696430f..ee59250 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -52,6 +52,7 @@
 #include "openvswitch/vlog.h"
 #include "smap.h"
 #include "vswitch-idl.h"
+#include "daemon.h"
 
 #include "rte_config.h"
 #include "rte_mbuf.h"
@@ -106,6 +107,9 @@ BUILD_ASSERT_DECL((MAX_NB_MBUF / 
ROUND_DOWN_POW2(MAX_NB_MBUF/MIN_NB_MBUF))
 
 static char *cuse_dev_name = NULL;    /* Character device cuse_dev_name. */
 static char *vhost_sock_dir = NULL;   /* Location of vhost-user sockets */
+static char *vhost_sock_owner = NULL; /* user:group notation for ownership
+                                         of vhost-user sockets */
+static char *vhost_sock_perms = NULL; /* OCTAL string of permission bits */
 
 /*
  * Maximum amount of time in micro seconds to try and enqueue to vhost.
@@ -682,6 +686,43 @@ netdev_dpdk_vhost_cuse_construct(struct netdev *netdev_)
     return err;
 }
 
+static void
+vhost_set_permissions(const char *vhost_sock_location)
+{
+    unsigned long int mode = strtoul(vhost_sock_perms, NULL, 0);
+    int err = chmod(vhost_sock_location, (mode_t)mode);
+    if (err) {
+        VLOG_ERR("vhost-user socket cannot set permissions to %s (%s).\n",
+                 vhost_sock_perms, ovs_strerror(err));
+        return;
+    }
+    VLOG_INFO("Socket %s changed permissions to %s\n", vhost_sock_location,
+              vhost_sock_perms);
+}
+
+static void
+vhost_set_ownership(const char *vhost_sock_location)
+{
+    uid_t vhuid;
+    gid_t vhgid;
+
+    if (get_owners_from_str(vhost_sock_owner, &vhuid, NULL, &vhgid, false)) {
+        VLOG_ERR("vhost-user socket unable to set ownership: %s\n",
+                 vhost_sock_owner);
+        return;
+    }
+
+    int err = chown(vhost_sock_location, vhuid, vhgid);
+    if (err) {
+        VLOG_ERR("vhost-user socket unable to set ownership to %s (%s).\n",
+                 vhost_sock_owner, ovs_strerror(err));
+        return;
+    }
+
+    VLOG_INFO("Socket %s changed ownership to %s.\n", vhost_sock_location,
+              vhost_sock_owner);
+}
+
 static int
 netdev_dpdk_vhost_user_construct(struct netdev *netdev_)
 {
@@ -700,6 +741,15 @@ netdev_dpdk_vhost_user_construct(struct netdev *netdev_)
                  netdev->vhost_id);
     }
     VLOG_INFO("Socket %s created for vhost-user port %s\n", netdev->vhost_id, 
netdev_->name);
+
+    if (vhost_sock_perms) {
+        vhost_set_permissions(netdev->vhost_id);
+    }
+
+    if (vhost_sock_owner) {
+        vhost_set_ownership(netdev->vhost_id);
+    }
+
     err = vhost_construct_helper(netdev_);
     ovs_mutex_unlock(&dpdk_mutex);
     return err;
@@ -2217,12 +2267,16 @@ __dpdk_init(const struct ovsrec_open_vswitch *ovs_cfg)
 
     VLOG_INFO("DPDK Enabled, initializing");
 
-#ifdef VHOST_CUSE
     if (process_vhost_flags("cuse_dev_name", strdup("vhost-net"),
                             PATH_MAX, ovs_cfg, &cuse_dev_name)) {
-#else
+        /**
+         * This is ignored when vhost_user anyway...
+         */
+    }
+
     if (process_vhost_flags("vhost_sock_dir", strdup(ovs_rundir()),
                             NAME_MAX, ovs_cfg, &vhost_sock_dir)) {
+#ifndef VHOST_CUSE
         struct stat s;
 
         err = stat(vhost_sock_dir, &s);
@@ -2233,6 +2287,11 @@ __dpdk_init(const struct ovsrec_open_vswitch *ovs_cfg)
 #endif
     }
 
+    (void)process_vhost_flags("vhost_sock_owners", NULL, NAME_MAX, ovs_cfg,
+                              &vhost_sock_owner);
+    (void)process_vhost_flags("vhost_sock_permissions", "0600", NAME_MAX,
+                              ovs_cfg, &vhost_sock_perms);
+    
     /* Get the main thread affinity */
     CPU_ZERO(&cpuset);
     err = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
-- 
2.6.1.133.gf5b6079

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to