From e6e899749af3a28323fe12499dbed1faef4cacca Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 22 Jan 2018 10:48:56 +0100 Subject: [PATCH 1/5] lsm: non-functional changes Signed-off-by: Christian Brauner --- src/lxc/lsm/apparmor.c | 2 +- src/lxc/lsm/lsm.c | 2 +- src/lxc/lsm/lsm.h | 53 ++++++++++++++++++++++++++++++------------ src/lxc/lsm/nop.c | 2 +- src/lxc/lsm/selinux.c | 2 +- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/lxc/lsm/apparmor.c b/src/lxc/lsm/apparmor.c index 2faa9a20d..0021001ac 100644 --- a/src/lxc/lsm/apparmor.c +++ b/src/lxc/lsm/apparmor.c @@ -172,7 +172,7 @@ static bool aa_needs_transition(char *curlabel) * Notes: This relies on /proc being available. */ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, - int use_default, int on_exec) + bool use_default, bool on_exec) { const char *label = inlabel ? inlabel : conf->lsm_aa_profile; char *curlabel; diff --git a/src/lxc/lsm/lsm.c b/src/lxc/lsm/lsm.c index 79f837fc6..75f20f13b 100644 --- a/src/lxc/lsm/lsm.c +++ b/src/lxc/lsm/lsm.c @@ -86,7 +86,7 @@ char *lsm_process_label_get(pid_t pid) } int lsm_process_label_set(const char *label, struct lxc_conf *conf, - int use_default, int on_exec) + bool use_default, bool on_exec) { if (!drv) { ERROR("LSM driver not inited"); diff --git a/src/lxc/lsm/lsm.h b/src/lxc/lsm/lsm.h index b915e8ddd..3b08b3be7 100644 --- a/src/lxc/lsm/lsm.h +++ b/src/lxc/lsm/lsm.h @@ -28,29 +28,52 @@ struct lxc_conf; #include +#include "../utils.h" + +#define LXC_LSMATTRLEN (5 + (LXC_NUMSTRLEN64) + 7 + 1) + struct lsm_drv { const char *name; - int (*enabled)(void); + int (*enabled)(void); char *(*process_label_get)(pid_t pid); - int (*process_label_set)(const char *label, struct lxc_conf *conf, - int use_default, int on_exec); + int (*process_label_set)(const char *label, struct lxc_conf *conf, + bool use_default, bool on_exec); }; #if HAVE_APPARMOR || HAVE_SELINUX -void lsm_init(void); -int lsm_enabled(void); -const char *lsm_name(void); -char *lsm_process_label_get(pid_t pid); -int lsm_process_label_set(const char *label, struct lxc_conf *conf, - int use_default, int on_exec); +extern void lsm_init(void); +extern int lsm_enabled(void); +extern const char *lsm_name(void); +extern char *lsm_process_label_get(pid_t pid); +extern int lsm_process_label_set(const char *label, struct lxc_conf *conf, + bool use_default, bool on_exec); #else -static inline void lsm_init(void) { } -static inline int lsm_enabled(void) { return 0; } -static inline const char *lsm_name(void) { return "none"; } -static inline char *lsm_process_label_get(pid_t pid) { return NULL; } -static inline int lsm_process_label_set(const char *label, - struct lxc_conf *conf, int use_default, int on_exec) { return 0; } +static inline void lsm_init(void) +{ + return; +} + +static inline int lsm_enabled(void) { + return 0; +} + +static inline const char *lsm_name(void) +{ + return "none"; +} + +static inline char *lsm_process_label_get(pid_t pid) +{ + return NULL; +} + +static inline int lsm_process_label_set(const char *label, + struct lxc_conf *conf, bool use_default, + bool on_exec) +{ + return 0; +} #endif #endif diff --git a/src/lxc/lsm/nop.c b/src/lxc/lsm/nop.c index c13d8f528..7bb8121b8 100644 --- a/src/lxc/lsm/nop.c +++ b/src/lxc/lsm/nop.c @@ -30,7 +30,7 @@ static char *nop_process_label_get(pid_t pid) } static int nop_process_label_set(const char *label, struct lxc_conf *conf, - int use_default, int on_exec) + bool use_default, bool on_exec) { return 0; } diff --git a/src/lxc/lsm/selinux.c b/src/lxc/lsm/selinux.c index 46554d84c..857fe29a8 100644 --- a/src/lxc/lsm/selinux.c +++ b/src/lxc/lsm/selinux.c @@ -72,7 +72,7 @@ static char *selinux_process_label_get(pid_t pid) * Notes: This relies on /proc being available. */ static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf, - int use_default, int on_exec) + bool use_default, bool on_exec) { const char *label = inlabel ? inlabel : conf->lsm_se_context; if (!label) { From 47ce2cb727eb0e306ab652910cf0b3fdd5cf7e24 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 22 Jan 2018 10:54:38 +0100 Subject: [PATCH 2/5] lsm: add lsm_process_label_fd_get() Signed-off-by: Christian Brauner --- src/lxc/attach.c | 45 ++++----------------------------------------- src/lxc/lsm/lsm.c | 36 ++++++++++++++++++++++++++++++++++++ src/lxc/lsm/lsm.h | 6 ++++++ 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 34bdf9145..369d88183 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -88,44 +88,6 @@ lxc_log_define(lxc_attach, lxc); -/* /proc/pid-to-str/current\0 = (5 + 21 + 7 + 1) */ -#define __LSMATTRLEN (5 + (LXC_NUMSTRLEN64) + 7 + 1) -static int lsm_open(pid_t pid, int on_exec) -{ - const char *name; - char path[__LSMATTRLEN]; - int ret = -1; - int labelfd = -1; - - name = lsm_name(); - - if (strcmp(name, "nop") == 0) - return 0; - - if (strcmp(name, "none") == 0) - return 0; - - /* We don't support on-exec with AppArmor */ - if (strcmp(name, "AppArmor") == 0) - on_exec = 0; - - if (on_exec) - ret = snprintf(path, __LSMATTRLEN, "/proc/%d/attr/exec", pid); - else - ret = snprintf(path, __LSMATTRLEN, "/proc/%d/attr/current", pid); - if (ret < 0 || ret >= __LSMATTRLEN) - return -1; - - labelfd = open(path, O_RDWR); - if (labelfd < 0) { - SYSERROR("%s - Unable to open file descriptor to set LSM label", - strerror(errno)); - return -1; - } - - return labelfd; -} - static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label) { int fret = -1; @@ -1396,11 +1358,12 @@ int lxc_attach(const char *name, const char *lxcpath, if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) { - int labelfd, on_exec; int ret = -1; + int labelfd; + bool on_exec; - on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; - labelfd = lsm_open(attached_pid, on_exec); + on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false; + labelfd = lsm_process_label_fd_get(attached_pid, on_exec); if (labelfd < 0) goto close_mainloop; TRACE("Opened LSM label file descriptor %d", labelfd); diff --git a/src/lxc/lsm/lsm.c b/src/lxc/lsm/lsm.c index 75f20f13b..98bf083bb 100644 --- a/src/lxc/lsm/lsm.c +++ b/src/lxc/lsm/lsm.c @@ -85,6 +85,42 @@ char *lsm_process_label_get(pid_t pid) return drv->process_label_get(pid); } +int lsm_process_label_fd_get(pid_t pid, bool on_exec) +{ + int ret = -1; + int labelfd = -1; + const char *name; + char path[LXC_LSMATTRLEN]; + + name = lsm_name(); + + if (strcmp(name, "nop") == 0) + return 0; + + if (strcmp(name, "none") == 0) + return 0; + + /* We don't support on-exec with AppArmor */ + if (strcmp(name, "AppArmor") == 0) + on_exec = 0; + + if (on_exec) + ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/exec", pid); + else + ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/current", pid); + if (ret < 0 || ret >= LXC_LSMATTRLEN) + return -1; + + labelfd = open(path, O_RDWR); + if (labelfd < 0) { + SYSERROR("%s - Unable to %s LSM label file descriptor", + name, strerror(errno)); + return -1; + } + + return labelfd; +} + int lsm_process_label_set(const char *label, struct lxc_conf *conf, bool use_default, bool on_exec) { diff --git a/src/lxc/lsm/lsm.h b/src/lxc/lsm/lsm.h index 3b08b3be7..db8738411 100644 --- a/src/lxc/lsm/lsm.h +++ b/src/lxc/lsm/lsm.h @@ -48,6 +48,7 @@ extern const char *lsm_name(void); extern char *lsm_process_label_get(pid_t pid); extern int lsm_process_label_set(const char *label, struct lxc_conf *conf, bool use_default, bool on_exec); +extern int lsm_process_label_fd_get(pid_t pid, bool on_exec); #else static inline void lsm_init(void) { @@ -74,6 +75,11 @@ static inline int lsm_process_label_set(const char *label, { return 0; } + +static inline int lsm_process_label_fd_get(pid_t pid, bool on_exec) +{ + return 0; +} #endif #endif From d3ba7c987201cb461ed92c027e9f424737fbe341 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 22 Jan 2018 11:54:21 +0100 Subject: [PATCH 3/5] lsm: add lsm_process_label_set_at() Signed-off-by: Christian Brauner --- src/lxc/attach.c | 68 +++-------------------------------------------- src/lxc/lsm/lsm.c | 53 ++++++++++++++++++++++++++++++++++++ src/lxc/lsm/lsm.h | 8 ++++++ 3 files changed, 65 insertions(+), 64 deletions(-) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 369d88183..45979bcdc 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -88,66 +88,6 @@ lxc_log_define(lxc_attach, lxc); -static int lsm_set_label_at(int lsm_labelfd, int on_exec, char *lsm_label) -{ - int fret = -1; - const char *name; - char *command = NULL; - - name = lsm_name(); - - if (strcmp(name, "nop") == 0) - return 0; - - if (strcmp(name, "none") == 0) - return 0; - - /* We don't support on-exec with AppArmor */ - if (strcmp(name, "AppArmor") == 0) - on_exec = 0; - - if (strcmp(name, "AppArmor") == 0) { - int size; - - command = - malloc(strlen(lsm_label) + strlen("changeprofile ") + 1); - if (!command) { - SYSERROR("Failed to write apparmor profile."); - goto out; - } - - size = sprintf(command, "changeprofile %s", lsm_label); - if (size < 0) { - SYSERROR("Failed to write apparmor profile."); - goto out; - } - - if (write(lsm_labelfd, command, size + 1) < 0) { - SYSERROR("Unable to set LSM label: %s.", command); - goto out; - } - INFO("Set LSM label to: %s.", command); - } else if (strcmp(name, "SELinux") == 0) { - if (write(lsm_labelfd, lsm_label, strlen(lsm_label) + 1) < 0) { - SYSERROR("Unable to set LSM label: %s.", lsm_label); - goto out; - } - INFO("Set LSM label to: %s.", lsm_label); - } else { - ERROR("Unable to restore label for unknown LSM: %s.", name); - goto out; - } - fret = 0; - -out: - free(command); - - if (lsm_labelfd != -1) - close(lsm_labelfd); - - return fret; -} - /* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */ #define __PROC_STATUS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1) static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid) @@ -922,15 +862,15 @@ static int attach_child_main(struct attach_clone_payload *payload) } if (needs_lsm) { - int on_exec; + bool on_exec; /* Change into our new LSM profile. */ - on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; - ret = lsm_set_label_at(lsm_fd, on_exec, init_ctx->lsm_label); + on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false; + ret = lsm_process_label_set_at(lsm_fd, init_ctx->lsm_label, on_exec); close(lsm_fd); if (ret < 0) goto on_error; - TRACE("Set LSM label"); + TRACE("Set %s LSM label to \"%s\"", lsm_name(), init_ctx->lsm_label); } if (init_ctx->container && init_ctx->container->lxc_conf && diff --git a/src/lxc/lsm/lsm.c b/src/lxc/lsm/lsm.c index 98bf083bb..677f53a61 100644 --- a/src/lxc/lsm/lsm.c +++ b/src/lxc/lsm/lsm.c @@ -121,6 +121,59 @@ int lsm_process_label_fd_get(pid_t pid, bool on_exec) return labelfd; } +int lsm_process_label_set_at(int label_fd, const char *label, bool on_exec) +{ + int ret = -1; + const char *name; + + name = lsm_name(); + + if (strcmp(name, "nop") == 0) + return 0; + + if (strcmp(name, "none") == 0) + return 0; + + /* We don't support on-exec with AppArmor */ + if (strcmp(name, "AppArmor") == 0) + on_exec = false; + + if (strcmp(name, "AppArmor") == 0) { + size_t len; + char *command; + + if (on_exec) { + ERROR("Changing AppArmor profile on exec not supported"); + return -EINVAL; + } + + len = strlen(label) + strlen("changeprofile ") + 1; + command = malloc(len); + if (!command) + return -1; + + ret = snprintf(command, len, "changeprofile %s", label); + if (ret < 0 || (size_t)ret >= len) { + free(command); + return -1; + } + + ret = lxc_write_nointr(label_fd, command, len - 1); + free(command); + } else if (strcmp(name, "SELinux") == 0) { + ret = lxc_write_nointr(label_fd, label, strlen(label)); + } else { + ret = -EINVAL; + } + if (ret < 0) { + SYSERROR("Failed to set %s label \"%s\"", name, label); + return -1; + } + + INFO("Set %s label to \"%s\"", name, label); + return 0; +} + int lsm_process_label_set(const char *label, struct lxc_conf *conf, bool use_default, bool on_exec) { diff --git a/src/lxc/lsm/lsm.h b/src/lxc/lsm/lsm.h index db8738411..33a412b7b 100644 --- a/src/lxc/lsm/lsm.h +++ b/src/lxc/lsm/lsm.h @@ -49,6 +49,8 @@ extern char *lsm_process_label_get(pid_t pid); extern int lsm_process_label_set(const char *label, struct lxc_conf *conf, bool use_default, bool on_exec); extern int lsm_process_label_fd_get(pid_t pid, bool on_exec); +extern int lsm_process_label_set_at(int label_fd, const char *label, + bool on_exec); #else static inline void lsm_init(void) { @@ -80,6 +82,12 @@ static inline int lsm_process_label_fd_get(pid_t pid, bool on_exec) { return 0; } + +extern int lsm_process_label_set_at(int label_fd, const char *label, + bool on_exec) +{ + return 0; +} #endif #endif From 5288a74faaa59680cab48f339e97c4ed6ce2a139 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 22 Jan 2018 12:02:44 +0100 Subject: [PATCH 4/5] apparmor: do not call aa_change_profile() We can simply write the label ourselves. There's no magic happening. Signed-off-by: Christian Brauner --- src/lxc/lsm/apparmor.c | 20 +++++++++++++++----- src/lxc/utils.h | 9 +++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/lxc/lsm/apparmor.c b/src/lxc/lsm/apparmor.c index 0021001ac..85b70de8d 100644 --- a/src/lxc/lsm/apparmor.c +++ b/src/lxc/lsm/apparmor.c @@ -25,11 +25,10 @@ #include #include #include -#include #include #include "log.h" -#include "lsm/lsm.h" +#include "lsm.h" #include "conf.h" #include "utils.h" @@ -174,6 +173,8 @@ static bool aa_needs_transition(char *curlabel) static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, bool use_default, bool on_exec) { + int label_fd, ret; + pid_t tid; const char *label = inlabel ? inlabel : conf->lsm_aa_profile; char *curlabel; @@ -230,12 +231,21 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf return 0; } - if (aa_change_profile(label) < 0) { - SYSERROR("failed to change apparmor profile to %s", label); + tid = lxc_raw_gettid(); + label_fd = lsm_process_label_fd_get(tid, on_exec); + if (label_fd < 0) { + SYSERROR("Failed to change apparmor profile to %s", label); return -1; } - INFO("changed apparmor profile to %s", label); + ret = lsm_process_label_set_at(label_fd, label, on_exec); + close(label_fd); + if (ret < 0) { + SYSERROR("Failed to change apparmor profile to %s", label); + return -1; + } + + INFO("Changed apparmor profile to %s", label); return 0; } diff --git a/src/lxc/utils.h b/src/lxc/utils.h index f8cf26fbf..188b646a3 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -541,4 +541,13 @@ static inline uint64_t lxc_getpagesize(void) */ extern uint64_t lxc_find_next_power2(uint64_t n); +static inline pid_t lxc_raw_gettid(void) +{ +#ifdef SYS_gettid + return syscall(SYS_gettid); +#else + return lxc_raw_getpid(); +#endif +} + #endif /* __LXC_UTILS_H */ From 05f0f93a93452070006524ac22a6f51e19f8271f Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Mon, 22 Jan 2018 12:14:21 +0100 Subject: [PATCH 5/5] autotools: do not link against libapparmor Since we write the label directly without going through the AppArmor API it doesn't make sense to link against it. Signed-off-by: Christian Brauner --- configure.ac | 5 ----- src/lxc/Makefile.am | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 0bcd75a28..6713539b4 100644 --- a/configure.ac +++ b/configure.ac @@ -258,11 +258,6 @@ if test "$enable_apparmor" = "auto" ; then fi AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"]) -AM_COND_IF([ENABLE_APPARMOR], - [AC_CHECK_HEADER([sys/apparmor.h],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])]) - AC_CHECK_LIB([apparmor], [aa_change_profile],[],[AC_MSG_ERROR([You must install the AppArmor development package in order to compile lxc])]) - AC_SUBST([APPARMOR_LIBS], [-lapparmor])]) - # GnuTLS AC_ARG_ENABLE([gnutls], [AC_HELP_STRING([--enable-gnutls], [enable GnuTLS support [default=auto]])], diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index 895684e0b..8f9a7ab29 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -207,7 +207,7 @@ liblxc_la_LDFLAGS = \ -Wl,-soname,liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) \ -version-info @LXC_ABI_MAJOR@ -liblxc_la_LIBADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS) +liblxc_la_LIBADD = $(CAP_LIBS) $(SELINUX_LIBS) $(SECCOMP_LIBS) if ENABLE_CGMANAGER liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS) @@ -264,7 +264,7 @@ AM_LDFLAGS = -Wl,-E if ENABLE_RPATH AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir) endif -LDADD=liblxc.la @CAP_LIBS@ @APPARMOR_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@ +LDADD=liblxc.la @CAP_LIBS@ @SELINUX_LIBS@ @SECCOMP_LIBS@ lxc_attach_SOURCES = tools/lxc_attach.c tools/arguments.c lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c