Merge pull request #2102 from brauner/2018-01-22/lsm_simplifications

lsm: simplifcations
This commit is contained in:
Serge Hallyn 2018-01-29 17:08:38 -06:00 committed by GitHub
commit 26f0e9151a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 179 additions and 136 deletions

View File

@ -258,11 +258,6 @@ if test "$enable_apparmor" = "auto" ; then
fi fi
AM_CONDITIONAL([ENABLE_APPARMOR], [test "x$enable_apparmor" = "xyes"]) 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 # GnuTLS
AC_ARG_ENABLE([gnutls], AC_ARG_ENABLE([gnutls],
[AC_HELP_STRING([--enable-gnutls], [enable GnuTLS support [default=auto]])], [AC_HELP_STRING([--enable-gnutls], [enable GnuTLS support [default=auto]])],

View File

@ -207,7 +207,7 @@ liblxc_la_LDFLAGS = \
-Wl,-soname,liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) \ -Wl,-soname,liblxc.so.$(firstword $(subst ., ,@LXC_ABI@)) \
-version-info @LXC_ABI_MAJOR@ -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 if ENABLE_CGMANAGER
liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS) liblxc_la_LIBADD += $(CGMANAGER_LIBS) $(DBUS_LIBS) $(NIH_LIBS) $(NIH_DBUS_LIBS)
@ -264,7 +264,7 @@ AM_LDFLAGS = -Wl,-E
if ENABLE_RPATH if ENABLE_RPATH
AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir) AM_LDFLAGS += -Wl,-rpath -Wl,$(libdir)
endif 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_attach_SOURCES = tools/lxc_attach.c tools/arguments.c
lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c lxc_autostart_SOURCES = tools/lxc_autostart.c tools/arguments.c

View File

@ -88,104 +88,6 @@
lxc_log_define(lxc_attach, lxc); 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;
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) */ /* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
#define __PROC_STATUS_LEN (5 + (LXC_NUMSTRLEN64) + 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) static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
@ -962,15 +864,15 @@ static int attach_child_main(struct attach_clone_payload *payload)
} }
if (needs_lsm) { if (needs_lsm) {
int on_exec; bool on_exec;
/* Change into our new LSM profile. */ /* Change into our new LSM profile. */
on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false;
ret = lsm_set_label_at(lsm_fd, on_exec, init_ctx->lsm_label); ret = lsm_process_label_set_at(lsm_fd, init_ctx->lsm_label, on_exec);
close(lsm_fd); close(lsm_fd);
if (ret < 0) if (ret < 0)
goto on_error; 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 && if (init_ctx->container && init_ctx->container->lxc_conf &&
@ -1409,11 +1311,12 @@ int lxc_attach(const char *name, const char *lxcpath,
if ((options->namespaces & CLONE_NEWNS) && if ((options->namespaces & CLONE_NEWNS) &&
(options->attach_flags & LXC_ATTACH_LSM) && (options->attach_flags & LXC_ATTACH_LSM) &&
init_ctx->lsm_label) { init_ctx->lsm_label) {
int labelfd, on_exec;
int ret = -1; int ret = -1;
int labelfd;
bool on_exec;
on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0; on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false;
labelfd = lsm_open(attached_pid, on_exec); labelfd = lsm_process_label_fd_get(attached_pid, on_exec);
if (labelfd < 0) if (labelfd < 0)
goto close_mainloop; goto close_mainloop;
TRACE("Opened LSM label file descriptor %d", labelfd); TRACE("Opened LSM label file descriptor %d", labelfd);

View File

@ -25,11 +25,10 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/apparmor.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include "log.h" #include "log.h"
#include "lsm/lsm.h" #include "lsm.h"
#include "conf.h" #include "conf.h"
#include "utils.h" #include "utils.h"
@ -172,8 +171,10 @@ static bool aa_needs_transition(char *curlabel)
* Notes: This relies on /proc being available. * Notes: This relies on /proc being available.
*/ */
static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, 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)
{ {
int label_fd, ret;
pid_t tid;
const char *label = inlabel ? inlabel : conf->lsm_aa_profile; const char *label = inlabel ? inlabel : conf->lsm_aa_profile;
char *curlabel; char *curlabel;
@ -230,12 +231,21 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
return 0; return 0;
} }
if (aa_change_profile(label) < 0) { tid = lxc_raw_gettid();
SYSERROR("failed to change apparmor profile to %s", label); 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; 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; return 0;
} }

View File

@ -85,8 +85,97 @@ char *lsm_process_label_get(pid_t pid)
return drv->process_label_get(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_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, 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) { if (!drv) {
ERROR("LSM driver not inited"); ERROR("LSM driver not inited");

View File

@ -28,29 +28,66 @@ struct lxc_conf;
#include <sys/types.h> #include <sys/types.h>
#include "../utils.h"
#define LXC_LSMATTRLEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
struct lsm_drv { struct lsm_drv {
const char *name; const char *name;
int (*enabled)(void); int (*enabled)(void);
char *(*process_label_get)(pid_t pid); char *(*process_label_get)(pid_t pid);
int (*process_label_set)(const char *label, struct lxc_conf *conf, int (*process_label_set)(const char *label, struct lxc_conf *conf,
int use_default, int on_exec); bool use_default, bool on_exec);
}; };
#if HAVE_APPARMOR || HAVE_SELINUX #if HAVE_APPARMOR || HAVE_SELINUX
void lsm_init(void); extern void lsm_init(void);
int lsm_enabled(void); extern int lsm_enabled(void);
const char *lsm_name(void); extern const char *lsm_name(void);
char *lsm_process_label_get(pid_t pid); extern char *lsm_process_label_get(pid_t pid);
int lsm_process_label_set(const char *label, struct lxc_conf *conf, extern int lsm_process_label_set(const char *label, struct lxc_conf *conf,
int use_default, int on_exec); 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 #else
static inline void lsm_init(void) { } static inline void lsm_init(void)
static inline int lsm_enabled(void) { return 0; } {
static inline const char *lsm_name(void) { return "none"; } return;
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 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;
}
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
#endif #endif

View File

@ -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, 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; return 0;
} }

View File

@ -72,7 +72,7 @@ static char *selinux_process_label_get(pid_t pid)
* Notes: This relies on /proc being available. * Notes: This relies on /proc being available.
*/ */
static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf, 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; const char *label = inlabel ? inlabel : conf->lsm_se_context;
if (!label) { if (!label) {

View File

@ -565,4 +565,13 @@ static inline uint64_t lxc_getpagesize(void)
*/ */
extern uint64_t lxc_find_next_power2(uint64_t n); 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 */ #endif /* __LXC_UTILS_H */