1 Description: eal: provide option to set vhost_user socket owner/permissions
3 The API doesn't hold a way to specify a owner/permission set for vhost_user
6 Projects consuming DPDK started to do 'their own workarounds' like openvswitch
7 https://patchwork.ozlabs.org/patch/559043/
8 https://patchwork.ozlabs.org/patch/559045/
9 But for this specific example they are blocked/stalled behind a bigger
10 rework (https://patchwork.ozlabs.org/patch/604898/).
12 We need something now for existing code linking against DPDK. That implies to
13 avoid changing API/ABI. So I created a DPDK EAL commandline option based ideas
14 in the former patches.
19 - with the split libs it now nees to be listed in
20 lib/librte_eal/linuxapp/eal/rte_eal_version.map to work on link steps
21 - please note that upstream gravitates towards not extending but creating a
22 new the API in DPDK as long term solution (will take a while)
23 - also as listed before most affected projects seem to create their own
25 So over time we have to check when we can drop it at the price of a config
26 transition - likely OVS 2.6 won't need it anymore.
29 - the handling and lifecycle of this changed in Openvswitch 2.7 so we can no
30 more use internal_config.
31 - Also the upstreaming was aborted as that now clearly goes towards client
32 mode vhost sockets for this (and other issues).
33 - But until that is fully working we have to carry the workaround.
34 - Updated to work with Openvswitch 2.7 (and backward compatible to 2.6)
37 - in 17.05 the patch now needs to be hooked up on a different place in vhost
39 - also the former rebase dropped a create socket call which is now restored
42 Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
43 Last-Update: 2017-08-23
45 --- a/doc/guides/testpmd_app_ug/run_app.rst
46 +++ b/doc/guides/testpmd_app_ug/run_app.rst
47 @@ -156,6 +156,25 @@ See the DPDK Getting Started Guides for
49 Use malloc instead of hugetlbfs.
53 + When creating vhost_user sockets change owner and group to the specified value.
54 + This can be given as ``user:group``, but also only ``user`` or ``:group`` are supported.
58 + --vhost-owner 'libvirt-qemu:kvm'
59 + --vhost-owner 'libvirt-qemu'
60 + --vhost-owner ':kvm'
64 + When creating vhost_user sockets set them up with these permissions.
71 Testpmd Command-line Options
72 ----------------------------
73 --- a/lib/librte_eal/common/eal_common_options.c
74 +++ b/lib/librte_eal/common/eal_common_options.c
75 @@ -98,6 +98,8 @@ eal_long_options[] = {
76 {OPT_VDEV, 1, NULL, OPT_VDEV_NUM },
77 {OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM },
78 {OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM },
79 + {OPT_VHOST_OWNER, 1, NULL, OPT_VHOST_OWNER_NUM },
80 + {OPT_VHOST_PERM, 1, NULL, OPT_VHOST_PERM_NUM },
84 --- a/lib/librte_eal/common/eal_options.h
85 +++ b/lib/librte_eal/common/eal_options.h
86 @@ -83,6 +83,10 @@ enum {
88 #define OPT_VMWARE_TSC_MAP "vmware-tsc-map"
89 OPT_VMWARE_TSC_MAP_NUM,
90 +#define OPT_VHOST_OWNER "vhost-owner"
91 + OPT_VHOST_OWNER_NUM,
92 +#define OPT_VHOST_PERM "vhost-perm"
97 --- a/lib/librte_eal/common/include/rte_eal.h
98 +++ b/lib/librte_eal/common/include/rte_eal.h
99 @@ -335,6 +335,11 @@ enum rte_iova_mode rte_eal_iova_mode(voi
101 rte_eal_mbuf_default_mempool_ops(void);
104 + * Set owner/permissions on sockets if requested on EAL commandline
106 +void rte_eal_set_socket_permissions(const char *);
111 --- a/lib/librte_eal/linuxapp/eal/eal.c
112 +++ b/lib/librte_eal/linuxapp/eal/eal.c
114 #if defined(RTE_ARCH_X86)
117 +#include <sys/types.h>
121 #include <rte_common.h>
122 #include <rte_debug.h>
123 @@ -117,6 +120,12 @@ struct lcore_config lcore_config[RTE_MAX
124 /* internal configuration */
125 struct internal_config internal_config;
127 +/* workaround to be able to create the sockets under a certain set of
128 + * owner/permissions as specified to EAL until solved upstream */
129 +static uid_t debian_vhost_sock_uid = (uid_t)-1;
130 +static gid_t debian_vhost_sock_gid = (gid_t)-1;
131 +static mode_t debian_vhost_sock_perm = 0;
133 /* used by rte_rdtsc() */
134 int rte_cycles_vmware_tsc_map;
136 @@ -366,6 +375,8 @@ eal_usage(const char *prgname)
137 " --"OPT_BASE_VIRTADDR" Base virtual address\n"
138 " --"OPT_CREATE_UIO_DEV" Create /dev/uioX (usually done by hotplug)\n"
139 " --"OPT_VFIO_INTR" Interrupt mode for VFIO (legacy|msi|msix)\n"
140 + " --"OPT_VHOST_OWNER" Create vhost-user sockets with this owner:group\n"
141 + " --"OPT_VHOST_PERM" Create vhost-user sockets with these permissions\n"
143 /* Allow the application to print its usage message too if hook is set */
144 if ( rte_application_usage_hook ) {
145 @@ -525,6 +536,121 @@ eal_log_level_parse(int argc, char **arg
149 +/* Try to double the size of '*buf', return true
150 + * if successful, and '*sizep' will be updated with
151 + * the new size. Otherwise, return false. */
153 +enlarge_buffer(char **buf, size_t *sizep)
155 + size_t newsize = *sizep * 2;
157 + if (newsize > *sizep) {
158 + *buf = realloc(*buf, newsize);
167 +get_owners_from_str(const char *user_spec, uid_t *uid, gid_t *gid)
169 + size_t bufsize = 4096;
171 + char *pos = strchr(user_spec, ':');
172 + user_spec += strspn(user_spec, " \t\r\n");
173 + size_t len = pos ? (size_t)(pos - user_spec) : strlen(user_spec);
176 + struct passwd pwd, *res;
179 + buf = malloc(bufsize);
180 + char *user_search = NULL;
182 + user_search = malloc(len + 1);
183 + memcpy(user_search, user_spec, len);
184 + user_search[len] = '\0';
185 + while ((e = getpwnam_r(user_search, &pwd, buf, bufsize, &res)) == ERANGE) {
186 + if (!enlarge_buffer(&buf, &bufsize)) {
192 + RTE_LOG(ERR, EAL,"Failed to retrive user %s's uid (%s), aborting.",
193 + user_search, strerror(e));
197 + RTE_LOG(ERR, EAL,"user %s not found, aborting.",
203 + /* User name is not specified, use current user. */
204 + while ((e = getpwuid_r(getuid(), &pwd, buf, bufsize, &res)) == ERANGE) {
205 + if (!enlarge_buffer(&buf, &bufsize)) {
211 + RTE_LOG(ERR, EAL,"Failed to retrive current user's uid "
212 + "(%s), aborting.", strerror(e));
215 + user_search = strdup(pwd.pw_name);
225 + char *grpstr = pos + 1;
226 + grpstr += strspn(grpstr, " \t\r\n");
229 + struct group grp, *res;
232 + buf = malloc(bufsize);
233 + while ((e = getgrnam_r(grpstr, &grp, buf, bufsize, &res))
235 + if (!enlarge_buffer(&buf, &bufsize)) {
241 + RTE_LOG(ERR, EAL,"Failed to get group entry for %s, "
242 + "(%s), aborting.", grpstr,
247 + RTE_LOG(ERR, EAL,"Group %s not found, aborting.",
264 /* Parse the argument given in the command line of the application */
266 eal_parse_args(int argc, char **argv)
267 @@ -612,6 +738,26 @@ eal_parse_args(int argc, char **argv)
268 internal_config.mbuf_pool_ops_name = optarg;
271 + case OPT_VHOST_OWNER_NUM:
272 + if (get_owners_from_str(optarg, &debian_vhost_sock_uid,
273 + &debian_vhost_sock_gid)) {
274 + RTE_LOG(ERR, EAL,"vhost-user socket unable to get"
275 + " specified user/group: %s\n", optarg);
276 + debian_vhost_sock_uid = (uid_t)-1;
277 + debian_vhost_sock_gid = (gid_t)-1;
280 + RTE_LOG(INFO, EAL,"socket owner specified as %s (%d:%d)\n",
281 + optarg, debian_vhost_sock_uid, debian_vhost_sock_gid);
285 + case OPT_VHOST_PERM_NUM:
286 + debian_vhost_sock_perm = (mode_t)strtoul(optarg, NULL, 0);
287 + RTE_LOG(INFO, EAL,"socket perm specified as '%#o' from '%s'\n",
288 + debian_vhost_sock_perm, optarg);
292 if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
293 RTE_LOG(ERR, EAL, "Option %c is not supported "
294 @@ -1041,3 +1187,47 @@ rte_eal_check_module(const char *module_
295 /* Module has been found */
300 +vhost_set_permissions(const char *vhost_sock_location)
302 + int err = chmod(vhost_sock_location, debian_vhost_sock_perm);
304 + RTE_LOG(ERR, EAL,"vhost-user socket cannot set"
305 + " permissions to %#o (%s).\n",
306 + debian_vhost_sock_perm, strerror(err));
309 + RTE_LOG(INFO, EAL,"Socket %s changed permissions"
310 + " to %#o\n", vhost_sock_location,
311 + debian_vhost_sock_perm);
315 +vhost_set_ownership(const char *vhost_sock_location)
317 + int err = chown(vhost_sock_location, debian_vhost_sock_uid, debian_vhost_sock_gid);
319 + RTE_LOG(ERR, EAL,"vhost-user socket unable to set"
320 + " ownership to %d:%d (%s).\n",
321 + debian_vhost_sock_uid, debian_vhost_sock_gid,
326 + RTE_LOG(INFO, EAL,"Socket %s changed ownership"
327 + " to %d:%d.\n", vhost_sock_location,
328 + debian_vhost_sock_uid, debian_vhost_sock_gid);
332 +rte_eal_set_socket_permissions(const char *path)
334 + if (debian_vhost_sock_perm != 0) {
335 + vhost_set_permissions(path);
338 + if (debian_vhost_sock_uid != (uid_t)-1 || debian_vhost_sock_gid != (gid_t)-1) {
339 + vhost_set_ownership(path);
342 --- a/lib/librte_eal/rte_eal_version.map
343 +++ b/lib/librte_eal/rte_eal_version.map
344 @@ -118,6 +118,7 @@ DPDK_16.04 {
346 rte_cpu_get_flag_name;
347 rte_eal_primary_proc_alive;
348 + rte_eal_set_socket_permissions;
352 --- a/lib/librte_vhost/socket.c
353 +++ b/lib/librte_vhost/socket.c
354 @@ -99,6 +99,8 @@ struct vhost_user {
355 pthread_mutex_t mutex;
358 +#include <rte_eal.h>
360 #define MAX_VIRTIO_BACKLOG 128
362 static void vhost_user_server_new_connection(int fd, void *data, int *remove);
363 @@ -366,6 +368,7 @@ vhost_user_start_server(struct vhost_use
367 + rte_eal_set_socket_permissions(path);