aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/fix-vhost-user-socket-permission.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/fix-vhost-user-socket-permission.patch')
-rw-r--r--debian/patches/fix-vhost-user-socket-permission.patch365
1 files changed, 365 insertions, 0 deletions
diff --git a/debian/patches/fix-vhost-user-socket-permission.patch b/debian/patches/fix-vhost-user-socket-permission.patch
new file mode 100644
index 00000000..7cd188c5
--- /dev/null
+++ b/debian/patches/fix-vhost-user-socket-permission.patch
@@ -0,0 +1,365 @@
+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.
+
+*Update*
+ - the handling and lifecycle of this changed in Openvswitch 2.7 so we can no
+ more use internal_config.
+ - Also the upstreaming was aborted as that now clearly goes towards client
+ mode vhost sockets for this (and other issues).
+ - But until that is fully working we have to carry the workaround.
+ - Updated to work with Openvswitch 2.7 (and backward compatible to 2.6)
+
+Forwarded: yes
+Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Last-Update: 2017-05-23
+
+--- a/doc/guides/testpmd_app_ug/run_app.rst
++++ b/doc/guides/testpmd_app_ug/run_app.rst
+@@ -156,6 +156,25 @@
+
+ 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
+ ----------------------------
+--- a/lib/librte_eal/common/eal_common_options.c
++++ b/lib/librte_eal/common/eal_common_options.c
+@@ -95,6 +95,8 @@
+ {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 }
+ };
+
+--- a/lib/librte_eal/common/eal_options.h
++++ b/lib/librte_eal/common/eal_options.h
+@@ -83,6 +83,10 @@
+ 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
+ };
+
+--- a/lib/librte_eal/common/include/rte_eal.h
++++ b/lib/librte_eal/common/include/rte_eal.h
+@@ -256,6 +256,11 @@
+ #define RTE_INIT(func) \
+ static void __attribute__((constructor, used)) func(void)
+
++/**
++ * Set owner/permissions on sockets if requested on EAL commandline
++ */
++void rte_eal_set_socket_permissions(const char *);
++
+ #ifdef __cplusplus
+ }
+ #endif
+--- 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>
+@@ -117,6 +120,12 @@
+ /* internal configuration */
+ struct internal_config internal_config;
+
++/* workaround to be able to create the sockets under a certain set of
++ * owner/permissions as specified to EAL until solved upstream */
++static uid_t debian_vhost_sock_uid = (uid_t)-1;
++static gid_t debian_vhost_sock_gid = (gid_t)-1;
++static mode_t debian_vhost_sock_perm = 0;
++
+ /* used by rte_rdtsc() */
+ int rte_cycles_vmware_tsc_map;
+
+@@ -354,6 +363,8 @@
+ " --"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 ) {
+@@ -515,6 +526,121 @@
+ optarg = old_optarg;
+ }
+
++/* 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;
++}
++
+ /* Parse the argument given in the command line of the application */
+ static int
+ eal_parse_args(int argc, char **argv)
+@@ -611,6 +737,26 @@
+ internal_config.create_uio_dev = 1;
+ break;
+
++ case OPT_VHOST_OWNER_NUM:
++ if (get_owners_from_str(optarg, &debian_vhost_sock_uid,
++ &debian_vhost_sock_gid)) {
++ RTE_LOG(ERR, EAL,"vhost-user socket unable to get"
++ " specified user/group: %s\n", optarg);
++ debian_vhost_sock_uid = (uid_t)-1;
++ debian_vhost_sock_gid = (gid_t)-1;
++ }
++ else {
++ RTE_LOG(INFO, EAL,"socket owner specified as %s (%d:%d)\n",
++ optarg, debian_vhost_sock_uid, debian_vhost_sock_gid);
++ }
++ break;
++
++ case OPT_VHOST_PERM_NUM:
++ debian_vhost_sock_perm = (mode_t)strtoul(optarg, NULL, 0);
++ RTE_LOG(INFO, EAL,"socket perm specified as '%#o' from '%s'\n",
++ debian_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 +1089,47 @@
+ /* Module has been found */
+ return 1;
+ }
++
++static void
++vhost_set_permissions(const char *vhost_sock_location)
++{
++ int err = chmod(vhost_sock_location, debian_vhost_sock_perm);
++ if (err) {
++ RTE_LOG(ERR, EAL,"vhost-user socket cannot set"
++ " permissions to %#o (%s).\n",
++ debian_vhost_sock_perm, strerror(err));
++ return;
++ }
++ RTE_LOG(INFO, EAL,"Socket %s changed permissions"
++ " to %#o\n", vhost_sock_location,
++ debian_vhost_sock_perm);
++}
++
++static void
++vhost_set_ownership(const char *vhost_sock_location)
++{
++ int err = chown(vhost_sock_location, debian_vhost_sock_uid, debian_vhost_sock_gid);
++ if (err) {
++ RTE_LOG(ERR, EAL,"vhost-user socket unable to set"
++ " ownership to %d:%d (%s).\n",
++ debian_vhost_sock_uid, debian_vhost_sock_gid,
++ strerror(err));
++ return;
++ }
++
++ RTE_LOG(INFO, EAL,"Socket %s changed ownership"
++ " to %d:%d.\n", vhost_sock_location,
++ debian_vhost_sock_uid, debian_vhost_sock_gid);
++}
++
++void
++rte_eal_set_socket_permissions(const char *path)
++{
++ if (debian_vhost_sock_perm != 0) {
++ vhost_set_permissions(path);
++ }
++
++ if (debian_vhost_sock_uid != (uid_t)-1 || debian_vhost_sock_gid != (gid_t)-1) {
++ vhost_set_ownership(path);
++ }
++}
+--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
++++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+@@ -139,6 +139,7 @@
+ rte_keepalive_register_core;
+ rte_xen_dom0_supported;
+ rte_xen_mem_phy2mch;
++ rte_eal_set_socket_permissions;
+
+ } DPDK_2.1;
+
+--- a/lib/librte_vhost/socket.c
++++ b/lib/librte_vhost/socket.c
+@@ -78,6 +78,8 @@
+ 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);
+@@ -519,6 +521,7 @@
+ vsocket->is_server = true;
+ ret = vhost_user_create_server(vsocket);
+ }
++ rte_eal_set_socket_permissions(path);
+ if (ret < 0) {
+ free(vsocket->path);
+ free(vsocket);