From: Christian Brauner Date: Wed, 12 Aug 2020 13:26:22 +0000 (+0200) Subject: lsm: remove the need for atomic operations X-Git-Tag: lxc-5.0.0~367^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af04d847520b7f91857b946b74be43449b0195b2;p=thirdparty%2Flxc.git lsm: remove the need for atomic operations Signed-off-by: Christian Brauner --- diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 94a80c2bd..4b9598922 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -93,7 +93,7 @@ static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid) info->lsm_ops = lsm_init(); - info->lsm_label = info->lsm_ops->process_label_get(pid); + info->lsm_label = info->lsm_ops->process_label_get(info->lsm_ops, pid); info->ns_inherited = 0; for (int i = 0; i < LXC_NS_MAX; i++) info->ns_fd[i] = -EBADF; @@ -779,7 +779,8 @@ static int attach_child_main(struct attach_clone_payload *payload) /* Change into our new LSM profile. */ on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false; - ret = init_ctx->lsm_ops->process_label_set_at(lsm_fd, init_ctx->lsm_label, on_exec); + ret = init_ctx->lsm_ops->process_label_set_at(init_ctx->lsm_ops, lsm_fd, + init_ctx->lsm_label, on_exec); close(lsm_fd); if (ret < 0) goto on_error; @@ -1244,7 +1245,8 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ret = -1; on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? true : false; - labelfd = init_ctx->lsm_ops->process_label_fd_get(attached_pid, on_exec); + labelfd = init_ctx->lsm_ops->process_label_fd_get(init_ctx->lsm_ops, + attached_pid, on_exec); if (labelfd < 0) goto close_mainloop; diff --git a/src/lxc/attach.h b/src/lxc/attach.h index bc9a81376..5649edd10 100644 --- a/src/lxc/attach.h +++ b/src/lxc/attach.h @@ -19,7 +19,7 @@ struct lxc_proc_context_info { unsigned long long capability_mask; int ns_inherited; int ns_fd[LXC_NS_MAX]; - const struct lsm_ops *lsm_ops; + struct lsm_ops *lsm_ops; }; __hidden extern int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 2067b03c8..d570a75e8 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3211,15 +3211,15 @@ static int lxc_setup_boot_id(void) return 0; } -static int lxc_setup_keyring(const struct lsm_ops *lsm_ops, const struct lxc_conf *conf) +static int lxc_setup_keyring(struct lsm_ops *lsm_ops, const struct lxc_conf *conf) { key_serial_t keyring; int ret = 0; if (conf->lsm_se_keyring_context) - ret = lsm_ops->keyring_label_set(conf->lsm_se_keyring_context); + ret = lsm_ops->keyring_label_set(lsm_ops, conf->lsm_se_keyring_context); else if (conf->lsm_se_context) - ret = lsm_ops->keyring_label_set(conf->lsm_se_context); + ret = lsm_ops->keyring_label_set(lsm_ops, conf->lsm_se_context); if (ret < 0) return log_error_errno(-1, errno, "Failed to set keyring context"); diff --git a/src/lxc/lsm/apparmor.c b/src/lxc/lsm/apparmor.c index c4fce1ee6..b09d47090 100644 --- a/src/lxc/lsm/apparmor.c +++ b/src/lxc/lsm/apparmor.c @@ -4,7 +4,6 @@ #define _GNU_SOURCE 1 #endif #include -#include #include #include #include @@ -25,15 +24,6 @@ lxc_log_define(apparmor, lsm); -/* set by lsm_apparmor_ops_init if true */ -static atomic_int aa_enabled ; -static atomic_int aa_parser_available = -1; -static atomic_int aa_supports_unix; -static atomic_int aa_can_stack; -static atomic_int aa_is_stacked; -static atomic_int aa_admin; -static atomic_int mount_features_enabled; - #define AA_DEF_PROFILE "lxc-container-default" #define AA_DEF_PROFILE_CGNS "lxc-container-default-cgns" #define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask" @@ -373,23 +363,18 @@ static const char AA_PROFILE_UNPRIVILEGED[] = " mount options=(ro,remount),\n" ; -static bool check_mount_feature_enabled(void) -{ - return atomic_load(&mount_features_enabled); -} - -static void load_mount_features_enabled(void) +static void load_mount_features_enabled(struct lsm_ops *ops) { struct stat statbuf; int ret; ret = stat(AA_MOUNT_RESTR, &statbuf); if (ret == 0) - atomic_store(&mount_features_enabled, 1); + ops->aa_mount_features_enabled = 1; } /* aa_getcon is not working right now. Use our hand-rolled version below */ -static int apparmor_enabled(void) +static int apparmor_enabled(struct lsm_ops *ops) { __do_fclose FILE *fin = NULL; char e; @@ -398,16 +383,17 @@ static int apparmor_enabled(void) fin = fopen_cloexec(AA_ENABLED_FILE, "r"); if (!fin) return 0; + ret = fscanf(fin, "%c", &e); if (ret == 1 && e == 'Y') { - load_mount_features_enabled(); + load_mount_features_enabled(ops); return 1; } return 0; } -static char *apparmor_process_label_get(pid_t pid) +static char *apparmor_process_label_get(struct lsm_ops *ops, pid_t pid) { char path[100], *space; int ret; @@ -459,9 +445,9 @@ again: * Probably makes sense to reorganize these to only read * the label once */ -static bool apparmor_am_unconfined(void) +static bool apparmor_am_unconfined(struct lsm_ops *ops) { - char *p = apparmor_process_label_get(lxc_raw_getpid()); + char *p = apparmor_process_label_get(ops, lxc_raw_getpid()); bool ret = false; if (!p || strcmp(p, "unconfined") == 0) ret = true; @@ -542,14 +528,18 @@ static inline char *apparmor_namespace(const char *ctname, const char *lxcpath) * do not have ERROR/... macros available, so there are some fprintf(stderr)s * in there. */ -static bool check_apparmor_parser_version() +static bool check_apparmor_parser_version(struct lsm_ops *ops) { int major = 0, minor = 0, micro = 0, ret = 0; struct lxc_popen_FILE *parserpipe; int rc; - if (atomic_load(&aa_parser_available) >= 0) + switch (ops->aa_parser_available) { + case 0: return false; + case 1: + return true; + } parserpipe = lxc_popen("apparmor_parser --version"); if (!parserpipe) { @@ -578,12 +568,12 @@ static bool check_apparmor_parser_version() } if ((major > 2) || (major == 2 && minor > 10) || (major == 2 && minor == 10 && micro >= 95)) - atomic_store(&aa_supports_unix, 1); + ops->aa_supports_unix = 1; ret = 1; out: - atomic_store(&aa_parser_available, ret); + ops->aa_parser_available = ret; return ret == 1; } @@ -730,7 +720,7 @@ static void append_all_remount_rules(char **profile, size_t *size) } } -static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxcpath) +static char *get_apparmor_profile_content(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { char *profile, *profile_name_full; size_t size; @@ -749,7 +739,7 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc append_all_remount_rules(&profile, &size); - if (atomic_load(&aa_supports_unix)) + if (ops->aa_supports_unix) must_append_sized(&profile, &size, AA_PROFILE_UNIX_SOCKETS, STRARRAYLEN(AA_PROFILE_UNIX_SOCKETS)); @@ -757,7 +747,7 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc must_append_sized(&profile, &size, AA_PROFILE_CGROUP_NAMESPACES, STRARRAYLEN(AA_PROFILE_CGROUP_NAMESPACES)); - if (atomic_load(&aa_can_stack) && !atomic_load(&aa_is_stacked)) { + if (ops->aa_can_stack && !ops->aa_is_stacked) { char *namespace, *temp; must_append_sized(&profile, &size, AA_PROFILE_STACKING_BASE, @@ -780,7 +770,7 @@ static char *get_apparmor_profile_content(struct lxc_conf *conf, const char *lxc must_append_sized(&profile, &size, AA_PROFILE_NESTING_BASE, STRARRAYLEN(AA_PROFILE_NESTING_BASE)); - if (!atomic_load(&aa_can_stack) || atomic_load(&aa_is_stacked)) { + if (!ops->aa_can_stack || ops->aa_is_stacked) { char *temp; temp = must_concat(NULL, " change_profile -> \"", @@ -837,11 +827,11 @@ static char *make_apparmor_namespace_path(const char *ctname, const char *lxcpat return ret; } -static bool make_apparmor_namespace(struct lxc_conf *conf, const char *lxcpath) +static bool make_apparmor_namespace(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { char *path; - if (!atomic_load(&aa_can_stack) || atomic_load(&aa_is_stacked)) + if (!ops->aa_can_stack || ops->aa_is_stacked) return true; path = make_apparmor_namespace_path(conf->name, lxcpath); @@ -921,7 +911,7 @@ static void remove_apparmor_profile(struct lxc_conf *conf, const char *lxcpath) free(path); } -static int load_apparmor_profile(struct lxc_conf *conf, const char *lxcpath) +static int load_apparmor_profile(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { struct stat profile_sb; size_t content_len; @@ -930,7 +920,7 @@ static int load_apparmor_profile(struct lxc_conf *conf, const char *lxcpath) char *profile_path = NULL, *old_content = NULL, *new_content = NULL; int profile_fd = -1; - if (!make_apparmor_namespace(conf, lxcpath)) + if (!make_apparmor_namespace(ops, conf, lxcpath)) return -1; /* In order to avoid forcing a profile parse (potentially slow) on @@ -966,7 +956,7 @@ static int load_apparmor_profile(struct lxc_conf *conf, const char *lxcpath) goto out; } - new_content = get_apparmor_profile_content(conf, lxcpath); + new_content = get_apparmor_profile_content(ops, conf, lxcpath); if (!new_content) goto out; @@ -1024,9 +1014,9 @@ out_ok: * Ensure that the container's policy namespace is unloaded to free kernel * memory. This does not delete the policy from disk or cache. */ -static void apparmor_cleanup(struct lxc_conf *conf, const char *lxcpath) +static void apparmor_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { - if (!atomic_load(&aa_admin)) + if (!ops->aa_admin) return; if (!conf->lsm_aa_profile_created) @@ -1038,16 +1028,14 @@ static void apparmor_cleanup(struct lxc_conf *conf, const char *lxcpath) remove_apparmor_profile(conf, lxcpath); } -static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath) +static int apparmor_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { int ret = -1; const char *label; char *curlabel = NULL, *genlabel = NULL; - if (!atomic_load(&aa_enabled)) { - ERROR("AppArmor not enabled"); - return -1; - } + if (!ops->aa_enabled) + return log_error(-1, "AppArmor not enabled"); label = conf->lsm_aa_profile; @@ -1059,13 +1047,13 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath) } if (label && strcmp(label, AA_GENERATED) == 0) { - if (!check_apparmor_parser_version()) { + if (!check_apparmor_parser_version(ops)) { ERROR("Cannot use generated profile: apparmor_parser not available"); goto out; } /* auto-generate profile based on available/requested security features */ - if (load_apparmor_profile(conf, lxcpath) != 0) { + if (load_apparmor_profile(ops, conf, lxcpath) != 0) { ERROR("Failed to load generated AppArmor profile"); goto out; } @@ -1076,7 +1064,7 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath) goto out; } - if (atomic_load(&aa_can_stack) && !atomic_load(&aa_is_stacked)) { + if (ops->aa_can_stack && !ops->aa_is_stacked) { char *namespace = apparmor_namespace(conf->name, lxcpath); size_t llen = strlen(genlabel); must_append_sized(&genlabel, &llen, "//&:", STRARRAYLEN("//&:")); @@ -1088,9 +1076,9 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath) label = genlabel; } - curlabel = apparmor_process_label_get(lxc_raw_getpid()); + curlabel = apparmor_process_label_get(ops, lxc_raw_getpid()); - if (!atomic_load(&aa_can_stack) && aa_needs_transition(curlabel)) { + if (!ops->aa_can_stack && aa_needs_transition(curlabel)) { /* we're already confined, and stacking isn't supported */ if (!label || strcmp(curlabel, label) == 0) { @@ -1110,7 +1098,7 @@ static int apparmor_prepare(struct lxc_conf *conf, const char *lxcpath) label = AA_DEF_PROFILE; } - if (!check_mount_feature_enabled() && strcmp(label, "unconfined") != 0) { + if (!ops->aa_mount_features_enabled && strcmp(label, "unconfined") != 0) { WARN("Incomplete AppArmor support in your kernel"); if (!conf->lsm_aa_allow_incomplete) { ERROR("If you really want to start this container, set"); @@ -1127,18 +1115,18 @@ out: if (genlabel) { free(genlabel); if (ret != 0) - apparmor_cleanup(conf, lxcpath); + apparmor_cleanup(ops, conf, lxcpath); } free(curlabel); return ret; } -static int apparmor_keyring_label_set(const char *label) +static int apparmor_keyring_label_set(struct lsm_ops *ops, const char *label) { return 0; } -static int apparmor_process_label_fd_get(pid_t pid, bool on_exec) +static int apparmor_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec) { int ret = -1; int labelfd; @@ -1158,7 +1146,7 @@ static int apparmor_process_label_fd_get(pid_t pid, bool on_exec) return labelfd; } -static int apparmor_process_label_set_at(int label_fd, const char *label, bool on_exec) +static int apparmor_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec) { int ret = -1; size_t len; @@ -1194,17 +1182,15 @@ static int apparmor_process_label_set_at(int label_fd, const char *label, bool o * * Notes: This relies on /proc being available. */ -static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf, - bool on_exec) +static int apparmor_process_label_set(struct lsm_ops *ops, const char *inlabel, + struct lxc_conf *conf, bool on_exec) { int label_fd, ret; pid_t tid; const char *label; - if (!atomic_load(&aa_enabled)) { - ERROR("AppArmor not enabled"); - return -1; - } + if (!ops->aa_enabled) + return log_error(-1, "AppArmor not enabled"); label = inlabel ? inlabel : conf->lsm_aa_profile_computed; if (!label) { @@ -1218,18 +1204,18 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf return 0; } - if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined()) { + if (strcmp(label, "unconfined") == 0 && apparmor_am_unconfined(ops)) { INFO("AppArmor profile unchanged"); return 0; } tid = lxc_raw_gettid(); - label_fd = apparmor_process_label_fd_get(tid, on_exec); + label_fd = apparmor_process_label_fd_get(ops, tid, on_exec); if (label_fd < 0) { SYSERROR("Failed to change AppArmor profile to %s", label); return -1; } - ret = apparmor_process_label_set_at(label_fd, label, on_exec); + ret = apparmor_process_label_set_at(ops, label_fd, label, on_exec); close(label_fd); if (ret < 0) { ERROR("Failed to change AppArmor profile to %s", label); @@ -1241,44 +1227,49 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf } static struct lsm_ops apparmor_ops = { - .name = "AppArmor", - .cleanup = apparmor_cleanup, - .enabled = apparmor_enabled, - .keyring_label_set = apparmor_keyring_label_set, - .prepare = apparmor_prepare, - .process_label_fd_get = apparmor_process_label_fd_get, - .process_label_get = apparmor_process_label_get, - .process_label_set = apparmor_process_label_set, - .process_label_set_at = apparmor_process_label_set_at, + .name = "AppArmor", + .aa_admin = -1, + .aa_can_stack = -1, + .aa_enabled = -1, + .aa_is_stacked = -1, + .aa_mount_features_enabled = -1, + .aa_parser_available = -1, + .aa_supports_unix = -1, + .cleanup = apparmor_cleanup, + .enabled = apparmor_enabled, + .keyring_label_set = apparmor_keyring_label_set, + .prepare = apparmor_prepare, + .process_label_fd_get = apparmor_process_label_fd_get, + .process_label_get = apparmor_process_label_get, + .process_label_set = apparmor_process_label_set, + .process_label_set_at = apparmor_process_label_set_at, }; -const struct lsm_ops *lsm_apparmor_ops_init(void) +struct lsm_ops *lsm_apparmor_ops_init(void) { - bool have_mac_admin = false; - bool can_stack, is_stacked; - - if (!apparmor_enabled()) + apparmor_ops.aa_admin = 0; + apparmor_ops.aa_can_stack = 0; + apparmor_ops.aa_enabled = 0; + apparmor_ops.aa_is_stacked = 0; + apparmor_ops.aa_mount_features_enabled = 0; + apparmor_ops.aa_parser_available = -1; + apparmor_ops.aa_supports_unix = 0; + + if (!apparmor_enabled(&apparmor_ops)) return NULL; - can_stack = apparmor_can_stack(); - if (can_stack) { - atomic_store(&aa_can_stack, 1); - is_stacked = file_is_yes("/sys/kernel/security/apparmor/.ns_stacked"); - if (is_stacked) - atomic_store(&aa_is_stacked, 1); - } + apparmor_ops.aa_can_stack = apparmor_can_stack(); + if (apparmor_ops.aa_can_stack) + apparmor_ops.aa_is_stacked = file_is_yes("/sys/kernel/security/apparmor/.ns_stacked"); #if HAVE_LIBCAP - have_mac_admin = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE); + apparmor_ops.aa_admin = lxc_proc_cap_is_set(CAP_SETGID, CAP_EFFECTIVE); #endif - - if (!have_mac_admin) + if (!apparmor_ops.aa_admin) WARN("Per-container AppArmor profiles are disabled because the mac_admin capability is missing"); - else if (am_host_unpriv() && !atomic_load(&aa_is_stacked)) + else if (am_host_unpriv() && !apparmor_ops.aa_is_stacked) WARN("Per-container AppArmor profiles are disabled because LXC is running in an unprivileged container without stacking"); - else - atomic_store(&aa_admin, 1); - atomic_store(&aa_enabled, 1); + apparmor_ops.aa_enabled = 1; return &apparmor_ops; } diff --git a/src/lxc/lsm/lsm.c b/src/lxc/lsm/lsm.c index 93c3aca82..7fe34bfb0 100644 --- a/src/lxc/lsm/lsm.c +++ b/src/lxc/lsm/lsm.c @@ -21,9 +21,9 @@ __hidden extern struct lsm_ops *lsm_apparmor_ops_init(void); __hidden extern struct lsm_ops *lsm_selinux_ops_init(void); __hidden extern struct lsm_ops *lsm_nop_ops_init(void); -const struct lsm_ops *lsm_init(void) +struct lsm_ops *lsm_init(void) { - const struct lsm_ops *ops = NULL; + struct lsm_ops *ops = NULL; #if HAVE_APPARMOR ops = lsm_apparmor_ops_init(); diff --git a/src/lxc/lsm/lsm.h b/src/lxc/lsm/lsm.h index c035db29d..52d436425 100644 --- a/src/lxc/lsm/lsm.h +++ b/src/lxc/lsm/lsm.h @@ -14,16 +14,25 @@ struct lxc_conf; struct lsm_ops { const char *name; - int (*enabled)(void); - char *(*process_label_get)(pid_t pid); - int (*process_label_set)(const char *label, struct lxc_conf *conf, bool on_exec); - int (*keyring_label_set)(const char *label); - int (*prepare)(struct lxc_conf *conf, const char *lxcpath); - void (*cleanup)(struct lxc_conf *conf, const char *lxcpath); - int (*process_label_fd_get)(pid_t pid, bool on_exec); - int (*process_label_set_at)(int label_fd, const char *label, bool on_exec); + /* AppArmor specific fields. */ + int aa_enabled; + int aa_parser_available; + int aa_supports_unix; + int aa_can_stack; + int aa_is_stacked; + int aa_admin; + int aa_mount_features_enabled; + + int (*enabled)(struct lsm_ops *ops); + char *(*process_label_get)(struct lsm_ops *ops, pid_t pid); + int (*process_label_set)(struct lsm_ops *ops, const char *label, struct lxc_conf *conf, bool on_exec); + int (*keyring_label_set)(struct lsm_ops *ops, const char *label); + int (*prepare)(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath); + void (*cleanup)(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath); + int (*process_label_fd_get)(struct lsm_ops *ops, pid_t pid, bool on_exec); + int (*process_label_set_at)(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec); }; -__hidden extern const struct lsm_ops *lsm_init(void); +__hidden extern struct lsm_ops *lsm_init(void); #endif /* __LXC_LSM_H */ diff --git a/src/lxc/lsm/nop.c b/src/lxc/lsm/nop.c index f5f08425f..955552f39 100644 --- a/src/lxc/lsm/nop.c +++ b/src/lxc/lsm/nop.c @@ -8,59 +8,66 @@ #include "config.h" #include "lsm/lsm.h" -static char *nop_process_label_get(pid_t pid) +static char *nop_process_label_get(struct lsm_ops *ops, pid_t pid) { return NULL; } -static int nop_process_label_set(const char *label, struct lxc_conf *conf, +static int nop_process_label_set(struct lsm_ops *ops, const char *label, struct lxc_conf *conf, bool on_exec) { return 0; } -static int nop_enabled(void) +static int nop_enabled(struct lsm_ops *ops) { return 0; } -static int nop_keyring_label_set(const char *label) +static int nop_keyring_label_set(struct lsm_ops *ops, const char *label) { return 0; } -static int nop_prepare(struct lxc_conf *conf, const char *lxcpath) +static int nop_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { return 0; } -static void nop_cleanup(struct lxc_conf *conf, const char *lxcpath) +static void nop_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { } -static int nop_process_label_fd_get(pid_t pid, bool on_exec) +static int nop_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec) { return 0; } -static int nop_process_label_set_at(int label_fd, const char *label, bool on_exec) +static int nop_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec) { return 0; } static struct lsm_ops nop_ops = { - .name = "nop", - .cleanup = nop_cleanup, - .enabled = nop_enabled, - .keyring_label_set = nop_keyring_label_set, - .prepare = nop_prepare, - .process_label_fd_get = nop_process_label_fd_get, - .process_label_get = nop_process_label_get, - .process_label_set = nop_process_label_set, - .process_label_set_at = nop_process_label_set_at, + .name = "nop", + .aa_admin = -1, + .aa_can_stack = -1, + .aa_enabled = -1, + .aa_is_stacked = -1, + .aa_mount_features_enabled = -1, + .aa_parser_available = -1, + .aa_supports_unix = -1, + .cleanup = nop_cleanup, + .enabled = nop_enabled, + .keyring_label_set = nop_keyring_label_set, + .prepare = nop_prepare, + .process_label_fd_get = nop_process_label_fd_get, + .process_label_get = nop_process_label_get, + .process_label_set = nop_process_label_set, + .process_label_set_at = nop_process_label_set_at, }; -const struct lsm_ops *lsm_nop_ops_init(void) +struct lsm_ops *lsm_nop_ops_init(void) { return &nop_ops; } diff --git a/src/lxc/lsm/selinux.c b/src/lxc/lsm/selinux.c index 8fa8c2e3f..22906c200 100644 --- a/src/lxc/lsm/selinux.c +++ b/src/lxc/lsm/selinux.c @@ -30,7 +30,7 @@ lxc_log_define(selinux, lsm); * * Note that this relies on /proc being available. */ -static char *selinux_process_label_get(pid_t pid) +static char *selinux_process_label_get(struct lsm_ops *ops, pid_t pid) { char *label; @@ -52,8 +52,8 @@ 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 on_exec) +static int selinux_process_label_set(struct lsm_ops *ops, const char *inlabel, + struct lxc_conf *conf, bool on_exec) { int ret; const char *label; @@ -84,21 +84,21 @@ static int selinux_process_label_set(const char *inlabel, struct lxc_conf *conf, * * Returns 0 on success, < 0 on failure */ -static int selinux_keyring_label_set(const char *label) +static int selinux_keyring_label_set(struct lsm_ops *ops, const char *label) { return setkeycreatecon_raw(label); } -static int selinux_prepare(struct lxc_conf *conf, const char *lxcpath) +static int selinux_prepare(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { return 0; } -static void selinux_cleanup(struct lxc_conf *conf, const char *lxcpath) +static void selinux_cleanup(struct lsm_ops *ops, struct lxc_conf *conf, const char *lxcpath) { } -static int selinux_process_label_fd_get(pid_t pid, bool on_exec) +static int selinux_process_label_fd_get(struct lsm_ops *ops, pid_t pid, bool on_exec) { int ret = -1; int labelfd; @@ -118,7 +118,7 @@ static int selinux_process_label_fd_get(pid_t pid, bool on_exec) return labelfd; } -static int selinux_process_label_set_at(int label_fd, const char *label, bool on_exec) +static int selinux_process_label_set_at(struct lsm_ops *ops, int label_fd, const char *label, bool on_exec) { int ret; @@ -133,19 +133,31 @@ static int selinux_process_label_set_at(int label_fd, const char *label, bool on return 0; } +static int selinux_enabled(struct lsm_ops *ops) +{ + return is_selinux_enabled(); +} + static struct lsm_ops selinux_ops = { - .name = "SELinux", - .cleanup = selinux_cleanup, - .enabled = is_selinux_enabled, - .keyring_label_set = selinux_keyring_label_set, - .prepare = selinux_prepare, - .process_label_fd_get = selinux_process_label_fd_get, - .process_label_get = selinux_process_label_get, - .process_label_set = selinux_process_label_set, - .process_label_set_at = selinux_process_label_set_at, + .name = "SELinux", + .aa_admin = -1, + .aa_can_stack = -1, + .aa_enabled = -1, + .aa_is_stacked = -1, + .aa_mount_features_enabled = -1, + .aa_parser_available = -1, + .aa_supports_unix = -1, + .cleanup = selinux_cleanup, + .enabled = selinux_enabled, + .keyring_label_set = selinux_keyring_label_set, + .prepare = selinux_prepare, + .process_label_fd_get = selinux_process_label_fd_get, + .process_label_get = selinux_process_label_get, + .process_label_set = selinux_process_label_set, + .process_label_set_at = selinux_process_label_set_at, }; -const struct lsm_ops *lsm_selinux_ops_init(void) +struct lsm_ops *lsm_selinux_ops_init(void) { if (!is_selinux_enabled()) return NULL; diff --git a/src/lxc/start.c b/src/lxc/start.c index 732e8d18f..322debf00 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -827,7 +827,7 @@ int lxc_init(const char *name, struct lxc_handler *handler) return log_error(-1, "Failed loading seccomp policy"); TRACE("Read seccomp policy"); - ret = handler->lsm_ops->prepare(conf, handler->lxcpath); + ret = handler->lsm_ops->prepare(handler->lsm_ops, conf, handler->lxcpath); if (ret < 0) { ERROR("Failed to initialize LSM"); goto out_delete_terminal; @@ -918,7 +918,7 @@ void lxc_end(struct lxc_handler *handler) while (namespace_count--) free(namespaces[namespace_count]); - handler->lsm_ops->cleanup(handler->conf, handler->lxcpath); + handler->lsm_ops->cleanup(handler->lsm_ops, handler->conf, handler->lxcpath); if (cgroup_ops) { cgroup_ops->payload_destroy(cgroup_ops, handler); @@ -1269,7 +1269,7 @@ static int do_start(void *data) } /* Set the label to change to when we exec(2) the container's init. */ - ret = handler->lsm_ops->process_label_set(NULL, handler->conf, true); + ret = handler->lsm_ops->process_label_set(handler->lsm_ops, NULL, handler->conf, true); if (ret < 0) goto out_warn_father; diff --git a/src/lxc/start.h b/src/lxc/start.h index 3c9fa04b5..9d23df955 100644 --- a/src/lxc/start.h +++ b/src/lxc/start.h @@ -128,7 +128,8 @@ struct lxc_handler { /* Internal fds that always need to stay open. */ int keep_fds[3]; - const struct lsm_ops *lsm_ops; + /* Static memory, don't free. */ + struct lsm_ops *lsm_ops; }; struct execute_args { diff --git a/src/tests/attach.c b/src/tests/attach.c index 79fd790e7..879017fd8 100644 --- a/src/tests/attach.c +++ b/src/tests/attach.c @@ -47,11 +47,11 @@ static const char *lsm_config_key = NULL; static const char *lsm_label = NULL; -const struct lsm_ops *lsm_ops; +struct lsm_ops *lsm_ops; static void test_lsm_detect(void) { - if (lsm_ops->enabled()) { + if (lsm_ops->enabled(lsm_ops)) { if (!strcmp(lsm_ops->name, "SELinux")) { lsm_config_key = "lxc.selinux.context"; lsm_label = "unconfined_u:unconfined_r:lxc_t:s0-s0:c0.c1023"; @@ -80,7 +80,7 @@ static void test_attach_lsm_set_config(struct lxc_container *ct) static int test_attach_lsm_func_func(void* payload) { - TSTOUT("%s", lsm_ops->process_label_get(syscall(SYS_getpid))); + TSTOUT("%s", lsm_ops->process_label_get(lsm_ops, syscall(SYS_getpid))); return 0; } @@ -330,7 +330,7 @@ static struct lxc_container *test_ct_create(const char *lxcpath, goto out2; } - if (lsm_ops->enabled()) + if (lsm_ops->enabled(lsm_ops)) test_attach_lsm_set_config(ct); ct->want_daemonize(ct, true); @@ -370,7 +370,7 @@ static int test_attach(const char *lxcpath, const char *name, const char *templa goto err2; } - if (lsm_ops->enabled()) { + if (lsm_ops->enabled(lsm_ops)) { ret = test_attach_lsm_cmd(ct); if (ret < 0) { TSTERR("attach lsm cmd test failed");