Skip to content

Commit

Permalink
refactor AppArmor into LSM backend, add SELinux support
Browse files Browse the repository at this point in the history
Currently, a maximum of one LSM within LXC will be initialized and
used. If in the future stacked LSMs become a reality, we can support it
without changing the configuration syntax and add support for more than
a single LSM at a time to the lsm code.

Generic LXC code should note that lsm_process_label_set() will take
effect "now" for AppArmor, and upon exec() for SELinux.

- fix Oracle template mounting of proc and sysfs, needed when using SELinux

Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
Acked-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
  • Loading branch information
Dwight Engen authored and hallyn committed Sep 25, 2013
1 parent 3a0abb3 commit fe4de9a
Show file tree
Hide file tree
Showing 17 changed files with 562 additions and 265 deletions.
14 changes: 14 additions & 0 deletions configure.ac
Expand Up @@ -117,6 +117,20 @@ AM_COND_IF([ENABLE_APPARMOR],
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])])

# SELinux
AC_ARG_ENABLE([selinux],
[AC_HELP_STRING([--enable-selinux], [enable SELinux support])],
[], [enable_selinux=check])

if test "x$enable_selinux" = xcheck; then
AC_CHECK_LIB([selinux],[setexeccon_raw],[enable_selinux=yes],[enable_selinux=no])
fi
AM_CONDITIONAL([ENABLE_SELINUX], [test "x$enable_selinux" = "xyes"])
AM_COND_IF([ENABLE_SELINUX],
[AC_CHECK_HEADER([selinux/selinux.h],[],[AC_MSG_ERROR([You must install the SELinux development package in order to compile lxc])])
AC_CHECK_LIB([selinux], [setexeccon_raw],[],[AC_MSG_ERROR([You must install the SELinux development package in order to compile lxc])])
AC_SUBST([SELINUX_LIBS])])

# Seccomp syscall filter
AC_ARG_ENABLE([seccomp],
[AC_HELP_STRING([--enable-seccomp], [enable seccomp])],
Expand Down
25 changes: 25 additions & 0 deletions doc/lxc.conf.sgml.in
Expand Up @@ -810,6 +810,31 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
</variablelist>
</refsect2>

<refsect2>
<title>SELinux context</title>
<para>
If lxc was compiled and installed with SELinux support, and the host
system has SELinux enabled, then the SELinux context under which the
container should be run can be specified in the container
configuration. The default is <command>unconfined_t</command>,
which means that lxc will not attempt to change contexts.
</para>
<variablelist>
<varlistentry>
<term>
<option>lxc.se_context</option>
</term>
<listitem>
<para>
Specify the SELinux context under which the container should
be run or <command>unconfined_t</command>. For example
</para>
<programlisting>lxc.se_context = unconfined_u:unconfined_r:lxc_t:s0-s0:c0.c1023</programlisting>
</listitem>
</varlistentry>
</variablelist>
</refsect2>

<refsect2>
<title>Seccomp configuration</title>
<para>
Expand Down
21 changes: 19 additions & 2 deletions src/lxc/Makefile.am
Expand Up @@ -37,6 +37,18 @@ sodir=$(libdir)
# use PROGRAMS to avoid complains from automake
so_PROGRAMS = liblxc.so

LSM_SOURCES = \
lsm/nop.c \
lsm/lsm.h lsm/lsm.c

if ENABLE_APPARMOR
LSM_SOURCES += lsm/apparmor.c
endif

if ENABLE_SELINUX
LSM_SOURCES += lsm/selinux.c
endif

liblxc_so_SOURCES = \
arguments.c arguments.h \
bdev.c bdev.h \
Expand Down Expand Up @@ -73,10 +85,11 @@ liblxc_so_SOURCES = \
af_unix.c af_unix.h \
\
lxcutmp.c lxcutmp.h \
apparmor.c apparmor.h \
lxclock.h lxclock.c \
lxccontainer.c lxccontainer.h \
version.c version.h
version.c version.h \
\
$(LSM_SOURCES)

if IS_BIONIC
liblxc_so_SOURCES += \
Expand Down Expand Up @@ -107,6 +120,10 @@ if ENABLE_APPARMOR
AM_CFLAGS += -DHAVE_APPARMOR
endif

if ENABLE_SELINUX
AM_CFLAGS += -DHAVE_SELINUX
endif

if HAVE_NEWUIDMAP
AM_CFLAGS += -DHAVE_NEWUIDMAP
endif
Expand Down
56 changes: 0 additions & 56 deletions src/lxc/apparmor.h

This file was deleted.

31 changes: 16 additions & 15 deletions src/lxc/attach.c
Expand Up @@ -46,11 +46,11 @@
#include "attach.h"
#include "caps.h"
#include "config.h"
#include "apparmor.h"
#include "utils.h"
#include "commands.h"
#include "cgroup.h"
#include "lxclock.h"
#include "lsm/lsm.h"

#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
Expand Down Expand Up @@ -129,7 +129,7 @@ struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
errno = ENOENT;
goto out_error;
}
info->aa_profile = aa_get_profile(pid);
info->lsm_label = lsm_process_label_get(pid);

return info;

Expand All @@ -138,6 +138,13 @@ struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
return NULL;
}

static void lxc_proc_put_context_info(struct lxc_proc_context_info *ctx)
{
if (ctx->lsm_label)
free(ctx->lsm_label);
free(ctx);
}

int lxc_attach_to_ns(pid_t pid, int which)
{
char path[MAXPATHLEN];
Expand Down Expand Up @@ -644,8 +651,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
ERROR("failed to automatically determine the "
"namespaces which the container unshared");
free(cwd);
free(init_ctx->aa_profile);
free(init_ctx);
lxc_proc_put_context_info(init_ctx);
return -1;
}
}
Expand Down Expand Up @@ -683,8 +689,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
if (ret < 0) {
SYSERROR("could not set up required IPC mechanism for attaching");
free(cwd);
free(init_ctx->aa_profile);
free(init_ctx);
lxc_proc_put_context_info(init_ctx);
return -1;
}

Expand All @@ -705,8 +710,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
if (pid < 0) {
SYSERROR("failed to create first subprocess");
free(cwd);
free(init_ctx->aa_profile);
free(init_ctx);
lxc_proc_put_context_info(init_ctx);
return -1;
}

Expand Down Expand Up @@ -794,8 +798,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
process_lock();
close(ipc_sockets[0]);
process_unlock();
free(init_ctx->aa_profile);
free(init_ctx);
lxc_proc_put_context_info(init_ctx);

/* we're done, the child process should now execute whatever
* it is that the user requested. The parent can now track it
Expand All @@ -815,8 +818,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
process_unlock();
if (to_cleanup_pid)
(void) wait_for_pid(to_cleanup_pid);
free(init_ctx->aa_profile);
free(init_ctx);
lxc_proc_put_context_info(init_ctx);
return -1;
}

Expand Down Expand Up @@ -918,7 +920,7 @@ int attach_child_main(void* data)

/* load apparmor profile */
if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_APPARMOR)) {
ret = attach_apparmor(init_ctx->aa_profile);
ret = lsm_process_label_set(init_ctx->lsm_label, 0);
if (ret < 0) {
shutdown(ipc_socket, SHUT_RDWR);
rexit(-1);
Expand Down Expand Up @@ -1021,8 +1023,7 @@ int attach_child_main(void* data)

shutdown(ipc_socket, SHUT_RDWR);
close(ipc_socket);
free(init_ctx->aa_profile);
free(init_ctx);
lxc_proc_put_context_info(init_ctx);

/* The following is done after the communication socket is
* shut down. That way, all errors that might (though
Expand Down
2 changes: 1 addition & 1 deletion src/lxc/attach.h
Expand Up @@ -28,7 +28,7 @@
#include "attach_options.h"

struct lxc_proc_context_info {
char *aa_profile;
char *lsm_label;
unsigned long personality;
unsigned long long capability_mask;
};
Expand Down
43 changes: 10 additions & 33 deletions src/lxc/conf.c
Expand Up @@ -74,10 +74,7 @@
#include "bdev.h"
#include "cgroup.h"
#include "lxclock.h"

#if HAVE_APPARMOR
#include <apparmor.h>
#endif
#include "lsm/lsm.h"

#if HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
Expand Down Expand Up @@ -2398,12 +2395,9 @@ struct lxc_conf *lxc_conf_init(void)
lxc_list_init(&new->id_map);
for (i=0; i<NUM_LXC_HOOKS; i++)
lxc_list_init(&new->hooks[i]);
#if HAVE_APPARMOR
new->aa_profile = NULL;
#endif
#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
new->lsm_aa_profile = NULL;
new->lsm_se_context = NULL;
new->lsm_umount_proc = 0;
#endif

return new;
}
Expand Down Expand Up @@ -3043,10 +3037,6 @@ int uid_shift_ttys(int pid, struct lxc_conf *conf)

int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath, struct cgroup_process_info *cgroup_info)
{
#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
int mounted;
#endif

if (setup_utsname(lxc_conf->utsname)) {
ERROR("failed to setup the utsname for '%s'", name);
return -1;
Expand Down Expand Up @@ -3140,24 +3130,11 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath,
return -1;
}

#if HAVE_APPARMOR /* || HAVE_SMACK || HAVE_SELINUX */
INFO("rootfs path is .%s., mount is .%s.", lxc_conf->rootfs.path,
lxc_conf->rootfs.mount);
if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0) {
if (mount("proc", "/proc", "proc", 0, NULL)) {
SYSERROR("Failed mounting /proc, proceeding");
mounted = 0;
} else
mounted = 1;
} else
mounted = lsm_mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
if (mounted == -1) {
SYSERROR("failed to mount /proc in the container.");
/* mount /proc if needed for LSM transition */
if (lsm_proc_mount(lxc_conf) < 0) {
ERROR("failed to LSM mount proc for '%s'", name);
return -1;
} else if (mounted == 1) {
lxc_conf->lsm_umount_proc = 1;
}
#endif

if (setup_pivot_root(&lxc_conf->rootfs)) {
ERROR("failed to set rootfs for '%s'", name);
Expand Down Expand Up @@ -3488,10 +3465,10 @@ void lxc_conf_free(struct lxc_conf *conf)
if (conf->rcfile)
free(conf->rcfile);
lxc_clear_config_network(conf);
#if HAVE_APPARMOR
if (conf->aa_profile)
free(conf->aa_profile);
#endif
if (conf->lsm_aa_profile)
free(conf->lsm_aa_profile);
if (conf->lsm_se_context)
free(conf->lsm_se_context);
lxc_seccomp_free(conf);
lxc_clear_config_caps(conf);
lxc_clear_config_keepcaps(conf);
Expand Down
12 changes: 4 additions & 8 deletions src/lxc/conf.h
Expand Up @@ -247,9 +247,8 @@ enum {
* @tty_info : tty data
* @console : console data
* @ttydir : directory (under /dev) in which to create console and ttys
#if HAVE_APPARMOR
* @aa_profile : apparmor profile to switch to
#endif
* @lsm_aa_profile : apparmor profile to switch to or NULL
* @lsm_se_context : selinux type to switch to or NULL
*/
enum lxchooks {
LXCHOOK_PRESTART, LXCHOOK_PREMOUNT, LXCHOOK_MOUNT, LXCHOOK_AUTODEV,
Expand Down Expand Up @@ -285,13 +284,10 @@ struct lxc_conf {
char *ttydir;
int close_all_fds;
struct lxc_list hooks[NUM_LXC_HOOKS];
#if HAVE_APPARMOR
char *aa_profile;
#endif

#if HAVE_APPARMOR /* || HAVE_SELINUX || HAVE_SMACK */
char *lsm_aa_profile;
char *lsm_se_context;
int lsm_umount_proc;
#endif
char *seccomp; // filename with the seccomp rules
#if HAVE_SCMP_FILTER_CTX
scmp_filter_ctx *seccomp_ctx;
Expand Down

0 comments on commit fe4de9a

Please sign in to comment.