提交 6f5f52c4 编写于 作者: D Daniel P. Berrange

Make virCommand env handling robust in setuid env

When running setuid, we must be careful about what env vars
we allow commands to inherit from us. Replace the
virCommandAddEnvPass function with two new ones which do
filtering

  virCommandAddEnvPassAllowSUID
  virCommandAddEnvPassBlockSUID

And make virCommandAddEnvPassCommon use the appropriate
ones
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
(cherry picked from commit 9b8f307c)

Conflicts:
	src/qemu/qemu_command.c
上级 b4ae6429
...@@ -1238,7 +1238,8 @@ virCommandAddArgSet; ...@@ -1238,7 +1238,8 @@ virCommandAddArgSet;
virCommandAddEnvBuffer; virCommandAddEnvBuffer;
virCommandAddEnvFormat; virCommandAddEnvFormat;
virCommandAddEnvPair; virCommandAddEnvPair;
virCommandAddEnvPass; virCommandAddEnvPassAllowSUID;
virCommandAddEnvPassBlockSUID;
virCommandAddEnvPassCommon; virCommandAddEnvPassCommon;
virCommandAddEnvString; virCommandAddEnvString;
virCommandAllowCap; virCommandAllowCap;
......
...@@ -733,7 +733,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, ...@@ -733,7 +733,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
cmd = virCommandNew(vm->def->emulator); cmd = virCommandNew(vm->def->emulator);
/* The controller may call ip command, so we have to retain PATH. */ /* The controller may call ip command, so we have to retain PATH. */
virCommandAddEnvPass(cmd, "PATH"); virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");
virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d", virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d",
virLogGetDefaultPriority()); virLogGetDefaultPriority());
......
...@@ -6917,7 +6917,7 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg, ...@@ -6917,7 +6917,7 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
* security issues and might not work when using VNC. * security issues and might not work when using VNC.
*/ */
if (cfg->vncAllowHostAudio) if (cfg->vncAllowHostAudio)
virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV"); virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
else else
virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none"); virCommandAddEnvString(cmd, "QEMU_AUDIO_DRV=none");
...@@ -7162,8 +7162,8 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg, ...@@ -7162,8 +7162,8 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
* use QEMU's host audio drivers, possibly SDL too * use QEMU's host audio drivers, possibly SDL too
* User can set these two before starting libvirtd * User can set these two before starting libvirtd
*/ */
virCommandAddEnvPass(cmd, "QEMU_AUDIO_DRV"); virCommandAddEnvPassBlockSUID(cmd, "QEMU_AUDIO_DRV", NULL);
virCommandAddEnvPass(cmd, "SDL_AUDIODRIVER"); virCommandAddEnvPassBlockSUID(cmd, "SDL_AUDIODRIVER", NULL);
/* New QEMU has this flag to let us explicitly ask for /* New QEMU has this flag to let us explicitly ask for
* SDL graphics. This is better than relying on the * SDL graphics. This is better than relying on the
......
...@@ -127,9 +127,9 @@ static int virNetSocketForkDaemon(const char *binary) ...@@ -127,9 +127,9 @@ static int virNetSocketForkDaemon(const char *binary)
NULL); NULL);
virCommandAddEnvPassCommon(cmd); virCommandAddEnvPassCommon(cmd);
virCommandAddEnvPass(cmd, "XDG_CACHE_HOME"); virCommandAddEnvPassBlockSUID(cmd, "XDG_CACHE_HOME", NULL);
virCommandAddEnvPass(cmd, "XDG_CONFIG_HOME"); virCommandAddEnvPassBlockSUID(cmd, "XDG_CONFIG_HOME", NULL);
virCommandAddEnvPass(cmd, "XDG_RUNTIME_DIR"); virCommandAddEnvPassBlockSUID(cmd, "XDG_RUNTIME_DIR", NULL);
virCommandClearCaps(cmd); virCommandClearCaps(cmd);
virCommandDaemonize(cmd); virCommandDaemonize(cmd);
ret = virCommandRun(cmd, NULL); ret = virCommandRun(cmd, NULL);
...@@ -680,11 +680,11 @@ int virNetSocketNewConnectSSH(const char *nodename, ...@@ -680,11 +680,11 @@ int virNetSocketNewConnectSSH(const char *nodename,
cmd = virCommandNew(binary ? binary : "ssh"); cmd = virCommandNew(binary ? binary : "ssh");
virCommandAddEnvPassCommon(cmd); virCommandAddEnvPassCommon(cmd);
virCommandAddEnvPass(cmd, "KRB5CCNAME"); virCommandAddEnvPassBlockSUID(cmd, "KRB5CCNAME", NULL);
virCommandAddEnvPass(cmd, "SSH_AUTH_SOCK"); virCommandAddEnvPassBlockSUID(cmd, "SSH_AUTH_SOCK", NULL);
virCommandAddEnvPass(cmd, "SSH_ASKPASS"); virCommandAddEnvPassBlockSUID(cmd, "SSH_ASKPASS", NULL);
virCommandAddEnvPass(cmd, "DISPLAY"); virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
virCommandAddEnvPass(cmd, "XAUTHORITY"); virCommandAddEnvPassBlockSUID(cmd, "XAUTHORITY", NULL);
virCommandClearCaps(cmd); virCommandClearCaps(cmd);
if (service) if (service)
......
...@@ -1247,21 +1247,49 @@ virCommandAddEnvBuffer(virCommandPtr cmd, virBufferPtr buf) ...@@ -1247,21 +1247,49 @@ virCommandAddEnvBuffer(virCommandPtr cmd, virBufferPtr buf)
/** /**
* virCommandAddEnvPass: * virCommandAddEnvPassAllowSUID:
* @cmd: the command to modify * @cmd: the command to modify
* @name: the name to look up in current environment * @name: the name to look up in current environment
* *
* Pass an environment variable to the child * Pass an environment variable to the child
* using current process' value * using current process' value
*
* Allow to be passed even if setuid
*/
void
virCommandAddEnvPassAllowSUID(virCommandPtr cmd, const char *name)
{
const char *value;
if (!cmd || cmd->has_error)
return;
value = virGetEnvAllowSUID(name);
if (value)
virCommandAddEnvPair(cmd, name, value);
}
/**
* virCommandAddEnvPassBlockSUID:
* @cmd: the command to modify
* @name: the name to look up in current environment
* @defvalue: value to return if running setuid, may be NULL
*
* Pass an environment variable to the child
* using current process' value.
*
* Do not pass if running setuid
*/ */
void void
virCommandAddEnvPass(virCommandPtr cmd, const char *name) virCommandAddEnvPassBlockSUID(virCommandPtr cmd, const char *name, const char *defvalue)
{ {
char *value; const char *value;
if (!cmd || cmd->has_error) if (!cmd || cmd->has_error)
return; return;
value = getenv(name); value = virGetEnvBlockSUID(name);
if (!value)
value = defvalue;
if (value) if (value)
virCommandAddEnvPair(cmd, name, value); virCommandAddEnvPair(cmd, name, value);
} }
...@@ -1286,13 +1314,13 @@ virCommandAddEnvPassCommon(virCommandPtr cmd) ...@@ -1286,13 +1314,13 @@ virCommandAddEnvPassCommon(virCommandPtr cmd)
virCommandAddEnvPair(cmd, "LC_ALL", "C"); virCommandAddEnvPair(cmd, "LC_ALL", "C");
virCommandAddEnvPass(cmd, "LD_PRELOAD"); virCommandAddEnvPassBlockSUID(cmd, "LD_PRELOAD", NULL);
virCommandAddEnvPass(cmd, "LD_LIBRARY_PATH"); virCommandAddEnvPassBlockSUID(cmd, "LD_LIBRARY_PATH", NULL);
virCommandAddEnvPass(cmd, "PATH"); virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");
virCommandAddEnvPass(cmd, "HOME"); virCommandAddEnvPassBlockSUID(cmd, "HOME", NULL);
virCommandAddEnvPass(cmd, "USER"); virCommandAddEnvPassAllowSUID(cmd, "USER");
virCommandAddEnvPass(cmd, "LOGNAME"); virCommandAddEnvPassAllowSUID(cmd, "LOGNAME");
virCommandAddEnvPass(cmd, "TMPDIR"); virCommandAddEnvPassBlockSUID(cmd, "TMPDIR", NULL);
} }
/** /**
......
...@@ -99,7 +99,11 @@ void virCommandAddEnvString(virCommandPtr cmd, ...@@ -99,7 +99,11 @@ void virCommandAddEnvString(virCommandPtr cmd,
void virCommandAddEnvBuffer(virCommandPtr cmd, void virCommandAddEnvBuffer(virCommandPtr cmd,
virBufferPtr buf); virBufferPtr buf);
void virCommandAddEnvPass(virCommandPtr cmd, void virCommandAddEnvPassBlockSUID(virCommandPtr cmd,
const char *name,
const char *defvalue) ATTRIBUTE_NONNULL(2);
void virCommandAddEnvPassAllowSUID(virCommandPtr cmd,
const char *name) ATTRIBUTE_NONNULL(2); const char *name) ATTRIBUTE_NONNULL(2);
void virCommandAddEnvPassCommon(virCommandPtr cmd); void virCommandAddEnvPassCommon(virCommandPtr cmd);
......
...@@ -294,8 +294,8 @@ static int test6(const void *unused ATTRIBUTE_UNUSED) ...@@ -294,8 +294,8 @@ static int test6(const void *unused ATTRIBUTE_UNUSED)
{ {
virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper"); virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
virCommandAddEnvPass(cmd, "DISPLAY"); virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
virCommandAddEnvPass(cmd, "DOESNOTEXIST"); virCommandAddEnvPassBlockSUID(cmd, "DOESNOTEXIST", NULL);
if (virCommandRun(cmd, NULL) < 0) { if (virCommandRun(cmd, NULL) < 0) {
virErrorPtr err = virGetLastError(); virErrorPtr err = virGetLastError();
...@@ -319,8 +319,8 @@ static int test7(const void *unused ATTRIBUTE_UNUSED) ...@@ -319,8 +319,8 @@ static int test7(const void *unused ATTRIBUTE_UNUSED)
virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper"); virCommandPtr cmd = virCommandNew(abs_builddir "/commandhelper");
virCommandAddEnvPassCommon(cmd); virCommandAddEnvPassCommon(cmd);
virCommandAddEnvPass(cmd, "DISPLAY"); virCommandAddEnvPassBlockSUID(cmd, "DISPLAY", NULL);
virCommandAddEnvPass(cmd, "DOESNOTEXIST"); virCommandAddEnvPassBlockSUID(cmd, "DOESNOTEXIST", NULL);
if (virCommandRun(cmd, NULL) < 0) { if (virCommandRun(cmd, NULL) < 0) {
virErrorPtr err = virGetLastError(); virErrorPtr err = virGetLastError();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册