2
0
mirror of git://github.com/lxc/lxc synced 2025-08-30 21:29:32 +00:00

Merge pull request #2479 from Blub/apparmor-profiles

RFC: Generated Apparmor profiles, namespaces, stacking
This commit is contained in:
Serge Hallyn
2018-07-25 23:04:32 -05:00
committed by GitHub
21 changed files with 1297 additions and 85 deletions

View File

@@ -85,7 +85,6 @@
mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
deny /sys/firmware/efi/efivars/** rwklx,
deny /sys/kernel/security/** rwklx,
mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
mount options=(ro, nosuid, nodev, noexec, remount, strictatime) -> /sys/fs/cgroup/,
# deny reads from debugfs

View File

@@ -40,5 +40,6 @@
pivot_root /usr/lib*/*/lxc/**,
change_profile -> lxc-*,
change_profile -> lxc-**,
change_profile -> unconfined,
change_profile -> :lxc-*:unconfined,

View File

@@ -9,4 +9,5 @@ profile lxc-container-default-cgns flags=(attach_disconnected,mediate_deleted) {
# the newinstance option (but, right now, we don't).
deny mount fstype=devpts,
mount fstype=cgroup -> /sys/fs/cgroup/**,
mount fstype=cgroup2 -> /sys/fs/cgroup/**,
}

View File

@@ -11,4 +11,5 @@ profile lxc-container-default-with-nesting flags=(attach_disconnected,mediate_de
mount fstype=sysfs -> /var/cache/lxc/**,
mount options=(rw,bind),
mount fstype=cgroup -> /sys/fs/cgroup/**,
mount fstype=cgroup2 -> /sys/fs/cgroup/**,
}

View File

@@ -469,6 +469,13 @@ AC_ARG_WITH([cgroup-pattern],
[pattern for container cgroups]
)], [], [with_cgroup_pattern=['lxc/%n']])
# The path for the apparmor_parser's cache for generated apparmor profiles
AC_ARG_WITH([apparmor-cache-dir],
[AC_HELP_STRING(
[--with-apparmor-cache-dir=dir],
[path for apparmor_parser cache]
)], [], [with_apparmor_cache_dir=['${localstatedir}/cache/lxc/apparmor']])
# Container log path. By default, use $lxcpath.
AC_MSG_CHECKING([Whether to place logfiles in container config path])
AC_ARG_ENABLE([configpath-log],
@@ -515,6 +522,7 @@ AS_AC_EXPAND(LXCBINHOOKDIR, "$libexecdir/lxc/hooks")
AS_AC_EXPAND(LXCINITDIR, "$libexecdir")
AS_AC_EXPAND(LOGPATH, "$with_log_path")
AS_AC_EXPAND(RUNTIME_PATH, "$with_runtime_path")
AS_AC_EXPAND(APPARMOR_CACHE_DIR, "$with_apparmor_cache_dir")
AC_SUBST(DEFAULT_CGROUP_PATTERN, ["$with_cgroup_pattern"])
# We need the install path so criu knows where to reference the hook scripts.

View File

@@ -174,6 +174,7 @@ AM_CFLAGS = -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
-DDEFAULT_CGROUP_PATTERN=\"$(DEFAULT_CGROUP_PATTERN)\" \
-DRUNTIME_PATH=\"$(RUNTIME_PATH)\" \
-DSBINDIR=\"$(SBINDIR)\" \
-DAPPARMOR_CACHE_DIR=\"$(APPARMOR_CACHE_DIR)\" \
-I $(top_srcdir)/src \
-I $(top_srcdir)/src/lxc \
-I $(top_srcdir)/src/lxc/storage \

View File

@@ -2360,7 +2360,23 @@ static int setup_mount(const struct lxc_conf *conf,
return ret;
}
FILE *make_anonymous_mount_file(struct lxc_list *mount)
/*
* In order for nested containers to be able to mount /proc and /sys they need
* to see a "pure" proc and sysfs mount points with nothing mounted on top
* (like lxcfs).
* For this we provide proc and sysfs in /dev/.lxc/{proc,sys} while using an
* apparmor rule to deny access to them. This is mostly for convenience: The
* container's root user can mount them anyway and thus has access to the two
* file systems. But a non-root user in the container should not be allowed to
* access them as a side effect without explicitly allowing it.
*/
static const char nesting_helpers[] =
"proc dev/.lxc/proc proc create=dir,optional\n"
"sys dev/.lxc/sys sysfs create=dir,optional\n"
;
FILE *make_anonymous_mount_file(struct lxc_list *mount,
bool include_nesting_helpers)
{
int ret;
char *mount_entry;
@@ -2402,6 +2418,13 @@ FILE *make_anonymous_mount_file(struct lxc_list *mount)
goto on_error;
}
if (include_nesting_helpers) {
ret = lxc_write_nointr(fd, nesting_helpers,
sizeof(nesting_helpers) - 1);
if (ret != sizeof(nesting_helpers) - 1)
goto on_error;
}
ret = lseek(fd, 0, SEEK_SET);
if (ret < 0)
goto on_error;
@@ -2422,7 +2445,7 @@ static int setup_mount_entries(const struct lxc_conf *conf,
int ret;
FILE *f;
f = make_anonymous_mount_file(mount);
f = make_anonymous_mount_file(mount, conf->lsm_aa_allow_nesting);
if (!f)
return -1;
@@ -2738,6 +2761,7 @@ struct lxc_conf *lxc_conf_init(void)
lxc_list_init(&new->groups);
lxc_list_init(&new->state_clients);
new->lsm_aa_profile = NULL;
lxc_list_init(&new->lsm_aa_raw);
new->lsm_se_context = NULL;
new->tmp_umount_proc = false;
new->tmp_umount_proc = 0;
@@ -4025,6 +4049,19 @@ void lxc_clear_includes(struct lxc_conf *conf)
}
}
int lxc_clear_apparmor_raw(struct lxc_conf *c)
{
struct lxc_list *it, *next;
lxc_list_for_each_safe (it, &c->lsm_aa_raw, next) {
lxc_list_del(it);
free(it->elem);
free(it);
}
return 0;
}
void lxc_conf_free(struct lxc_conf *conf)
{
if (!conf)
@@ -4052,6 +4089,7 @@ void lxc_conf_free(struct lxc_conf *conf)
free(conf->syslog);
lxc_free_networks(&conf->network);
free(conf->lsm_aa_profile);
free(conf->lsm_aa_profile_computed);
free(conf->lsm_se_context);
lxc_seccomp_free(conf);
lxc_clear_config_caps(conf);
@@ -4068,6 +4106,7 @@ void lxc_conf_free(struct lxc_conf *conf)
lxc_clear_limits(conf, "lxc.prlimit");
lxc_clear_sysctls(conf, "lxc.sysctl");
lxc_clear_procs(conf, "lxc.proc");
lxc_clear_apparmor_raw(conf);
free(conf->cgroup_meta.dir);
free(conf->cgroup_meta.controllers);
free(conf->shmount.path_host);

View File

@@ -275,7 +275,11 @@ struct lxc_conf {
};
char *lsm_aa_profile;
char *lsm_aa_profile_computed;
bool lsm_aa_profile_created;
unsigned int lsm_aa_allow_nesting;
unsigned int lsm_aa_allow_incomplete;
struct lxc_list lsm_aa_raw;
char *lsm_se_context;
bool tmp_umount_proc;
char *seccomp; /* filename with the seccomp rules */
@@ -427,7 +431,8 @@ extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
extern void remount_all_slave(void);
extern void suggest_default_idmap(void);
extern FILE *make_anonymous_mount_file(struct lxc_list *mount);
extern FILE *make_anonymous_mount_file(struct lxc_list *mount,
bool include_nesting_helpers);
extern struct lxc_list *sort_cgroup_settings(struct lxc_list *cgroup_settings);
extern unsigned long add_required_remount_flags(const char *s, const char *d,
unsigned long flags);
@@ -441,5 +446,6 @@ extern int setup_sysctl_parameters(struct lxc_list *sysctls);
extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
extern int setup_proc_filesystem(struct lxc_list *procs, pid_t pid);
extern int lxc_clear_procs(struct lxc_conf *c, const char *key);
extern int lxc_clear_apparmor_raw(struct lxc_conf *c);
#endif /* __LXC_CONF_H */

View File

@@ -84,7 +84,9 @@ lxc_log_define(confile, lxc);
lxc_config_define(autodev);
lxc_config_define(apparmor_allow_incomplete);
lxc_config_define(apparmor_allow_nesting);
lxc_config_define(apparmor_profile);
lxc_config_define(apparmor_raw);
lxc_config_define(cap_drop);
lxc_config_define(cap_keep);
lxc_config_define(cgroup_controller);
@@ -158,6 +160,8 @@ static struct lxc_config_t config[] = {
{ "lxc.arch", set_config_personality, get_config_personality, clr_config_personality, },
{ "lxc.apparmor.profile", set_config_apparmor_profile, get_config_apparmor_profile, clr_config_apparmor_profile, },
{ "lxc.apparmor.allow_incomplete", set_config_apparmor_allow_incomplete, get_config_apparmor_allow_incomplete, clr_config_apparmor_allow_incomplete, },
{ "lxc.apparmor.allow_nesting", set_config_apparmor_allow_nesting, get_config_apparmor_allow_nesting, clr_config_apparmor_allow_nesting, },
{ "lxc.apparmor.raw", set_config_apparmor_raw, get_config_apparmor_raw, clr_config_apparmor_raw, },
{ "lxc.autodev", set_config_autodev, get_config_autodev, clr_config_autodev, },
{ "lxc.cap.drop", set_config_cap_drop, get_config_cap_drop, clr_config_cap_drop, },
{ "lxc.cap.keep", set_config_cap_keep, get_config_cap_keep, clr_config_cap_keep, },
@@ -1132,6 +1136,52 @@ static int set_config_apparmor_allow_incomplete(const char *key,
return 0;
}
static int set_config_apparmor_allow_nesting(const char *key,
const char *value,
struct lxc_conf *lxc_conf,
void *data)
{
if (lxc_config_value_empty(value))
return clr_config_apparmor_allow_nesting(key, lxc_conf, NULL);
if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_nesting) < 0)
return -1;
if (lxc_conf->lsm_aa_allow_nesting > 1)
return -1;
return 0;
}
static int set_config_apparmor_raw(const char *key,
const char *value,
struct lxc_conf *lxc_conf,
void *data)
{
char *elem;
struct lxc_list *list;
if (lxc_config_value_empty(value))
return lxc_clear_apparmor_raw(lxc_conf);
list = malloc(sizeof(*list));
if (!list) {
errno = ENOMEM;
return -1;
}
elem = strdup(value);
if (!elem) {
free(list);
return -1;
}
list->elem = elem;
lxc_list_add_tail(&lxc_conf->lsm_aa_raw, list);
return 0;
}
static int set_config_selinux_context(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
@@ -3004,6 +3054,34 @@ static int get_config_apparmor_allow_incomplete(const char *key, char *retv,
c->lsm_aa_allow_incomplete);
}
static int get_config_apparmor_allow_nesting(const char *key, char *retv,
int inlen, struct lxc_conf *c,
void *data)
{
return lxc_get_conf_int(c, retv, inlen,
c->lsm_aa_allow_nesting);
}
static int get_config_apparmor_raw(const char *key, char *retv,
int inlen, struct lxc_conf *c,
void *data)
{
int len;
struct lxc_list *it;
int fulllen = 0;
if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);
lxc_list_for_each(it, &c->lsm_aa_raw) {
strprint(retv, inlen, "%s\n", (char *)it->elem);
}
return fulllen;
}
static int get_config_selinux_context(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
@@ -3794,6 +3872,21 @@ static inline int clr_config_apparmor_allow_incomplete(const char *key,
return 0;
}
static inline int clr_config_apparmor_allow_nesting(const char *key,
struct lxc_conf *c,
void *data)
{
c->lsm_aa_allow_nesting = 0;
return 0;
}
static inline int clr_config_apparmor_raw(const char *key,
struct lxc_conf *c,
void *data)
{
return lxc_clear_apparmor_raw(c);
}
static inline int clr_config_selinux_context(const char *key,
struct lxc_conf *c, void *data)
{
@@ -4986,7 +5079,9 @@ int lxc_list_subkeys(struct lxc_conf *conf, const char *key, char *retv,
if (!strcmp(key, "lxc.apparmor")) {
strprint(retv, inlen, "allow_incomplete\n");
strprint(retv, inlen, "allow_nesting\n");
strprint(retv, inlen, "profile\n");
strprint(retv, inlen, "raw\n");
} else if (!strcmp(key, "lxc.cgroup")) {
strprint(retv, inlen, "dir\n");
} else if (!strcmp(key, "lxc.selinux")) {

View File

@@ -378,7 +378,8 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct criu_opts *opts)
DECLARE_ARG(opts->user->action_script);
}
mnts = make_anonymous_mount_file(&opts->c->lxc_conf->mount_list);
mnts = make_anonymous_mount_file(&opts->c->lxc_conf->mount_list,
opts->c->lxc_conf->lsm_aa_allow_nesting);
if (!mnts)
goto err;

File diff suppressed because it is too large Load Diff

View File

@@ -142,18 +142,20 @@ int lsm_process_label_set_at(int label_fd, const char *label, bool on_exec)
if (on_exec) {
ERROR("Changing AppArmor profile on exec not supported");
return -EINVAL;
return -1;
}
len = strlen(label) + strlen("changeprofile ") + 1;
command = malloc(len);
if (!command)
return -1;
goto on_error;
ret = snprintf(command, len, "changeprofile %s", label);
if (ret < 0 || (size_t)ret >= len) {
int saved_errno = errno;
free(command);
return -1;
errno = saved_errno;
goto on_error;
}
ret = lxc_write_nointr(label_fd, command, len - 1);
@@ -161,9 +163,11 @@ int lsm_process_label_set_at(int label_fd, const char *label, bool on_exec)
} else if (strcmp(name, "SELinux") == 0) {
ret = lxc_write_nointr(label_fd, label, strlen(label));
} else {
ret = -EINVAL;
errno = EINVAL;
ret = -1;
}
if (ret < 0) {
on_error:
SYSERROR("Failed to set %s label \"%s\"", name, label);
return -1;
}
@@ -173,11 +177,37 @@ int lsm_process_label_set_at(int label_fd, const char *label, bool on_exec)
}
int lsm_process_label_set(const char *label, struct lxc_conf *conf,
bool use_default, bool on_exec)
bool on_exec)
{
if (!drv) {
ERROR("LSM driver not inited");
return -1;
}
return drv->process_label_set(label, conf, use_default, on_exec);
return drv->process_label_set(label, conf, on_exec);
}
int lsm_process_prepare(struct lxc_conf *conf, const char *lxcpath)
{
if (!drv) {
ERROR("LSM driver not inited");
return 0;
}
if (!drv->prepare)
return 0;
return drv->prepare(conf, lxcpath);
}
void lsm_process_cleanup(struct lxc_conf *conf, const char *lxcpath)
{
if (!drv) {
ERROR("LSM driver not inited");
return;
}
if (!drv->cleanup)
return;
drv->cleanup(conf, lxcpath);
}

View File

@@ -38,17 +38,21 @@ struct lsm_drv {
int (*enabled)(void);
char *(*process_label_get)(pid_t pid);
int (*process_label_set)(const char *label, struct lxc_conf *conf,
bool use_default, bool on_exec);
bool on_exec);
int (*prepare)(struct lxc_conf *conf, const char *lxcpath);
void (*cleanup)(struct lxc_conf *conf, const char *lxcpath);
};
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_prepare(struct lxc_conf *conf, const char *lxcpath);
extern int lsm_process_label_set(const char *label, struct lxc_conf *conf,
bool use_default, bool on_exec);
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);
extern void lsm_process_cleanup(struct lxc_conf *conf, const char *lxcpath);
#endif /* __LXC_LSM_H */

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,
bool use_default, bool on_exec)
bool on_exec)
{
return 0;
}

View File

@@ -75,15 +75,13 @@ 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,
bool use_default, bool on_exec)
bool on_exec)
{
int ret;
const char *label;
label = inlabel ? inlabel : conf->lsm_se_context;
if (!label) {
if (!use_default)
return -EINVAL;
label = DEFAULT_LABEL;
}

View File

@@ -863,9 +863,19 @@ int lxc_init(const char *name, struct lxc_handler *handler)
}
TRACE("Initialized cgroup driver");
ret = lsm_process_prepare(conf, handler->lxcpath);
if (ret < 0) {
ERROR("Failed to initialize LSM");
goto out_destroy_cgroups;
}
TRACE("Initialized LSM");
INFO("Container \"%s\" is initialized", name);
return 0;
out_destroy_cgroups:
handler->cgroup_ops->destroy(handler->cgroup_ops, handler);
out_delete_terminal:
lxc_terminal_delete(&handler->conf->console);
@@ -956,6 +966,8 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
while (namespace_count--)
free(namespaces[namespace_count]);
lsm_process_cleanup(handler->conf, handler->lxcpath);
cgroup_ops->destroy(cgroup_ops, handler);
cgroup_exit(cgroup_ops);
@@ -1235,7 +1247,7 @@ static int do_start(void *data)
}
/* Set the label to change to when we exec(2) the container's init. */
ret = lsm_process_label_set(NULL, handler->conf, 1, 1);
ret = lsm_process_label_set(NULL, handler->conf, true);
if (ret < 0)
goto out_warn_father;

View File

@@ -2433,6 +2433,30 @@ int run_command(char *buf, size_t buf_size, int (*child_fn)(void *), void *args)
return fret;
}
char *must_concat(const char *first, ...)
{
va_list args;
char *cur, *dest;
size_t cur_len, it_len;
dest = must_copy_string(first);
cur_len = it_len = strlen(first);
va_start(args, first);
while ((cur = va_arg(args, char *)) != NULL) {
it_len = strlen(cur);
dest = must_realloc(dest, cur_len + it_len + 1);
(void)memcpy(dest + cur_len, cur, it_len);
cur_len += it_len;
}
va_end(args);
dest[cur_len] = 0;
return dest;
}
char *must_make_path(const char *first, ...)
{
va_list args;

View File

@@ -568,6 +568,7 @@ extern int run_command(char *buf, size_t buf_size, int (*child_fn)(void *),
/* Concatenate all passed-in strings into one path. Do not fail. If any piece
* is not prefixed with '/', add a '/'.
*/
__attribute__((sentinel)) extern char *must_concat(const char *first, ...);
__attribute__((sentinel)) extern char *must_make_path(const char *first, ...);
__attribute__((sentinel)) extern char *must_append_path(char *first, ...);

View File

@@ -81,6 +81,7 @@ if DISTRO_UBUNTU
bin_SCRIPTS += \
lxc-test-lxc-attach \
lxc-test-apparmor-mount \
lxc-test-apparmor-generated \
lxc-test-checkpoint-restore \
lxc-test-snapdeps \
lxc-test-symlink \
@@ -114,6 +115,7 @@ EXTRA_DIST = \
lxc-test-rootfs \
lxc-test-autostart \
lxc-test-apparmor-mount \
lxc-test-apparmor-generated \
lxc-test-checkpoint-restore \
lxc-test-cloneconfig \
lxc-test-createconfig \

View File

@@ -0,0 +1,84 @@
#!/bin/sh
# lxc: linux Container library
# This is a test script for generated apparmor profiles
# 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
if ! which apparmor_parser >/dev/null 2>&1; then
echo 'SKIP: test for generated apparmor profiles: apparmor_parser missing'
fi
exit 0
DONE=0
KNOWN_RELEASES="precise trusty xenial yakkety zesty"
LOGFILE="/tmp/lxc-test-$$.log"
cleanup() {
lxc-destroy -n $CONTAINER_NAME >/dev/null 2>&1 || true
if [ $DONE -eq 0 ]; then
[ -f "$LOGFILE" ] && cat "$LOGFILE" >&2
rm -f "$LOGFILE"
echo "FAIL"
exit 1
fi
rm -f "$LOGFILE"
echo "PASS"
}
ARCH=i386
if type dpkg >/dev/null 2>&1; then
ARCH=$(dpkg --print-architecture)
fi
trap cleanup EXIT HUP INT TERM
set -eu
# Create a container
CONTAINER_NAME=lxc-test-apparmor-generated
# default release is trusty, or the systems release if recognized
release=trusty
if [ -f /etc/lsb-release ]; then
. /etc/lsb-release
rels=$(ubuntu-distro-info --supported 2>/dev/null) ||
rels="$KNOWN_RELEASES"
for r in $rels; do
[ "$DISTRIB_CODENAME" = "$r" ] && release="$r"
done
fi
lxc-create -t download -n $CONTAINER_NAME -B dir -- -d ubuntu -r $release -a $ARCH
CONTAINER_PATH=$(dirname $(lxc-info -n $CONTAINER_NAME -c lxc.rootfs.path -H) | sed -e 's/dir://')
cp $CONTAINER_PATH/config $CONTAINER_PATH/config.bak
# Set the profile to be auto-generated
echo "lxc.apparmor.profile = generated" >> $CONTAINER_PATH/config
# Start it
lxc-start -n $CONTAINER_NAME -lDEBUG -o "$LOGFILE"
lxc-wait -n $CONTAINER_NAME -t 5 -s RUNNING || (echo "Container didn't start" && exit 1)
pid=`lxc-info -p -H -n $CONTAINER_NAME`
profile=`cat /proc/$pid/attr/current`
expected_profile="lxc-${CONTAINER_NAME}_</var/lib/lxc>//&:lxc-${CONTAINER_NAME}_<-var-lib-lxc>:unconfined (enforce)"
lxc-stop -n $CONTAINER_NAME -k
if [ "x$profile" != "x$expected_profile" ]; then
echo "FAIL: container was in profile $profile" >&2
echo "expected profile: $expected_profile" >&2
exit 1
fi
DONE=1

View File

@@ -23,6 +23,16 @@
set -e
# Only run on a normally configured ubuntu lxc system
if [ ! -d /sys/class/net/lxcbr0 ]; then
echo "lxcbr0 is not configured."
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo "ERROR: Must run as root."
exit 1
fi
if [ -f /proc/self/ns/cgroup ]; then
default_profile="lxc-container-default-cgns (enforce)"
else
@@ -45,6 +55,7 @@ DONE=0
KNOWN_RELEASES="precise trusty xenial yakkety zesty"
MOUNTSR=/sys/kernel/security/apparmor/features/mount
dnam=`mktemp -d`
logfile=`mktemp`
cname=`basename $dnam`
cleanup() {
run_cmd lxc-destroy -f -n $cname || true
@@ -56,23 +67,24 @@ cleanup() {
rm -Rf $HDIR /run/user/$(id -u $TUSER)
deluser $TUSER
if [ $DONE -eq 0 ]; then
echo 'Failed container log:' >&2
cat "$logfile" >&2
echo 'End log' >&2
rm -f "$logfile"
echo "FAIL"
exit 1
fi
rm -f "$logfile"
echo "PASS"
}
clear_log() {
truncate -s0 "$logfile"
}
trap cleanup exit
# Only run on a normally configured ubuntu lxc system
if [ ! -d /sys/class/net/lxcbr0 ]; then
echo "lxcbr0 is not configured."
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo "ERROR: Must run as root."
exit 1
fi
chmod 0666 "$logfile"
# This would be much simpler if we could run it as
# root. However, in order to not have the bind mount
@@ -160,7 +172,7 @@ fi
run_cmd lxc-create -t download -n $cname -- -d ubuntu -r $release -a $ARCH
echo "test default confined container"
run_cmd lxc-start -n $cname -d
run_cmd lxc-start -n $cname -d -lDEBUG -o "$logfile"
run_cmd lxc-wait -n $cname -s RUNNING
pid=`run_cmd lxc-info -p -H -n $cname`
profile=`cat /proc/$pid/attr/current`
@@ -169,10 +181,11 @@ if [ "x$profile" != "x${default_profile}" ]; then
exit 1
fi
run_cmd lxc-stop -n $cname -k
clear_log
echo "test regular unconfined container"
echo "lxc.apparmor.profile = unconfined" >> $HDIR/.local/share/lxc/$cname/config
run_cmd lxc-start -n $cname -d
run_cmd lxc-start -n $cname -d -lDEBUG -o "$logfile"
run_cmd lxc-wait -n $cname -s RUNNING
pid=`run_cmd lxc-info -p -H -n $cname`
profile=`cat /proc/$pid/attr/current`
@@ -181,6 +194,7 @@ if [ "x$profile" != "xunconfined" ]; then
exit 1
fi
run_cmd lxc-stop -n $cname -k
clear_log
echo "masking $MOUNTSR"
mount --bind $dnam $MOUNTSR
@@ -198,7 +212,7 @@ fi
echo "test regular unconfined container"
echo "lxc.apparmor.profile = unconfined" >> $HDIR/.local/share/lxc/$cname/config
run_cmd lxc-start -n $cname -d
run_cmd lxc-start -n $cname -d -lDEBUG -o "$logfile"
run_cmd lxc-wait -n $cname -s RUNNING
pid=`run_cmd lxc-info -p -H -n $cname`
if [ "$pid" = "-1" ]; then
@@ -211,11 +225,12 @@ if [ "x$profile" != "xunconfined" ]; then
exit 1
fi
run_cmd lxc-stop -n $cname -k
clear_log
echo "testing override"
sed -i '/apparmor.profile/d' $HDIR/.local/share/lxc/$cname/config
echo "lxc.apparmor.allow_incomplete = 1" >> $HDIR/.local/share/lxc/$cname/config
run_cmd lxc-start -n $cname -d
run_cmd lxc-start -n $cname -d -lDEBUG -o "$logfile"
run_cmd lxc-wait -n $cname -s RUNNING
pid=`run_cmd lxc-info -p -H -n $cname`
if [ "$pid" = "-1" ]; then
@@ -228,5 +243,6 @@ if [ "x$profile" != "x${default_profile}" ]; then
exit 1
fi
run_cmd lxc-stop -n $cname -k
clear_log
DONE=1