c401cc
From e879d4e45082bb2d43c45704b7d9592eebcc09b4 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <e879d4e45082bb2d43c45704b7d9592eebcc09b4.1390394206.git.jdenemar@redhat.com>
c401cc
From: Eric Blake <eblake@redhat.com>
c401cc
Date: Fri, 17 Jan 2014 10:35:01 -0700
c401cc
Subject: [PATCH] virt-login-shell: fix regressions in behavior
c401cc
c401cc
https://bugzilla.redhat.com/show_bug.cgi?id=1015247
c401cc
c401cc
Our fixes for CVE-2013-4400 were so effective at "fixing" bugs
c401cc
in virt-login-shell that we ended up fixing it into a useless
c401cc
do-nothing program.
c401cc
c401cc
Commit 3e2f27e1 picked the name LIBVIRT_SETUID_RPC_CLIENT for
c401cc
the witness macro when we are doing secure compilation.  But
c401cc
commit 9cd6a57d checked whether the name IN_VIRT_LOGIN_SHELL,
c401cc
from an earlier version of the patch series, was defined; with
c401cc
the net result that virt-login-shell invariably detected that
c401cc
it was setuid and failed virInitialize.
c401cc
c401cc
Commit b7fcc799 closed all fds larger than stderr, but in the
c401cc
wrong place.  Looking at the larger context, we mistakenly did
c401cc
the close in between obtaining the set of namespace fds, then
c401cc
actually using those fds to switch namespace, which means that
c401cc
virt-login-shell will ALWAYS fail.
c401cc
c401cc
This is the minimal patch to fix the regressions, although
c401cc
further patches are also worth having to clean up poor
c401cc
semantics of the resulting program (for example, it is rude to
c401cc
not pass on the exit status of the wrapped program back to the
c401cc
invoking shell).
c401cc
c401cc
* tools/virt-login-shell.c (main): Don't close fds until after
c401cc
namespace swap.
c401cc
* src/libvirt.c (virGlobalInit): Use correct macro.
c401cc
c401cc
Signed-off-by: Eric Blake <eblake@redhat.com>
c401cc
(cherry picked from commit 3d007cb5f892bb9fd3f6efac6dc89a8e00e94922)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/libvirt.c            |  2 +-
c401cc
 tools/virt-login-shell.c | 21 +++++++++++----------
c401cc
 2 files changed, 12 insertions(+), 11 deletions(-)
c401cc
c401cc
diff --git a/src/libvirt.c b/src/libvirt.c
c401cc
index 31600e8..61cae03 100644
c401cc
--- a/src/libvirt.c
c401cc
+++ b/src/libvirt.c
c401cc
@@ -409,7 +409,7 @@ virGlobalInit(void)
c401cc
         virErrorInitialize() < 0)
c401cc
         goto error;
c401cc
 
c401cc
-#ifndef IN_VIRT_LOGIN_SHELL
c401cc
+#ifndef LIBVIRT_SETUID_RPC_CLIENT
c401cc
     if (virIsSUID()) {
c401cc
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
                        _("libvirt.so is not safe to use from setuid programs"));
c401cc
diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
c401cc
index baa6202..a9a406c 100644
c401cc
--- a/tools/virt-login-shell.c
c401cc
+++ b/tools/virt-login-shell.c
c401cc
@@ -1,7 +1,7 @@
c401cc
 /*
c401cc
  * virt-login-shell.c: a shell to connect to a container
c401cc
  *
c401cc
- * Copyright (C) 2013 Red Hat, Inc.
c401cc
+ * Copyright (C) 2013-2014 Red Hat, Inc.
c401cc
  *
c401cc
  * This library is free software; you can redistribute it and/or
c401cc
  * modify it under the terms of the GNU Lesser General Public
c401cc
@@ -312,15 +312,6 @@ main(int argc, char **argv)
c401cc
 
c401cc
         int openmax = sysconf(_SC_OPEN_MAX);
c401cc
         int fd;
c401cc
-        if (openmax < 0) {
c401cc
-            virReportSystemError(errno,  "%s",
c401cc
-                                 _("sysconf(_SC_OPEN_MAX) failed"));
c401cc
-            return EXIT_FAILURE;
c401cc
-        }
c401cc
-        for (fd = 3; fd < openmax; fd++) {
c401cc
-            int tmpfd = fd;
c401cc
-            VIR_MASS_CLOSE(tmpfd);
c401cc
-        }
c401cc
 
c401cc
         /* Fork once because we don't want to affect
c401cc
          * virt-login-shell's namespace itself
c401cc
@@ -349,6 +340,16 @@ main(int argc, char **argv)
c401cc
         if (ret < 0)
c401cc
             return EXIT_FAILURE;
c401cc
 
c401cc
+        if (openmax < 0) {
c401cc
+            virReportSystemError(errno,  "%s",
c401cc
+                                 _("sysconf(_SC_OPEN_MAX) failed"));
c401cc
+            return EXIT_FAILURE;
c401cc
+        }
c401cc
+        for (fd = 3; fd < openmax; fd++) {
c401cc
+            int tmpfd = fd;
c401cc
+            VIR_MASS_CLOSE(tmpfd);
c401cc
+        }
c401cc
+
c401cc
         if (virFork(&ccpid) < 0)
c401cc
             return EXIT_FAILURE;
c401cc
 
c401cc
-- 
c401cc
1.8.5.3
c401cc