Drop ubuntu prefix from patches
[deb_dpdk.git] / debian / patches / fix-vhost-user-socket-permission.patch
diff --git a/debian/patches/fix-vhost-user-socket-permission.patch b/debian/patches/fix-vhost-user-socket-permission.patch
new file mode 100644 (file)
index 0000000..ab3d632
--- /dev/null
@@ -0,0 +1,371 @@
+Description: eal: provide option to set vhost_user socket owner/permissions
+
+The API doesn't hold a way to specify a owner/permission set for vhost_user
+created sockets.
+
+Projects consuming DPDK started to do 'their own workarounds' like openvswitch
+https://patchwork.ozlabs.org/patch/559043/
+https://patchwork.ozlabs.org/patch/559045/
+But for this specific example they are blocked/stalled behind a bigger
+rework (https://patchwork.ozlabs.org/patch/604898/).
+
+We need something now for existing code linking against DPDK. That implies to
+avoid changing API/ABI. So I created a DPDK EAL commandline option based ideas
+in the former patches.
+
+Fixes LP: #1546565
+
+*Update*
+ - with the split libs it now nees to be listed in
+   lib/librte_eal/linuxapp/eal/rte_eal_version.map to work on link steps
+ - please note that upstream gravitates towards not extending but creating a
+   new the API in DPDK as long term solution (will take a while)
+ - also as listed before most affected projects seem to create their own
+   workaround.
+ So over time we have to check when we can drop it at the price of a config
+ transition - likely OVS 2.6 won't need it anymore.
+
+Forwarded: yes
+Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Last-Update: 2016-07-25
+
+diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst
+index 7712bd2..28776b9 100644
+--- a/doc/guides/testpmd_app_ug/run_app.rst
++++ b/doc/guides/testpmd_app_ug/run_app.rst
+@@ -156,6 +156,25 @@ See the DPDK Getting Started Guides for more information on these options.
+     Use malloc instead of hugetlbfs.
++*   ``--vhost-owner``
++
++     When creating vhost_user sockets change owner and group to the specified value.
++     This can be given as ``user:group``, but also only ``user`` or ``:group`` are supported.
++
++    Examples::
++
++       --vhost-owner 'libvirt-qemu:kvm'
++       --vhost-owner 'libvirt-qemu'
++       --vhost-owner ':kvm'
++
++*   ``--vhost-perm``
++
++    When creating vhost_user sockets set them up with these permissions.
++
++    For example::
++
++       --vhost-perm '0664'
++
+ Testpmd Command-line Options
+ ----------------------------
+diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
+index 481c732..2126140 100644
+--- a/lib/librte_eal/common/eal_common_options.c
++++ b/lib/librte_eal/common/eal_common_options.c
+@@ -95,6 +95,8 @@ eal_long_options[] = {
+       {OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
+       {OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
+       {OPT_XEN_DOM0,          0, NULL, OPT_XEN_DOM0_NUM         },
++      {OPT_VHOST_OWNER,       1, NULL, OPT_VHOST_OWNER_NUM      },
++      {OPT_VHOST_PERM,        1, NULL, OPT_VHOST_PERM_NUM       },
+       {0,                     0, NULL, 0                        }
+ };
+@@ -166,6 +168,8 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
+ #endif
+       internal_cfg->vmware_tsc_map = 0;
+       internal_cfg->create_uio_dev = 0;
++      internal_cfg->vhost_sock_owner = NULL;
++      internal_cfg->vhost_sock_perm = NULL;
+ }
+ static int
+diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
+index 5f1367e..bdf34e3 100644
+--- a/lib/librte_eal/common/eal_internal_cfg.h
++++ b/lib/librte_eal/common/eal_internal_cfg.h
+@@ -83,6 +83,8 @@ struct internal_config {
+       volatile enum rte_intr_mode vfio_intr_mode;
+       const char *hugefile_prefix;      /**< the base filename of hugetlbfs files */
+       const char *hugepage_dir;         /**< specific hugetlbfs directory to use */
++      const char *vhost_sock_owner;     /**< owner:group of vhost_user sockets */
++      const char *vhost_sock_perm;      /**< permissions of vhost_user sockets */
+       unsigned num_hugepage_sizes;      /**< how many sizes on this system */
+       struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES];
+diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
+index a881c62..1161083 100644
+--- a/lib/librte_eal/common/eal_options.h
++++ b/lib/librte_eal/common/eal_options.h
+@@ -83,6 +83,10 @@ enum {
+       OPT_VMWARE_TSC_MAP_NUM,
+ #define OPT_XEN_DOM0          "xen-dom0"
+       OPT_XEN_DOM0_NUM,
++#define OPT_VHOST_OWNER       "vhost-owner"
++      OPT_VHOST_OWNER_NUM,
++#define OPT_VHOST_PERM        "vhost-perm"
++      OPT_VHOST_PERM_NUM,
+       OPT_LONG_MAX_NUM
+ };
+diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
+index a71d6f5..506cf24 100644
+--- a/lib/librte_eal/common/include/rte_eal.h
++++ b/lib/librte_eal/common/include/rte_eal.h
+@@ -252,6 +252,11 @@ static inline int rte_gettid(void)
+       return RTE_PER_LCORE(_thread_id);
+ }
++/**
++ * Set owner/permissions on sockets if requested on EAL commandline
++ */
++void rte_eal_set_socket_permissions(const char *);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
+index 3fb2188..dc84c5b 100644
+--- a/lib/librte_eal/linuxapp/eal/eal.c
++++ b/lib/librte_eal/linuxapp/eal/eal.c
+@@ -53,6 +53,9 @@
+ #if defined(RTE_ARCH_X86)
+ #include <sys/io.h>
+ #endif
++#include <sys/types.h>
++#include <pwd.h>
++#include <grp.h>
+ #include <rte_common.h>
+ #include <rte_debug.h>
+@@ -344,6 +347,8 @@ eal_usage(const char *prgname)
+              "  --"OPT_CREATE_UIO_DEV"    Create /dev/uioX (usually done by hotplug)\n"
+              "  --"OPT_VFIO_INTR"         Interrupt mode for VFIO (legacy|msi|msix)\n"
+              "  --"OPT_XEN_DOM0"          Support running on Xen dom0 without hugetlbfs\n"
++             "  --"OPT_VHOST_OWNER"       Create vhost-user sockets with this owner:group\n"
++             "  --"OPT_VHOST_PERM"        Create vhost-user sockets with these permissions\n"
+              "\n");
+       /* Allow the application to print its usage message too if hook is set */
+       if ( rte_application_usage_hook ) {
+@@ -601,6 +606,14 @@ eal_parse_args(int argc, char **argv)
+                       internal_config.create_uio_dev = 1;
+                       break;
++              case OPT_VHOST_OWNER_NUM:
++                      internal_config.vhost_sock_owner = optarg;
++                      break;
++
++              case OPT_VHOST_PERM_NUM:
++                      internal_config.vhost_sock_perm = optarg;
++                      break;
++
+               default:
+                       if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
+                               RTE_LOG(ERR, EAL, "Option %c is not supported "
+@@ -943,3 +956,172 @@ rte_eal_check_module(const char *module_name)
+       /* Module has been found */
+       return 1;
+ }
++
++/* Try to double the size of '*buf', return true
++ * if successful, and '*sizep' will be updated with
++ * the new size. Otherwise, return false.  */
++static int
++enlarge_buffer(char **buf, size_t *sizep)
++{
++    size_t newsize = *sizep * 2;
++
++    if (newsize > *sizep) {
++        *buf = realloc(*buf, newsize);
++        *sizep = newsize;
++        return 1;
++    }
++
++    return 0;
++}
++
++static int
++get_owners_from_str(const char *user_spec, uid_t *uid, gid_t *gid)
++{
++      size_t bufsize = 4096;
++
++      char *pos = strchr(user_spec, ':');
++      user_spec += strspn(user_spec, " \t\r\n");
++      size_t len = pos ? (size_t)(pos - user_spec) : strlen(user_spec);
++
++      char *buf = NULL;
++      struct passwd pwd, *res;
++      int e;
++
++      buf = malloc(bufsize);
++      char *user_search = NULL;
++      if (len) {
++              user_search = malloc(len + 1);
++              memcpy(user_search, user_spec, len);
++              user_search[len] = '\0';
++              while ((e = getpwnam_r(user_search, &pwd, buf, bufsize, &res)) == ERANGE) {
++                      if (!enlarge_buffer(&buf, &bufsize)) {
++                              break;
++                      }
++              }
++
++              if (e != 0) {
++                      RTE_LOG(ERR, EAL,"Failed to retrive user %s's uid (%s), aborting.",
++                              user_search, strerror(e));
++                      goto release;
++              }
++              if (res == NULL) {
++                      RTE_LOG(ERR, EAL,"user %s not found,  aborting.",
++                              user_search);
++                      e = -1;
++                      goto release;
++              }
++      } else {
++              /* User name is not specified, use current user.  */
++              while ((e = getpwuid_r(getuid(), &pwd, buf, bufsize, &res)) == ERANGE) {
++                      if (!enlarge_buffer(&buf, &bufsize)) {
++                              break;
++                      }
++              }
++
++              if (e != 0) {
++                      RTE_LOG(ERR, EAL,"Failed to retrive current user's uid "
++                              "(%s), aborting.", strerror(e));
++                      goto release;
++              }
++              user_search = strdup(pwd.pw_name);
++      }
++
++      if (uid)
++              *uid = pwd.pw_uid;
++
++      free(buf);
++      buf = NULL;
++
++      if (pos) {
++              char *grpstr = pos + 1;
++              grpstr += strspn(grpstr, " \t\r\n");
++
++              if (*grpstr) {
++                      struct group grp, *res;
++
++                      bufsize = 4096;
++                      buf = malloc(bufsize);
++                      while ((e = getgrnam_r(grpstr, &grp, buf, bufsize, &res))
++                                       == ERANGE) {
++                              if (!enlarge_buffer(&buf, &bufsize)) {
++                                      break;
++                              }
++                      }
++
++                      if (e) {
++                              RTE_LOG(ERR, EAL,"Failed to get group entry for %s, "
++                                      "(%s), aborting.", grpstr,
++                                      strerror(e));
++                              goto release;
++                      }
++                      if (res == NULL) {
++                              RTE_LOG(ERR, EAL,"Group %s not found, aborting.",
++                                      grpstr);
++                              e = -1;
++                              goto release;
++                      }
++
++                      if (gid)
++                              *gid = grp.gr_gid;
++              }
++      }
++
++ release:
++      free(buf);
++      free(user_search);
++      return e;
++}
++
++static void
++vhost_set_permissions(const char *vhost_sock_location)
++{
++      unsigned long int mode = strtoul(internal_config.vhost_sock_perm, NULL, 0);
++      int err = chmod(vhost_sock_location, (mode_t)mode);
++      if (err) {
++              RTE_LOG(ERR, EAL,"vhost-user socket cannot set"
++                      " permissions to %s (%s).\n",
++                      internal_config.vhost_sock_perm, strerror(err));
++              return;
++      }
++      RTE_LOG(INFO, EAL,"Socket %s changed permissions"
++                      " to %s\n", vhost_sock_location,
++                      internal_config.vhost_sock_perm);
++}
++
++static void
++vhost_set_ownership(const char *vhost_sock_location)
++{
++      uid_t vhuid=0;
++      gid_t vhgid=0;
++
++      if (get_owners_from_str(internal_config.vhost_sock_owner, &vhuid, &vhgid)) {
++              RTE_LOG(ERR, EAL,"vhost-user socket unable to get"
++                      " specified user/group: %s\n",
++                      internal_config.vhost_sock_owner);
++              return;
++      }
++
++      int err = chown(vhost_sock_location, vhuid, vhgid);
++      if (err) {
++              RTE_LOG(ERR, EAL,"vhost-user socket unable to set"
++                      " ownership to %s (%s).\n",
++                      internal_config.vhost_sock_owner, strerror(err));
++              return;
++      }
++
++      RTE_LOG(INFO, EAL,"Socket %s changed ownership"
++                      " to %s.\n", vhost_sock_location,
++                      internal_config.vhost_sock_owner);
++}
++
++void
++rte_eal_set_socket_permissions(const char *path)
++{
++      if (internal_config.vhost_sock_perm) {
++              vhost_set_permissions(path);
++      }
++
++      if (internal_config.vhost_sock_owner) {
++              vhost_set_ownership(path);
++      }
++}
+diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+index db8c984..bb92e57 100644
+--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
++++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+@@ -139,6 +139,7 @@ DPDK_2.2 {
+       rte_keepalive_register_core;
+       rte_xen_dom0_supported;
+       rte_xen_mem_phy2mch;
++      rte_eal_set_socket_permissions;
+ } DPDK_2.1;
+diff --git a/lib/librte_vhost/vhost_user/vhost-net-user.c b/lib/librte_vhost/vhost_user/vhost-net-user.c
+index b35594d..dbdb8ad 100644
+--- a/lib/librte_vhost/vhost_user/vhost-net-user.c
++++ b/lib/librte_vhost/vhost_user/vhost-net-user.c
+@@ -79,6 +79,8 @@ struct vhost_user {
+       pthread_mutex_t mutex;
+ };
++#include <rte_eal.h>
++
+ #define MAX_VIRTIO_BACKLOG 128
+ static void vhost_user_server_new_connection(int fd, void *data, int *remove);
+@@ -682,6 +684,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
+       if (!vsocket)
+               goto out;
+       memset(vsocket, 0, sizeof(struct vhost_user_socket));
++      rte_eal_set_socket_permissions(path);
+       vsocket->path = strdup(path);
+       vsocket->connfd = -1;