[Pkg-libvirt-commits] [SCM] Libvirt Debian packaging branch, squeeze-security, updated. debian/0.8.3-5+squeeze5

Guido Günther agx at sigxcpu.org
Sun Mar 17 18:23:54 UTC 2013


The following commit has been merged in the squeeze-security branch:
commit 465cafdf16096079880296c266aba09e406b905d
Author: Guido Günther <agx at sigxcpu.org>
Date:   Sun Mar 17 13:35:44 2013 +0100

    Invoke initgroups when starting kvm
    
    so we don't fail to open /dev/kvm.
    
    Closes: #703208

diff --git a/debian/patches/0020-Rerun-autoconf.patch b/debian/patches/0020-Rerun-autoconf.patch
new file mode 100644
index 0000000..e74f0a8
--- /dev/null
+++ b/debian/patches/0020-Rerun-autoconf.patch
@@ -0,0 +1,35 @@
+From: =?UTF-8?q?Guido=20G=C3=BCnther?= <agx at sigxcpu.org>
+Date: Sun, 17 Mar 2013 14:19:08 +0100
+Subject: Rerun autoconf
+
+---
+ config.h.in |    3 +++
+ configure   |    1 +
+ 2 files changed, 4 insertions(+)
+
+diff --git a/config.h.in b/config.h.in
+index 187fdbc..d839f22 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -452,6 +452,9 @@
+ /* Define to 1 if you have the `inet_pton' function. */
+ #undef HAVE_INET_PTON
+ 
++/* Define to 1 if you have the `initgroups' function. */
++#undef HAVE_INITGROUPS
++
+ /* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */
+ #undef HAVE_INTMAX_T
+ 
+diff --git a/configure b/configure
+index 37adb0a..f24ad5d 100755
+--- a/configure
++++ b/configure
+@@ -3009,6 +3009,7 @@ gl_func_list="$gl_func_list regexec"
+ gl_func_list="$gl_func_list sched_getaffinity"
+ gl_func_list="$gl_func_list getuid"
+ gl_func_list="$gl_func_list getgid"
++gl_func_list="$gl_func_list initgroups"
+ gl_func_list="$gl_func_list posix_fallocate"
+ gl_func_list="$gl_func_list mmap"
+ gl_func_list="$gl_func_list strerror_r"
diff --git a/debian/patches/security/0017-New-virSetUIDGID-utility-function.patch b/debian/patches/security/0017-New-virSetUIDGID-utility-function.patch
new file mode 100644
index 0000000..80352d6
--- /dev/null
+++ b/debian/patches/security/0017-New-virSetUIDGID-utility-function.patch
@@ -0,0 +1,123 @@
+From: Laine Stump <laine at laine.org>
+Date: Sun, 17 Mar 2013 13:32:59 +0100
+Subject: New virSetUIDGID() utility function
+
+virSetUIDGID() sets both the real and effective group and user of the
+process, and additionally calls initgroups() to assure that the
+process joins all the auxiliary groups that the given uid is a member
+of.
+
+---
+ configure.ac    |    2 +-
+ src/util/util.c |   64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ src/util/util.h |    2 ++
+ 3 files changed, 67 insertions(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index cd48c1b..a075c58 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -93,7 +93,7 @@ AC_MSG_RESULT([$have_cpuid])
+ 
+ 
+ dnl Availability of various common functions (non-fatal if missing).
+-AC_CHECK_FUNCS_ONCE([cfmakeraw regexec sched_getaffinity getuid getgid \
++AC_CHECK_FUNCS_ONCE([cfmakeraw regexec sched_getaffinity getuid getgid initgroups \
+  posix_fallocate mmap])
+ 
+ dnl Availability of various not common threadsafe functions
+diff --git a/src/util/util.c b/src/util/util.c
+index 8f2a17e..08e6137 100644
+--- a/src/util/util.c
++++ b/src/util/util.c
+@@ -2748,6 +2748,61 @@ int virGetGroupID(const char *name,
+     return 0;
+ }
+ 
++
++/* Set the real and effective uid and gid to the given values, and call
++ * initgroups so that the process has all the assumed group membership of
++ * that uid. return 0 on success, -1 on failure.
++ */
++int
++virSetUIDGID(uid_t uid, gid_t gid)
++{
++    if (gid > 0) {
++        if (setregid(gid, gid) < 0) {
++            virReportSystemError(errno,
++                                 _("cannot change to '%d' group"), gid);
++            return -1;
++        }
++    }
++
++    if (uid > 0) {
++# ifdef HAVE_INITGROUPS
++        struct passwd pwd, *pwd_result;
++        char *buf = NULL;
++        size_t bufsize;
++
++        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
++        if (bufsize == -1)
++            bufsize = 16384;
++
++        if (VIR_ALLOC_N(buf, bufsize) < 0) {
++            virReportOOMError();
++            return -1;
++        }
++        getpwuid_r(uid, &pwd, buf, bufsize, &pwd_result);
++        if (!pwd_result) {
++            virReportSystemError(errno,
++                                 _("cannot getpwuid_r(%d)"), uid);
++            VIR_FREE(buf);
++            return -1;
++        }
++        if (initgroups(pwd.pw_name, pwd.pw_gid) < 0) {
++            virReportSystemError(errno,
++                                 _("cannot initgroups(\"%s\", %d)"),
++                                 pwd.pw_name, pwd.pw_gid);
++            VIR_FREE(buf);
++            return -1;
++        }
++        VIR_FREE(buf);
++# endif
++        if (setreuid(uid, uid) < 0) {
++            virReportSystemError(errno,
++                                 _("cannot change to uid to '%d'"), uid);
++            return -1;
++        }
++    }
++    return 0;
++}
++
+ #else /* HAVE_GETPWUID_R */
+ 
+ char *
+@@ -2786,6 +2841,15 @@ int virGetGroupID(const char *name ATTRIBUTE_UNUSED,
+ 
+     return 0;
+ }
++
++int
++virSetUIDGID(uid_t uid ATTRIBUTE_UNUSED,
++             gid_t gid ATTRIBUTE_UNUSED)
++{
++    virUtilError(VIR_ERR_INTERNAL_ERROR,
++                 "%s", _("virSetUIDGID is not available"));
++    return -1;
++}
+ #endif /* HAVE_GETPWUID_R */
+ 
+ 
+diff --git a/src/util/util.h b/src/util/util.h
+index 476eac4..f746cce 100644
+--- a/src/util/util.h
++++ b/src/util/util.h
+@@ -92,6 +92,8 @@ int virPipeReadUntilEOF(int outfd, int errfd,
+                         char **outbuf, char **errbuf);
+ int virFork(pid_t *pid);
+ 
++int virSetUIDGID(uid_t uid, gid_t gid);
++
+ int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
+ 
+ int virFileReadAll(const char *path, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
diff --git a/debian/patches/security/0018-Run-initgroups-in-qemudOpenAsUID.patch b/debian/patches/security/0018-Run-initgroups-in-qemudOpenAsUID.patch
new file mode 100644
index 0000000..87b8c0d
--- /dev/null
+++ b/debian/patches/security/0018-Run-initgroups-in-qemudOpenAsUID.patch
@@ -0,0 +1,74 @@
+From: Dan Kenigsberg <danken at redhat.com>
+Date: Tue, 19 Oct 2010 15:22:57 +0200
+Subject: Run initgroups() in qemudOpenAsUID()
+
+qemudOpenAsUID is intended to open a file with the credentials of a
+specified uid. Current implementation fails if the file is accessible to
+one of uid's groups but not owned by uid.
+
+This patch replaces the supplementary group list that the child process
+inherited from libvirtd with the default group list of uid.
+
+---
+ src/qemu/qemu_driver.c |   27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 6097648..5629885 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -41,6 +41,7 @@
+ #include <signal.h>
+ #include <paths.h>
+ #include <pwd.h>
++#include <grp.h>
+ #include <stdio.h>
+ #include <sys/wait.h>
+ #include <sys/ioctl.h>
+@@ -6308,6 +6309,7 @@ parent_cleanup:
+     char *buf = NULL;
+     size_t bufsize = 1024 * 1024;
+     int bytesread;
++    struct passwd pwd, *pwd_result;
+ 
+     /* child doesn't need the read side of the pipe */
+     close(pipefd[0]);
+@@ -6320,6 +6322,26 @@ parent_cleanup:
+         goto child_cleanup;
+     }
+ 
++    if (VIR_ALLOC_N(buf, bufsize) < 0) {
++        exit_code = ENOMEM;
++        virReportOOMError();
++        goto child_cleanup;
++    }
++
++    exit_code = getpwuid_r(uid, &pwd, buf, bufsize, &pwd_result);
++    if (pwd_result == NULL) {
++        virReportSystemError(errno,
++                             _("cannot getpwuid_r(%d) to read '%s'"),
++                             uid, path);
++        goto child_cleanup;
++    }
++    if (initgroups(pwd.pw_name, pwd.pw_gid) != 0) {
++        exit_code = errno;
++        virReportSystemError(errno,
++                             _("cannot initgroups(\"%s\", %d) to read '%s'"),
++                             pwd.pw_name, pwd.pw_gid, path);
++        goto child_cleanup;
++    }
+     if (setuid(uid) != 0) {
+         exit_code = errno;
+         virReportSystemError(errno,
+@@ -6334,11 +6356,6 @@ parent_cleanup:
+                              path, uid);
+         goto child_cleanup;
+     }
+-    if (VIR_ALLOC_N(buf, bufsize) < 0) {
+-        exit_code = ENOMEM;
+-        virReportOOMError();
+-        goto child_cleanup;
+-    }
+ 
+     /* read from fd and write to pipefd[1] until EOF */
+     do {
diff --git a/debian/patches/security/0019-Replace-setuid-setgid-initgroups-with-virSetUIDGID.patch b/debian/patches/security/0019-Replace-setuid-setgid-initgroups-with-virSetUIDGID.patch
new file mode 100644
index 0000000..46e1785
--- /dev/null
+++ b/debian/patches/security/0019-Replace-setuid-setgid-initgroups-with-virSetUIDGID.patch
@@ -0,0 +1,148 @@
+From: Laine Stump <laine at laine.org>
+Date: Sun, 17 Mar 2013 13:29:13 +0100
+Subject: Replace setuid/setgid/initgroups with virSetUIDGID()
+
+This patch fixes https://bugzilla.redhat.com/show_bug.cgi?id=664406
+
+If qemu is run as a different uid, it has been unable to access mode
+0660 files that are owned by a different user, but with a group that
+the qemu is a member of (aside from the one group listed in the passwd
+file), because initgroups() is not being called prior to the
+exec. initgroups will change the group membership of the process (and
+its children) to match the new uid.
+
+To make this happen, the setregid()/setreuid() code in
+qemuSecurityDACSetProcessLabel has been replaced with a call to
+virSetUIDGID(), which does both of those, plus calls initgroups.
+
+Similar, but not identical, code in qemudOpenAsUID() has been replaced
+with virSetUIDGID(). This not only consolidates the functionality to a
+single location, but also potentially fixes some as-yet unreported
+bugs.
+
+---
+ src/qemu/qemu_driver.c       |   44 ++++++++++++++----------------------------
+ src/qemu/qemu_security_dac.c |   18 ++---------------
+ 2 files changed, 16 insertions(+), 46 deletions(-)
+
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 5629885..4843884 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -40,8 +40,6 @@
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <paths.h>
+-#include <pwd.h>
+-#include <grp.h>
+ #include <stdio.h>
+ #include <sys/wait.h>
+ #include <sys/ioctl.h>
+@@ -6242,7 +6240,9 @@ cleanup:
+    after it's finished reading (to avoid a zombie, if nothing
+    else). */
+ 
+-static int qemudOpenAsUID(const char *path, uid_t uid, pid_t *child_pid) {
++static int
++qemudOpenAsUID(const char *path, uid_t uid, gid_t gid, pid_t *child_pid)
++{
+     int pipefd[2];
+     int fd = -1;
+ 
+@@ -6309,7 +6309,6 @@ parent_cleanup:
+     char *buf = NULL;
+     size_t bufsize = 1024 * 1024;
+     int bytesread;
+-    struct passwd pwd, *pwd_result;
+ 
+     /* child doesn't need the read side of the pipe */
+     close(pipefd[0]);
+@@ -6322,33 +6321,11 @@ parent_cleanup:
+         goto child_cleanup;
+     }
+ 
+-    if (VIR_ALLOC_N(buf, bufsize) < 0) {
+-        exit_code = ENOMEM;
+-        virReportOOMError();
+-        goto child_cleanup;
++    if (virSetUIDGID(uid, gid) < 0) {
++       exit_code = errno;
++       goto child_cleanup;
+     }
+ 
+-    exit_code = getpwuid_r(uid, &pwd, buf, bufsize, &pwd_result);
+-    if (pwd_result == NULL) {
+-        virReportSystemError(errno,
+-                             _("cannot getpwuid_r(%d) to read '%s'"),
+-                             uid, path);
+-        goto child_cleanup;
+-    }
+-    if (initgroups(pwd.pw_name, pwd.pw_gid) != 0) {
+-        exit_code = errno;
+-        virReportSystemError(errno,
+-                             _("cannot initgroups(\"%s\", %d) to read '%s'"),
+-                             pwd.pw_name, pwd.pw_gid, path);
+-        goto child_cleanup;
+-    }
+-    if (setuid(uid) != 0) {
+-        exit_code = errno;
+-        virReportSystemError(errno,
+-                             _("cannot setuid(%d) to read '%s'"),
+-                             uid, path);
+-        goto child_cleanup;
+-    }
+     if ((fd = open(path, O_RDONLY)) < 0) {
+         exit_code = errno;
+         virReportSystemError(errno,
+@@ -6357,6 +6334,12 @@ parent_cleanup:
+         goto child_cleanup;
+     }
+ 
++    if (VIR_ALLOC_N(buf, bufsize) < 0) {
++        exit_code = ENOMEM;
++        virReportOOMError();
++        goto child_cleanup;
++    }
++
+     /* read from fd and write to pipefd[1] until EOF */
+     do {
+         if ((bytesread = saferead(fd, buf, bufsize)) < 0) {
+@@ -6428,7 +6411,8 @@ qemudDomainSaveImageOpen(struct qemud_driver *driver,
+            that might have better luck. Create a pipe, then fork a
+            child process to run as the qemu user, which will hopefully
+            have the necessary authority to read the file. */
+-        if ((fd = qemudOpenAsUID(path, driver->user, &read_pid)) < 0) {
++        if ((fd = qemudOpenAsUID(path,
++                                 driver->user, driver->group, &read_pid)) < 0) {
+             /* error already reported */
+             goto error;
+         }
+diff --git a/src/qemu/qemu_security_dac.c b/src/qemu/qemu_security_dac.c
+index 55dc0c6..b2841a1 100644
+--- a/src/qemu/qemu_security_dac.c
++++ b/src/qemu/qemu_security_dac.c
+@@ -549,22 +549,8 @@ qemuSecurityDACSetProcessLabel(virSecurityDriverPtr drv ATTRIBUTE_UNUSED,
+     if (!driver->privileged)
+         return 0;
+ 
+-    if (driver->group) {
+-        if (setregid(driver->group, driver->group) < 0) {
+-            virReportSystemError(errno,
+-                                 _("cannot change to '%d' group"),
+-                                 driver->group);
+-            return -1;
+-        }
+-    }
+-    if (driver->user) {
+-        if (setreuid(driver->user, driver->user) < 0) {
+-            virReportSystemError(errno,
+-                                 _("cannot change to '%d' user"),
+-                                 driver->user);
+-            return -1;
+-        }
+-    }
++    if (virSetUIDGID(driver->user, driver->group) < 0)
++       return -1;
+ 
+     return 0;
+ }
diff --git a/debian/patches/series b/debian/patches/series
index 1c3ce85..d9d07e2 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -14,3 +14,7 @@ security/0013-Add-missing-checks-for-read-only-connections.patch
 security/0014-Make-error-reporting-in-libvirtd-thread-safe.patch
 security/0015-Fix-integer-overflow-in-VirDomainGetVcpus.patch
 0016-Add-missing-return-on-error-path.patch
+security/0017-New-virSetUIDGID-utility-function.patch
+security/0018-Run-initgroups-in-qemudOpenAsUID.patch
+security/0019-Replace-setuid-setgid-initgroups-with-virSetUIDGID.patch
+0020-Rerun-autoconf.patch

-- 
Libvirt Debian packaging



More information about the Pkg-libvirt-commits mailing list