]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lsm: remove the need for atomic operations 3518/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 12 Aug 2020 13:26:22 +0000 (15:26 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 12 Aug 2020 20:42:40 +0000 (22:42 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/attach.c
src/lxc/attach.h
src/lxc/conf.c
src/lxc/lsm/apparmor.c
src/lxc/lsm/lsm.c
src/lxc/lsm/lsm.h
src/lxc/lsm/nop.c
src/lxc/lsm/selinux.c
src/lxc/start.c
src/lxc/start.h
src/tests/attach.c

index 94a80c2bd6dcd007157710d5028acdaf6ca79dee..4b95989227f4f94fb3f2274773dffaa9d7aa9d89 100644 (file)
@@ -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;
 
index bc9a81376c41b25d769205c5a5a3ede1939d3b2f..5649edd10fe80015ce858bfe1d026f12b256767d 100644 (file)
@@ -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,
index 2067b03c896ef419adc4e9998f8d6362f16cc068..d570a75e8204fad79b92b6f836727153bfe02612 100644 (file)
@@ -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");
 
index c4fce1ee6c21cf658ad1956236a2e24deca581bf..b09d47090544742a87fd862e204800f7f8a55999 100644 (file)
@@ -4,7 +4,6 @@
 #define _GNU_SOURCE 1
 #endif
 #include <errno.h>
-#include <stdatomic.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mount.h>
 
 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;
 }
index 93c3aca8207ca2c5f5374a11e5dfe16a5ce31d0f..7fe34bfb035b7917af14a2d3653e1a4140ca7191 100644 (file)
@@ -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();
index c035db29d1b447650ece66161463d15cd4c86df4..52d4364255872b4e40895949b5387efa2b37166a 100644 (file)
@@ -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 */
index f5f08425f05883fbe47eca35e35c4d7025f37e13..955552f39007ddbef2f756aeeb03ac7fb0c8fa27 100644 (file)
@@ -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;
 }
index 8fa8c2e3f1d83e372507053330bb55ee241dc138..22906c2006ce0c4b4df966df42b367927290eab1 100644 (file)
@@ -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;
index 732e8d18f61c0449ec0a86a161194889e7935a35..322debf00f2c2c5af8c833d7f32313c16b8528d8 100644 (file)
@@ -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;
 
index 3c9fa04b58f40a64d0de96565b61cf042b88d123..9d23df955bc87835447d2481f5495c90c6b3b436 100644 (file)
@@ -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 {
index 79fd790e7ecd9503fd2ee70b608c3934abe4595a..879017fd819551b7cddd41b6097f3754208e2778 100644 (file)
 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");