]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
rexec: make rexecution opt-in for library callers 2846/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Tue, 12 Feb 2019 16:31:14 +0000 (17:31 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 12 Feb 2019 16:58:34 +0000 (17:58 +0100)
We cannot rexecute the liblxc shared library unconditionally as this would
break most of our downstreams. Here are some scenarios:
- anyone performing a dlopen() on the shared library (e.g. users of the LXC
  Python bindings)
- LXD as it needs to know the absolute path to its own executable based on
  /proc/self/exe etc.

This commit makes the rexecution of liblxc conditional on whether the
LXC_MEMFD_REXEC environment variable is set or not. If it is then liblxc is
unconditionally rexecuted.

The only relevant attack vector exists for lxc-attach which we simply reexecute
unconditionally.

Reported-by: Stéphane Graber <stgraber@ubuntu.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/Makefile.am
src/lxc/rexec.c
src/lxc/rexec.h [new file with mode: 0644]
src/lxc/tools/lxc_attach.c

index e1499a7ebe3f1b714949cd2389c4ca6efd922e20..ef19df9e082d72f16ccbed4099aa483eecb1edf5 100644 (file)
@@ -25,6 +25,7 @@ noinst_HEADERS = api_extensions.h \
                 monitor.h \
                 namespace.h \
                 raw_syscalls.h \
+                rexec.h \
                 start.h \
                 state.h \
                 storage/btrfs.h \
@@ -180,7 +181,7 @@ liblxc_la_SOURCES += ../include/strlcat.c ../include/strlcat.h
 endif
 
 if ENFORCE_MEMFD_REXEC
-liblxc_la_SOURCES += rexec.c
+liblxc_la_SOURCES += rexec.c rexec.h
 endif
 
 AM_CFLAGS = -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
@@ -307,6 +308,7 @@ LDADD = liblxc.la \
 
 if ENABLE_TOOLS
 lxc_attach_SOURCES = tools/lxc_attach.c \
+                    rexec.c rexec.h \
                     tools/arguments.c tools/arguments.h
 lxc_autostart_SOURCES = tools/lxc_autostart.c \
                        tools/arguments.c tools/arguments.h
index 3ce499b1e253a5c20ce3c5f54712731a154a9ab8..024728d855d484dacfdd9608d80bd9fe31da6429 100644 (file)
@@ -142,7 +142,7 @@ on_error:
        errno = saved_errno;
 }
 
-static int lxc_rexec(const char *memfd_name)
+int lxc_rexec(const char *memfd_name)
 {
        int ret;
        char **argv = NULL, **envp = NULL;
@@ -179,7 +179,7 @@ static int lxc_rexec(const char *memfd_name)
  */
 __attribute__((constructor)) static void liblxc_rexec(void)
 {
-       if (lxc_rexec("liblxc")) {
+       if (getenv("LXC_MEMFD_REXEC") && lxc_rexec("liblxc")) {
                fprintf(stderr, "Failed to re-execute liblxc via memory file descriptor\n");
                _exit(EXIT_FAILURE);
        }
diff --git a/src/lxc/rexec.h b/src/lxc/rexec.h
new file mode 100644 (file)
index 0000000..088ded9
--- /dev/null
@@ -0,0 +1,26 @@
+/* liblxcapi
+ *
+ * Copyright © 2019 Christian Brauner <christian.brauner@ubuntu.com>.
+ * Copyright © 2019 Canonical Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __LXC_REXEC_H
+#define __LXC_REXEC_H
+
+extern int lxc_rexec(const char *memfd_name);
+
+#endif /* __LXC_REXEC_H */
index 3de0d7747f3392dcd40bd87b2ef0107b328a03ec..d10b6ecc23847d23350bda58bc89859588e87a11 100644 (file)
 #include "config.h"
 #include "confile.h"
 #include "log.h"
+#include "rexec.h"
 #include "utils.h"
 
 lxc_log_define(lxc_attach, lxc);
 
+/**
+ * This function will copy any binary that calls liblxc into a memory file and
+ * will use the memfd to rexecute the binary. This is done to prevent attacks
+ * through the /proc/self/exe symlink to corrupt the host binary when host and
+ * container are in the same user namespace or have set up an identity id
+ * mapping: CVE-2019-5736.
+ */
+#ifdef ENFORCE_MEMFD_REXEC
+__attribute__((constructor)) static void lxc_attach_rexec(void)
+{
+       if (!getenv("LXC_MEMFD_REXEC") && lxc_rexec("lxc-attach")) {
+               fprintf(stderr, "Failed to re-execute lxc-attach via memory file descriptor\n");
+               _exit(EXIT_FAILURE);
+       }
+}
+#endif
+
 static int my_parser(struct lxc_arguments *args, int c, char *arg);
 static int add_to_simple_array(char ***array, ssize_t *capacity, char *value);
 static bool stdfd_is_pty(void);