Daniele Di Proietto <diproiet...@vmware.com> writes:

> Hi Aaron,
>
> I'm still a little bit nervous about calling chown on a (partially)
> user controlled file name.

I agree, that always seems scary.

> Before moving forward I wanted to discuss a couple of other options:
>
> * Ansis (in CC) suggested using -runas parameter in qemu.  This way
> qemu can open the socket as root and drop privileges before starting
> guest execution.

I'm not sure how to do this with libvirt, or via the OpenStack Neutron
plugin.  I also don't know if it would be an acceptable workaround for
users.  Additionally, I recall there being something of a "don't even
know if this works" around it.  Maybe Christian or Ansis (both in CC)
can expound on it.

Today, I know that users are manually going to directories which
contain the vhost-user sockets and running chown/chmod.  Sometimes with
even worse protections than what ovs could provide (I know of someone
just doing `chown a+rw`..shudder..).  Additionally, it definitely
doesn't survive reboot.

I think what attracted Christian and I to this feature set is that it
can be complementary to MAC, by using group whitelisting (ie: ovs is in
a mutual vhost-user group with the qemu group and can chown/chmod
without actually needing root).

There is a more complicated solution, which is to keep a part of OVS
running as root that can manually open the files, change permissions,
and pass the descriptors back.  That solution feels a bit more invasive,
and just as dangerous to me.

> * Instead of changing the owner of the socket, we could create it as a
> different user using setfsgid() or seteuid() system call.  I'm not
> sure whether this is doable, we need to make sure that
> rte_vhost_driver_register() can run with reduced privileges and that
> the system calls play nicely with other threads.

This is orthogonal, I think.  I'm envisioning a scenario as I've
outlined above.  Open vSwitch runs as the openvswitch user.  The
openvswitch user belongs to both the openvswitch group, as well as the
vhost-user group.  Additionally, the qemu user is a member of the
vhost-user group.  Then there's a baked in whitelist - both have access
to vhost-user group chown'd files, and we can set the permissions on the
socket to be something like 0060 or 0660.  This assumes that it is
possible to start ovs+dpdk without root access; I'll need some time to
investigate that.

> What do you guys think?

I think originally we quickly discussed 4 possible solutions (and
hopefully I captured them correctly):

1. OVS downgrades to the ovs user, and kvm runs under the ovs
   group.  I don't actually like this solution because kvm could then
   pollute the ovs database.

2. OVS runs as some user and sets the user/group ownership of the socket
   via chown/chmod where permissions come from the database (the
   original context had ovs running as root - but as I described above
   it doesn't need to be root provided ovs+DPDK can start without root).

3. OVS runs as some user, kvm starts as root, opens the socket and
   downgrades.  IIRC, this doesn't actually work, or it may have
   implications on other projects.  I don't remember exactly what was
   not as great about this solution, TBH.

4. OVS and KVM run as whatever users; MAC is used to enforce the
   layering between them.

I think solution 2 and solution 4 don't actually interfere with each
other, and can be used to a complementary effect (if implemented
properly) so that the MAC layer enforces access, but even without MAC,
the DAC layer can provide appropriate whitelisting behavior.

I hope that makes sense.  Thanks for your input on this, as always,
Daniele!

-Aaron

> Thanks,
>
> Daniele
>
>
>
>
> On 20/05/2016 13:32, "Aaron Conole" <acon...@redhat.com> wrote:
>
>>Currently, when dpdkvhostuser devices are created, they inherit whatever the
>>running umask and uid/gid of the vswitchd process. This leads to difficulties
>>when using vhost_user consumers (such as qemu).
>>
>>This patch introduces two new database entries, 'vhost-sock-owner' to set the
>>ownership, and 'vhost-sock-perms' to set the permissions bits for the
>>vhost_user sockets.
>>
>>Signed-off-by: Aaron Conole <acon...@redhat.com>
>>---
>>v1->v2:
>>* Rebased to latest
>>
>> INSTALL.DPDK.md      |  7 +++++++
>> NEWS                 |  2 ++
>> lib/netdev-dpdk.c    | 26 +++++++++++++++++++++++---
>> vswitchd/vswitch.xml | 23 +++++++++++++++++++++++
>> 4 files changed, 55 insertions(+), 3 deletions(-)
>>
>>diff --git a/INSTALL.DPDK.md b/INSTALL.DPDK.md
>>index 93f92e4..5debcd1 100644
>>--- a/INSTALL.DPDK.md
>>+++ b/INSTALL.DPDK.md
>>@@ -180,6 +180,13 @@ Using the DPDK with ovs-vswitchd:
>>    * vhost-sock-dir
>>    Option to set the path to the vhost_user unix socket files.
>> 
>>+   * vhost-sock-owner
>>+   Option to set the owner of the vhost_user unix socket files.
>>+
>>+   * vhost-sock-perms
>>+   Option to set the DAC permissions of the vhost_user unix socket
>>+   files.
>>+
>>    NOTE: Changing any of these options requires restarting the ovs-vswitchd
>>    application.
>> 
>>diff --git a/NEWS b/NEWS
>>index 4e81cad..807d4bf 100644
>>--- a/NEWS
>>+++ b/NEWS
>>@@ -32,6 +32,8 @@ Post-v2.5.0
>>      * DB entries have been added for many of the DPDK EAL command line
>>        arguments. Additional arguments can be passed via the dpdk-extra
>>        entry.
>>+     * New database options 'vhost-sock-owner' and 'vhost-sock-perms' for
>>+       setting vhost_user unix socket file ownership and permissions.
>>    - ovs-benchmark: This utility has been removed due to lack of use and
>>      bitrot.
>>    - ovs-appctl:
>>diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
>>index 87879d5..d405e66 100644
>>--- a/lib/netdev-dpdk.c
>>+++ b/lib/netdev-dpdk.c
>>@@ -31,6 +31,7 @@
>> #include <sys/stat.h>
>> #include <getopt.h>
>> 
>>+#include "chutil.h"
>> #include "dirs.h"
>> #include "dp-packet.h"
>> #include "dpif-netdev.h"
>>@@ -140,6 +141,10 @@ 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. */
>> #endif
>> static char *vhost_sock_dir = NULL;   /* Location of vhost-user sockets */
>>+static char *vhost_sock_def_owner = NULL; /* Default owner of vhost-user
>>+                                             sockets*/
>>+static char *vhost_sock_def_perms = NULL; /* Default permissions of
>>+                                             vhost-user sockets */
>> 
>> /*
>>  * Maximum amount of time in micro seconds to try and enqueue to vhost.
>>@@ -872,6 +877,16 @@ netdev_dpdk_vhost_user_construct(struct netdev *netdev)
>>     }
>> 
>>     ovs_mutex_unlock(&dpdk_mutex);
>>+    if (!err && vhost_sock_def_owner &&
>>+        (err = ovs_chown(dev->vhost_id, vhost_sock_def_owner))) {
>>+        VLOG_ERR("vhost-user socket device ownership change failed.");
>>+    }
>>+
>>+    if (!err && vhost_sock_def_perms &&
>>+        (err = ovs_chmod(dev->vhost_id, vhost_sock_def_perms))) {
>>+        VLOG_ERR("vhost-user socket device permission change failed.");
>>+    }
>>+
>>     return err;
>> }
>> 
>>@@ -3098,8 +3113,8 @@ dpdk_init__(const struct smap *ovs_other_config)
>>     VLOG_INFO("DPDK Enabled, initializing");
>> 
>> #ifdef VHOST_CUSE
>>-    if (process_vhost_flags("cuse-dev-name", xstrdup("vhost-net"),
>>-                            PATH_MAX, ovs_other_config, &cuse_dev_name)) {
>>+    process_vhost_flags("cuse-dev-name", xstrdup("vhost-net"),
>>+                        PATH_MAX, ovs_other_config, &cuse_dev_name);
>> #else
>>     if (process_vhost_flags("vhost-sock-dir", xstrdup(ovs_rundir()),
>>                             NAME_MAX, ovs_other_config,
>>@@ -3123,9 +3138,14 @@ dpdk_init__(const struct smap *ovs_other_config)
>>         free(sock_dir_subcomponent);
>>     } else {
>>         vhost_sock_dir = sock_dir_subcomponent;
>>-#endif
>>     }
>> 
>>+    process_vhost_flags("vhost-sock-owner", NULL, NAME_MAX, ovs_other_config,
>>+                        &vhost_sock_def_owner);
>>+    process_vhost_flags("vhost-sock-perms", NULL, NAME_MAX, ovs_other_config,
>>+                        &vhost_sock_def_perms);
>>+#endif
>>+
>>     /* Get the main thread affinity */
>>     CPU_ZERO(&cpuset);
>>     err = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t),
>>diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
>>index 944d8ec..0553d5a 100644
>>--- a/vswitchd/vswitch.xml
>>+++ b/vswitchd/vswitch.xml
>>@@ -311,6 +311,29 @@
>>         </p>
>>       </column>
>> 
>>+      <column name="other_config" key="vhost-sock-owner"
>>+              type='{"type": "string"}'>
>>+        <p>
>>+          Specifies the owner of the vhost-user unix domain socket files.
>>+        </p>
>>+        <p>
>>+          The default is to inherit from the running user and group id's. The
>>+          argument is specified in the same form as the 'chown' unix utility.
>>+        </p>
>>+      </column>
>>+
>>+      <column name="other_config" key="vhost-sock-perms"
>>+              type='{"type": "string"}'>
>>+        <p>
>>+          Specifies the permissions for the vhost-user unix domain socket
>>+          files.
>>+        </p>
>>+        <p>
>>+          The default is derived from the running mask. The argument is
>>+          specified in the same form as the 'chmod' unix utility.
>>+        </p>
>>+      </column>
>>+
>>       <column name="other_config" key="n-handler-threads"
>>               type='{"type": "integer", "minInteger": 1}'>
>>         <p>
>>-- 
>>2.5.5
>>
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to