[ovs-dev] [PATCH] bridge: allow OVS to interact with controller through sockets outside run dir

Ansis Atteka aatteka at ovn.org
Mon Jun 20 21:19:40 UTC 2016


Currently Open vSwitch is unable to create or connect to Unix Domain
Sockets outside designated 'run' directory, because of fear of potential
remote exploits where a hacked remote OVSDB manager would tell Open vSwitch
to connect to a unix domain sockets owned by other daemons on the same
hypervisor.

This patch allows to disable this behavior by changing
/etc/default/openvswitch file to:

...
OVS_CTL_OPTS=--no-self-confinement
...

Note, that it is better to stick with default behavior, unless:
1. You have Open vSwitch running under SELinux or AppArmor
   that would prevent OVS from messing with sockets owned by other
   daemons; OR
2. You are sure that relying on OpenFlow handshake is enough to
   prevent OVS to adversely interact with those other daemons
   running on the same hypervisor; OR
3. You don't have much worries of remote exploits in the first
   place, because perhaps OVSDB manager is running on the same host
   as OVS.

Signed-off-by: Ansis Atteka <aatteka at ovn.org>
VMware-BZ: #1525857
---
 lib/daemon.c         | 14 ++++++++++++++
 lib/daemon.h         | 14 ++++++++++++++
 utilities/ovs-ctl.in | 18 +++++++++++-------
 vswitchd/bridge.c    |  5 +++--
 4 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/lib/daemon.c b/lib/daemon.c
index b8313d4..6273ebd 100644
--- a/lib/daemon.c
+++ b/lib/daemon.c
@@ -29,6 +29,13 @@ VLOG_DEFINE_THIS_MODULE(daemon);
  * /dev/null (if false) or keep it for the daemon to use (if true). */
 static bool save_fds[3];
 
+/* Self Confinement is a security feature that introduces additional
+ * layer of defense where OVS in self-denying manner would refuse to connect
+ * to or create unix domain sockets outside designated 'run' directory even
+ * if remote (or local) OVSDB manager asked it to do so.  This feature may
+ * be disabled if Mandatory Access Control is used. */
+bool self_confine = true;
+
 /* Will daemonize() really detach? */
 bool
 get_detach(void)
@@ -59,6 +66,13 @@ set_pidfile(const char *name)
     pidfile = make_pidfile_name(name);
 }
 
+/* Disables self confinement. */
+void
+daemon_disable_self_confinement(void)
+{
+    self_confine = false;
+}
+
 /* A daemon doesn't normally have any use for the file descriptors for stdin,
  * stdout, and stderr after it detaches.  To keep these file descriptors from
  * e.g. holding an SSH session open, by default detaching replaces each of
diff --git a/lib/daemon.h b/lib/daemon.h
index 4990415..742f382 100644
--- a/lib/daemon.h
+++ b/lib/daemon.h
@@ -39,6 +39,7 @@
 #ifndef _WIN32
 #define DAEMON_OPTION_ENUMS                     \
     OPT_DETACH,                                 \
+    OPT_NO_SELF_CONFINEMENT,                    \
     OPT_NO_CHDIR,                               \
     OPT_OVERWRITE_PIDFILE,                      \
     OPT_PIDFILE,                                \
@@ -47,6 +48,7 @@
 
 #define DAEMON_LONG_OPTIONS                                              \
         {"detach",            no_argument, NULL, OPT_DETACH},            \
+        {"no-self-confinement", no_argument, NULL, OPT_NO_SELF_CONFINEMENT}, \
         {"no-chdir",          no_argument, NULL, OPT_NO_CHDIR},          \
         {"pidfile",           optional_argument, NULL, OPT_PIDFILE},     \
         {"overwrite-pidfile", no_argument, NULL, OPT_OVERWRITE_PIDFILE}, \
@@ -58,6 +60,10 @@
             set_detach();                       \
             break;                              \
                                                 \
+        case OPT_NO_SELF_CONFINEMENT:           \
+            daemon_disable_self_confinement();  \
+            break;                              \
+                                                \
         case OPT_NO_CHDIR:                      \
             set_no_chdir();                     \
             break;                              \
@@ -86,6 +92,7 @@ pid_t read_pidfile(const char *name);
 #else
 #define DAEMON_OPTION_ENUMS                    \
     OPT_DETACH,                                \
+    OPT_NO_SELF_CONFINEMENT,                   \
     OPT_NO_CHDIR,                              \
     OPT_PIDFILE,                               \
     OPT_PIPE_HANDLE,                           \
@@ -95,6 +102,7 @@ pid_t read_pidfile(const char *name);
 
 #define DAEMON_LONG_OPTIONS                                               \
         {"detach",             no_argument, NULL, OPT_DETACH},            \
+        {"no-self-confinement" no_argument, NULL, OPT_NO_SELF_CONFINEMENT}, \
         {"no-chdir",           no_argument, NULL, OPT_NO_CHDIR},          \
         {"pidfile",            optional_argument, NULL, OPT_PIDFILE},     \
         {"pipe-handle",        required_argument, NULL, OPT_PIPE_HANDLE}, \
@@ -106,6 +114,10 @@ pid_t read_pidfile(const char *name);
         case OPT_DETACH:                        \
             break;                              \
                                                 \
+        case OPT_NO_SELF_CONFINEMENT:           \
+            daemon_disable_self_confinement();  \
+            break;                              \
+                                                \
         case OPT_NO_CHDIR:                      \
             break;                              \
                                                 \
@@ -138,10 +150,12 @@ void daemonize_complete(void);
 void daemon_set_new_user(const char * user_spec);
 void daemon_become_new_user(bool access_datapath);
 void daemon_usage(void);
+void daemon_disable_self_confinement(void);
 void service_start(int *argcp, char **argvp[]);
 void service_stop(void);
 bool should_service_stop(void);
 void set_pidfile(const char *name);
 void close_standard_fds(void);
 
+extern bool self_confine;
 #endif /* daemon.h */
diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
index 6bc7ced..1f03f96 100755
--- a/utilities/ovs-ctl.in
+++ b/utilities/ovs-ctl.in
@@ -226,13 +226,16 @@ do_start_forwarding () {
             ulimit -n $MAXFD
         fi
 
-	    # Start ovs-vswitchd.
-	    set ovs-vswitchd unix:"$DB_SOCK"
-	    set "$@" -vconsole:emer -vsyslog:err -vfile:info
-	    if test X"$MLOCKALL" != Xno; then
-	        set "$@" --mlockall
-	    fi
-	    start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
+        # Start ovs-vswitchd.
+        set ovs-vswitchd unix:"$DB_SOCK"
+        set "$@" -vconsole:emer -vsyslog:err -vfile:info
+        if test X"$MLOCKALL" != Xno; then
+            set "$@" --mlockall
+        fi
+        if test X"$SELF_CONFINEMENT" = Xno; then
+            set "$@" --no-self-confinement
+        fi
+        start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
     fi
 }
 
@@ -492,6 +495,7 @@ set_defaults () {
     DAEMON_CWD=/
     FORCE_COREFILES=yes
     MLOCKALL=yes
+    SELF_CONFINEMENT=yes
     OVSDB_SERVER=yes
     OVS_VSWITCHD=yes
     OVSDB_SERVER_PRIORITY=-10
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 4273552..9b97d9a 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -3561,8 +3561,9 @@ bridge_configure_remotes(struct bridge *br,
     for (i = 0; i < n_controllers; i++) {
         struct ovsrec_controller *c = controllers[i];
 
-        if (!strncmp(c->target, "punix:", 6)
-            || !strncmp(c->target, "unix:", 5)) {
+        if (self_confine
+            && (!strncmp(c->target, "punix:", 6)
+            || !strncmp(c->target, "unix:", 5))) {
             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
             char *whitelist;
 
-- 
2.7.4




More information about the dev mailing list