]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
LSM: Lift LSM selection out of individual LSMs
authorKees Cook <keescook@chromium.org>
Fri, 14 Sep 2018 06:17:50 +0000 (23:17 -0700)
committerKees Cook <keescook@chromium.org>
Tue, 8 Jan 2019 21:18:42 +0000 (13:18 -0800)
As a prerequisite to adjusting LSM selection logic in the future, this
moves the selection logic up out of the individual major LSMs, making
their init functions only run when actually enabled. This considers all
LSMs enabled by default unless they specified an external "enable"
variable.

Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: John Johansen <john.johansen@canonical.com>
include/linux/lsm_hooks.h
security/apparmor/lsm.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c
security/tomoyo/tomoyo.c

index 7bbe5e287161956047aff5c7537b6a1c8c88cce7..be1581d18e3ec508927f71ca44c2e9e1fee2e32c 100644 (file)
@@ -2088,7 +2088,6 @@ static inline void security_delete_hooks(struct security_hook_list *hooks,
 #define __lsm_ro_after_init    __ro_after_init
 #endif /* CONFIG_SECURITY_WRITABLE_HOOKS */
 
-extern int __init security_module_enable(const char *module);
 extern void __init capability_add_hooks(void);
 #ifdef CONFIG_SECURITY_YAMA
 extern void __init yama_add_hooks(void);
index a4652ff622cfd8a8e091851fb25bdc4fc159c98b..dfc5fbf8ba828d151f5cceece6b60c89a9e455cf 100644 (file)
@@ -1663,12 +1663,6 @@ static int __init apparmor_init(void)
 {
        int error;
 
-       if (!apparmor_enabled || !security_module_enable("apparmor")) {
-               aa_info_message("AppArmor disabled by boot time parameter");
-               apparmor_enabled = false;
-               return 0;
-       }
-
        aa_secids_init();
 
        error = aa_setup_dfa_engine();
index 6bc591f77b1a2f14436c652cf1a1696e3a4520ea..c900d7a1441a198dc6cbbb8353358f05d65a6d76 100644 (file)
@@ -52,33 +52,96 @@ static __initdata bool debug;
                        pr_info(__VA_ARGS__);                   \
        } while (0)
 
+static bool __init is_enabled(struct lsm_info *lsm)
+{
+       if (!lsm->enabled || *lsm->enabled)
+               return true;
+
+       return false;
+}
+
+/* Mark an LSM's enabled flag. */
+static int lsm_enabled_true __initdata = 1;
+static int lsm_enabled_false __initdata = 0;
+static void __init set_enabled(struct lsm_info *lsm, bool enabled)
+{
+       /*
+        * When an LSM hasn't configured an enable variable, we can use
+        * a hard-coded location for storing the default enabled state.
+        */
+       if (!lsm->enabled) {
+               if (enabled)
+                       lsm->enabled = &lsm_enabled_true;
+               else
+                       lsm->enabled = &lsm_enabled_false;
+       } else if (lsm->enabled == &lsm_enabled_true) {
+               if (!enabled)
+                       lsm->enabled = &lsm_enabled_false;
+       } else if (lsm->enabled == &lsm_enabled_false) {
+               if (enabled)
+                       lsm->enabled = &lsm_enabled_true;
+       } else {
+               *lsm->enabled = enabled;
+       }
+}
+
+/* Is an LSM allowed to be initialized? */
+static bool __init lsm_allowed(struct lsm_info *lsm)
+{
+       /* Skip if the LSM is disabled. */
+       if (!is_enabled(lsm))
+               return false;
+
+       /* Skip major-specific checks if not a major LSM. */
+       if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
+               return true;
+
+       /* Disabled if this LSM isn't the chosen one. */
+       if (strcmp(lsm->name, chosen_lsm) != 0)
+               return false;
+
+       return true;
+}
+
+/* Check if LSM should be initialized. */
+static void __init maybe_initialize_lsm(struct lsm_info *lsm)
+{
+       int enabled = lsm_allowed(lsm);
+
+       /* Record enablement (to handle any following exclusive LSMs). */
+       set_enabled(lsm, enabled);
+
+       /* If selected, initialize the LSM. */
+       if (enabled) {
+               int ret;
+
+               init_debug("initializing %s\n", lsm->name);
+               ret = lsm->init();
+               WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+       }
+}
+
 static void __init ordered_lsm_init(void)
 {
        struct lsm_info *lsm;
-       int ret;
 
        for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
                if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) != 0)
                        continue;
 
-               init_debug("initializing %s\n", lsm->name);
-               ret = lsm->init();
-               WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+               maybe_initialize_lsm(lsm);
        }
 }
 
 static void __init major_lsm_init(void)
 {
        struct lsm_info *lsm;
-       int ret;
 
        for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
                if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) == 0)
                        continue;
 
-               init_debug("initializing %s\n", lsm->name);
-               ret = lsm->init();
-               WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);
+               maybe_initialize_lsm(lsm);
        }
 }
 
@@ -168,29 +231,6 @@ static int lsm_append(char *new, char **result)
        return 0;
 }
 
-/**
- * security_module_enable - Load given security module on boot ?
- * @module: the name of the module
- *
- * Each LSM must pass this method before registering its own operations
- * to avoid security registration races. This method may also be used
- * to check if your LSM is currently loaded during kernel initialization.
- *
- * Returns:
- *
- * true if:
- *
- * - The passed LSM is the one chosen by user at boot time,
- * - or the passed LSM is configured as the default and the user did not
- *   choose an alternate LSM at boot time.
- *
- * Otherwise, return false.
- */
-int __init security_module_enable(const char *module)
-{
-       return !strcmp(module, chosen_lsm);
-}
-
 /**
  * security_add_hooks - Add a modules hooks to the hook lists.
  * @hooks: the hooks to add
index f847514d6f03d9f2771cf073fac75c3bb66f177a..0f8ae2fbd14a677e91039b5ddb1ca2ce3b77899d 100644 (file)
@@ -6928,16 +6928,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 
 static __init int selinux_init(void)
 {
-       if (!security_module_enable("selinux")) {
-               selinux_enabled = 0;
-               return 0;
-       }
-
-       if (!selinux_enabled) {
-               pr_info("SELinux:  Disabled at boot.\n");
-               return 0;
-       }
-
        pr_info("SELinux:  Initializing.\n");
 
        memset(&selinux_state, 0, sizeof(selinux_state));
index d72d215d7fdedbff59756b5ecc903a0bfb7a10a1..580e9d6e5680ae5da332edfdf00fc018eab00a31 100644 (file)
@@ -4762,9 +4762,6 @@ static __init int smack_init(void)
        struct cred *cred;
        struct task_smack *tsp;
 
-       if (!security_module_enable("smack"))
-               return 0;
-
        smack_inode_cache = KMEM_CACHE(inode_smack, 0);
        if (!smack_inode_cache)
                return -ENOMEM;
index 09f7af130d3a1b1ba1f9cbcb9b160493fcd63630..a46f6bc1e97c1e72a264f3224b75a463192ea842 100644 (file)
@@ -540,8 +540,6 @@ static int __init tomoyo_init(void)
 {
        struct cred *cred = (struct cred *) current_cred();
 
-       if (!security_module_enable("tomoyo"))
-               return 0;
        /* register ourselves with the security framework */
        security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
        printk(KERN_INFO "TOMOYO Linux initialized\n");