43fe83
From 4799286cbbf12b5d2734ae79d0580d92b8d3b100 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <4799286cbbf12b5d2734ae79d0580d92b8d3b100.1383321465.git.jdenemar@redhat.com>
43fe83
From: "Daniel P. Berrange" <berrange@redhat.com>
43fe83
Date: Wed, 30 Oct 2013 17:01:50 +0000
43fe83
Subject: [PATCH] Make virCommand env handling robust in setuid env
43fe83
43fe83
For
43fe83
43fe83
  https://bugzilla.redhat.com/show_bug.cgi?id=1015247
43fe83
43fe83
When running setuid, we must be careful about what env vars
43fe83
we allow commands to inherit from us. Replace the
43fe83
virCommandAddEnvPass function with two new ones which do
43fe83
filtering
43fe83
43fe83
  virCommandAddEnvPassAllowSUID
43fe83
  virCommandAddEnvPassBlockSUID
43fe83
43fe83
And make virCommandAddEnvPassCommon use the appropriate
43fe83
ones
43fe83
43fe83
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
43fe83
(cherry picked from commit 9b8f307c6ad002a17a0510513883d06395636793)
43fe83
43fe83
Conflicts:
43fe83
	src/qemu/qemu_command.c
43fe83
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
43fe83
---
43fe83
 src/libvirt_private.syms |  3 ++-
43fe83
 src/lxc/lxc_process.c    |  2 +-
43fe83
 src/qemu/qemu_command.c  |  6 +++---
43fe83
 src/rpc/virnetsocket.c   | 16 ++++++++--------
43fe83
 src/util/vircommand.c    | 50 +++++++++++++++++++++++++++++++++++++-----------
43fe83
 src/util/vircommand.h    |  8 ++++++--
43fe83
 tests/commandtest.c      |  8 ++++----
43fe83
 7 files changed, 63 insertions(+), 30 deletions(-)
43fe83
43fe83
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
43fe83
index 374a332..ca6275c 100644
43fe83
--- a/src/libvirt_private.syms
43fe83
+++ b/src/libvirt_private.syms
43fe83
@@ -1237,7 +1237,8 @@ virCommandAddArgSet;
43fe83
 virCommandAddEnvBuffer;
43fe83
 virCommandAddEnvFormat;
43fe83
 virCommandAddEnvPair;
43fe83
-virCommandAddEnvPass;
43fe83
+virCommandAddEnvPassAllowSUID;
43fe83
+virCommandAddEnvPassBlockSUID;
43fe83
 virCommandAddEnvPassCommon;
43fe83
 virCommandAddEnvString;
43fe83
 virCommandAllowCap;
43fe83
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
43fe83
index a5f1f35..a88fb4d 100644
43fe83
--- a/src/lxc/lxc_process.c
43fe83
+++ b/src/lxc/lxc_process.c
43fe83
@@ -740,7 +740,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
43fe83
     cmd = virCommandNew(vm->def->emulator);
43fe83
 
43fe83
     /* The controller may call ip command, so we have to retain PATH. */
43fe83
-    virCommandAddEnvPass(cmd, "PATH");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");
43fe83
 
43fe83
     virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d",
43fe83
                            virLogGetDefaultPriority());
43fe83
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
43fe83
index 78f07c8..0292b72 100644
43fe83
--- a/src/qemu/qemu_command.c
43fe83
+++ b/src/qemu/qemu_command.c
43fe83
@@ -6997,7 +6997,7 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
43fe83
      * security issues and might not work when using VNC.
43fe83
      */
43fe83
     if (cfg->vncAllowHostAudio)
43fe83
-        virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
43fe83
+        virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
43fe83
     else
43fe83
         virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
43fe83
 
43fe83
@@ -7242,8 +7242,8 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
43fe83
          * use QEMU's host audio drivers, possibly SDL too
43fe83
          * User can set these two before starting libvirtd
43fe83
          */
43fe83
-        virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV");
43fe83
-        virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER");
43fe83
+        virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
43fe83
+        virCommandAddEnvPassBlockSUID(cmd, "SDL_AUDIODRIVER", NULL);
43fe83
 
43fe83
         /* New QEMU has this flag to let us explicitly ask for
43fe83
          * SDL graphics. This is better than relying on the
43fe83
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
43fe83
index ae81512..fcd41ca 100644
43fe83
--- a/src/rpc/virnetsocket.c
43fe83
+++ b/src/rpc/virnetsocket.c
43fe83
@@ -127,9 +127,9 @@ static int virNetSocketForkDaemon(const char *binary)
43fe83
                                              NULL);
43fe83
 
43fe83
     virCommandAddEnvPassCommon(cmd);
43fe83
-    virCommandAddEnvPass(cmd, "XDG_CACHE_HOME");
43fe83
-    virCommandAddEnvPass(cmd, "XDG_CONFIG_HOME");
43fe83
-    virCommandAddEnvPass(cmd, "XDG_RUNTIME_DIR");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "XDG_CACHE_HOME", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "XDG_CONFIG_HOME", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "XDG_RUNTIME_DIR", NULL);
43fe83
     virCommandClearCaps(cmd);
43fe83
     virCommandDaemonize(cmd);
43fe83
     ret = virCommandRun(cmd, NULL);
43fe83
@@ -680,11 +680,11 @@ int virNetSocketNewConnectSSH(const char *nodename,
43fe83
 
43fe83
     cmd = virCommandNew(binary ? binary : "ssh");
43fe83
     virCommandAddEnvPassCommon(cmd);
43fe83
-    virCommandAddEnvPass(cmd, "KRB5CCNAME");
43fe83
-    virCommandAddEnvPass(cmd, "SSH_AUTH_SOCK");
43fe83
-    virCommandAddEnvPass(cmd, "SSH_ASKPASS");
43fe83
-    virCommandAddEnvPass(cmd, "DISPLAY");
43fe83
-    virCommandAddEnvPass(cmd, "XAUTHORITY");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "KRB5CCNAME", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "SSH_AUTH_SOCK", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "SSH_ASKPASS", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "XAUTHORITY", NULL);
43fe83
     virCommandClearCaps(cmd);
43fe83
 
43fe83
     if (service)
43fe83
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
43fe83
index 00ff69a..fca0e09 100644
43fe83
--- a/src/util/vircommand.c
43fe83
+++ b/src/util/vircommand.c
43fe83
@@ -1247,21 +1247,49 @@ virCommandAddEnvBuffer(virCommandPtr cmd, virBufferPtr buf)
43fe83
 
43fe83
 
43fe83
 /**
43fe83
- * virCommandAddEnvPass:
43fe83
+ * virCommandAddEnvPassAllowSUID:
43fe83
  * @cmd: the command to modify
43fe83
  * @name: the name to look up in current environment
43fe83
  *
43fe83
  * Pass an environment variable to the child
43fe83
  * using current process' value
43fe83
+ *
43fe83
+ * Allow to be passed even if setuid
43fe83
+ */
43fe83
+void
43fe83
+virCommandAddEnvPassAllowSUID(virCommandPtr cmd, const char *name)
43fe83
+{
43fe83
+    const char *value;
43fe83
+    if (!cmd || cmd->has_error)
43fe83
+        return;
43fe83
+
43fe83
+    value = virGetEnvAllowSUID(name);
43fe83
+    if (value)
43fe83
+        virCommandAddEnvPair(cmd, name, value);
43fe83
+}
43fe83
+
43fe83
+
43fe83
+/**
43fe83
+ * virCommandAddEnvPassBlockSUID:
43fe83
+ * @cmd: the command to modify
43fe83
+ * @name: the name to look up in current environment
43fe83
+ * @defvalue: value to return if running setuid, may be NULL
43fe83
+ *
43fe83
+ * Pass an environment variable to the child
43fe83
+ * using current process' value.
43fe83
+ *
43fe83
+ * Do not pass if running setuid
43fe83
  */
43fe83
 void
43fe83
-virCommandAddEnvPass(virCommandPtr cmd, const char *name)
43fe83
+virCommandAddEnvPassBlockSUID(virCommandPtr cmd, const char *name, const char *defvalue)
43fe83
 {
43fe83
-    char *value;
43fe83
+    const char *value;
43fe83
     if (!cmd || cmd->has_error)
43fe83
         return;
43fe83
 
43fe83
-    value = getenv(name);
43fe83
+    value = virGetEnvBlockSUID(name);
43fe83
+    if (!value)
43fe83
+        value = defvalue;
43fe83
     if (value)
43fe83
         virCommandAddEnvPair(cmd, name, value);
43fe83
 }
43fe83
@@ -1286,13 +1314,13 @@ virCommandAddEnvPassCommon(virCommandPtr cmd)
43fe83
 
43fe83
     virCommandAddEnvPair(cmd, "LC_ALL", "C");
43fe83
 
43fe83
-    virCommandAddEnvPass(cmd, "LD_PRELOAD");
43fe83
-    virCommandAddEnvPass(cmd, "LD_LIBRARY_PATH");
43fe83
-    virCommandAddEnvPass(cmd, "PATH");
43fe83
-    virCommandAddEnvPass(cmd, "HOME");
43fe83
-    virCommandAddEnvPass(cmd, "USER");
43fe83
-    virCommandAddEnvPass(cmd, "LOGNAME");
43fe83
-    virCommandAddEnvPass(cmd, "TMPDIR");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "LD_PRELOAD", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "LD_LIBRARY_PATH", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "HOME", NULL);
43fe83
+    virCommandAddEnvPassAllowSUID(cmd, "USER");
43fe83
+    virCommandAddEnvPassAllowSUID(cmd, "LOGNAME");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "TMPDIR", NULL);
43fe83
 }
43fe83
 
43fe83
 /**
43fe83
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
43fe83
index c619e06..e977f93 100644
43fe83
--- a/src/util/vircommand.h
43fe83
+++ b/src/util/vircommand.h
43fe83
@@ -99,8 +99,12 @@ void virCommandAddEnvString(virCommandPtr cmd,
43fe83
 void virCommandAddEnvBuffer(virCommandPtr cmd,
43fe83
                             virBufferPtr buf);
43fe83
 
43fe83
-void virCommandAddEnvPass(virCommandPtr cmd,
43fe83
-                          const char *name) ATTRIBUTE_NONNULL(2);
43fe83
+void virCommandAddEnvPassBlockSUID(virCommandPtr cmd,
43fe83
+                                   const char *name,
43fe83
+                                   const char *defvalue) ATTRIBUTE_NONNULL(2);
43fe83
+
43fe83
+void virCommandAddEnvPassAllowSUID(virCommandPtr cmd,
43fe83
+                                   const char *name) ATTRIBUTE_NONNULL(2);
43fe83
 
43fe83
 void virCommandAddEnvPassCommon(virCommandPtr cmd);
43fe83
 
43fe83
diff --git a/tests/commandtest.c b/tests/commandtest.c
43fe83
index eeb6d1e..1acc8d9 100644
43fe83
--- a/tests/commandtest.c
43fe83
+++ b/tests/commandtest.c
43fe83
@@ -294,8 +294,8 @@ static int test6(const void *unused ATTRIBUTE_UNUSED)
43fe83
 {
43fe83
     virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
43fe83
 
43fe83
-    virCommandAddEnvPass(cmd, "DISPLAY");
43fe83
-    virCommandAddEnvPass(cmd, "DOESNOTEXIST");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "DOESNOTEXIST", NULL);
43fe83
 
43fe83
     if (virCommandRun(cmd, NULL) < 0) {
43fe83
         virErrorPtr err = virGetLastError();
43fe83
@@ -319,8 +319,8 @@ static int test7(const void *unused ATTRIBUTE_UNUSED)
43fe83
     virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
43fe83
 
43fe83
     virCommandAddEnvPassCommon(cmd);
43fe83
-    virCommandAddEnvPass(cmd, "DISPLAY");
43fe83
-    virCommandAddEnvPass(cmd, "DOESNOTEXIST");
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
43fe83
+    virCommandAddEnvPassBlockSUID(cmd, "DOESNOTEXIST", NULL);
43fe83
 
43fe83
     if (virCommandRun(cmd, NULL) < 0) {
43fe83
         virErrorPtr err = virGetLastError();
43fe83
-- 
43fe83
1.8.4.2
43fe83