diff options
Diffstat (limited to 'debian/patches/fix-vhost-user-socket-permission.patch')
-rw-r--r-- | debian/patches/fix-vhost-user-socket-permission.patch | 371 |
1 files changed, 371 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..ab3d6322 --- /dev/null +++ b/debian/patches/fix-vhost-user-socket-permission.patch @@ -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; + |