One part of a larger effort to cleanup the LSM framework initialization
code.

Signed-off-by: Paul Moore <p...@paul-moore.com>
---
 security/lsm_init.c | 211 ++++++++++++++++++++++----------------------
 1 file changed, 106 insertions(+), 105 deletions(-)

diff --git a/security/lsm_init.c b/security/lsm_init.c
index 163fc2a1a952..e07fd4d2a16a 100644
--- a/security/lsm_init.c
+++ b/security/lsm_init.c
@@ -36,6 +36,9 @@ static __initdata bool debug;
 
 #define lsm_order_for_each(iter)                                       \
        for ((iter) = lsm_order; *(iter); (iter)++)
+#define lsm_for_each_raw(iter)                                         \
+       for ((iter) = __start_lsm_info;                                 \
+            (iter) < __end_lsm_info; (iter)++)
 #define lsm_early_for_each_raw(iter)                                   \
        for ((iter) = __start_early_lsm_info;                           \
             (iter) < __end_early_lsm_info; (iter)++)
@@ -127,6 +130,10 @@ static bool __init lsm_order_exists(struct lsm_info *lsm)
  * lsm_order_append - Append a LSM to the ordered list
  * @lsm: LSM definition
  * @src: source of the addition
+ *
+ * Append @lsm to the enabled LSM array after ensuring that it hasn't been
+ * explicitly disabled, is a duplicate entry, or would run afoul of the
+ * LSM_FLAG_EXCLUSIVE logic.
  */
 static void __init lsm_order_append(struct lsm_info *lsm, const char *src)
 {
@@ -135,19 +142,106 @@ static void __init lsm_order_append(struct lsm_info 
*lsm, const char *src)
                return;
 
        /* Skip explicitly disabled LSMs. */
-       if (lsm->enabled && !lsm_is_enabled(lsm)) {
-               if (WARN(lsm_count == MAX_LSM_COUNT,
-                        "%s: out of LSM static calls!?\n", src))
-                       return;
-               lsm_enabled_set(lsm, true);
-               lsm_order[lsm_count] = lsm;
-               lsm_idlist[lsm_count++] = lsm->id;
+       if (lsm->enabled && !lsm_is_enabled(lsm))
+               goto out;
+
+       if (WARN(lsm_count == MAX_LSM_COUNT,
+                "%s: out of LSM static calls!?\n", src)) {
+               lsm_enabled_set(lsm, false);
+               goto out;
        }
 
+       if (lsm->flags & LSM_FLAG_EXCLUSIVE) {
+               if (lsm_exclusive) {
+                       init_debug("exclusive disabled: %s\n", lsm->id->name);
+                       lsm_enabled_set(lsm, false);
+                       goto out;
+               } else {
+                       init_debug("exclusive chosen:   %s\n", lsm->id->name);
+                       lsm_exclusive = lsm;
+               }
+       }
+
+       lsm_enabled_set(lsm, true);
+       lsm_order[lsm_count] = lsm;
+       lsm_idlist[lsm_count++] = lsm->id;
+
+out:
        init_debug("%s ordered: %s (%s)\n", src, lsm->id->name,
                   lsm_is_enabled(lsm) ? "enabled" : "disabled");
 }
 
+/**
+ * lsm_order_parse - Parse the comma delimited LSM list
+ * @list: LSM list
+ * @src: source of the list
+ */
+static void __init lsm_order_parse(const char *list, const char *src)
+{
+       struct lsm_info *lsm;
+       char *sep, *name, *next;
+
+       /* Handle any Legacy LSM exclusions if one was specified. */
+       if (lsm_order_legacy) {
+               /*
+                * To match the original "security=" behavior, this explicitly
+                * does NOT fallback to another Legacy Major if the selected
+                * one was separately disabled: disable all non-matching
+                * Legacy Major LSMs.
+                */
+               lsm_for_each_raw(lsm) {
+                       if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) &&
+                            strcmp(lsm->id->name, lsm_order_legacy)) {
+                               lsm_enabled_set(lsm, false);
+                               init_debug("security=%s disabled: %s (only one 
legacy major LSM)\n",
+                                          lsm_order_legacy, lsm->id->name);
+                       }
+               }
+       }
+
+       /* LSM_ORDER_FIRST */
+       lsm_for_each_raw(lsm) {
+               if (lsm->order == LSM_ORDER_FIRST)
+                       lsm_order_append(lsm, "first");
+       }
+
+       /* Normal or "mutable" LSMs */
+       sep = kstrdup(list, GFP_KERNEL);
+       next = sep;
+       /* Walk the list, looking for matching LSMs. */
+       while ((name = strsep(&next, ",")) != NULL) {
+               lsm_for_each_raw(lsm) {
+                       if (!strcmp(lsm->id->name, name) &&
+                           lsm->order == LSM_ORDER_MUTABLE)
+                               lsm_order_append(lsm, src);
+               }
+       }
+       kfree(sep);
+
+       /* Legacy LSM if specified. */
+       if (lsm_order_legacy) {
+               lsm_for_each_raw(lsm) {
+                       if (!strcmp(lsm->id->name, lsm_order_legacy))
+                               lsm_order_append(lsm, src);
+               }
+       }
+
+       /* LSM_ORDER_LAST */
+       lsm_for_each_raw(lsm) {
+               if (lsm->order == LSM_ORDER_LAST)
+                       lsm_order_append(lsm, "last");
+       }
+
+       /* Disable all LSMs not previously enabled. */
+       lsm_for_each_raw(lsm) {
+               if (lsm_order_exists(lsm))
+                       continue;
+               lsm_enabled_set(lsm, false);
+               init_debug("%s skipped: %s (not in requested order)\n",
+                          src, lsm->id->name);
+       }
+}
+
 /**
  * lsm_blob_size_update - Update the LSM blob size and offset information
  * @sz_req: the requested additional blob size
@@ -172,26 +266,12 @@ static void __init lsm_blob_size_update(unsigned int 
*sz_req,
  */
 static void __init lsm_prep_single(struct lsm_info *lsm)
 {
-       struct lsm_blob_sizes *blobs;
+       struct lsm_blob_sizes *blobs = lsm->blobs;
 
-       if (!lsm_is_enabled(lsm)) {
-               lsm_enabled_set(lsm, false);
+       if (!blobs)
                return;
-       } else if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && lsm_exclusive) {
-               init_debug("exclusive disabled: %s\n", lsm->id->name);
-               lsm_enabled_set(lsm, false);
-               return;
-       }
-
-       /* Mark the LSM as enabled. */
-       lsm_enabled_set(lsm, true);
-       if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !lsm_exclusive) {
-               init_debug("exclusive chosen:   %s\n", lsm->id->name);
-               lsm_exclusive = lsm;
-       }
 
        /* Register the LSM blob sizes. */
-       blobs = lsm->blobs;
        lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred);
        lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file);
        lsm_blob_size_update(&blobs->lbs_ib, &blob_sizes.lbs_ib);
@@ -230,86 +310,6 @@ static void __init lsm_init_single(struct lsm_info *lsm)
        WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret);
 }
 
-/* Populate ordered LSMs list from comma-separated LSM name list. */
-static void __init ordered_lsm_parse(const char *order, const char *origin)
-{
-       struct lsm_info *lsm;
-       char *sep, *name, *next;
-
-       /* LSM_ORDER_FIRST is always first. */
-       for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
-               if (lsm->order == LSM_ORDER_FIRST)
-                       lsm_order_append(lsm, "  first");
-       }
-
-       /* Process "security=", if given. */
-       if (lsm_order_legacy) {
-               struct lsm_info *major;
-
-               /*
-                * To match the original "security=" behavior, this
-                * explicitly does NOT fallback to another Legacy Major
-                * if the selected one was separately disabled: disable
-                * all non-matching Legacy Major LSMs.
-                */
-               for (major = __start_lsm_info; major < __end_lsm_info;
-                    major++) {
-                       if ((major->flags & LSM_FLAG_LEGACY_MAJOR) &&
-                           strcmp(major->id->name, lsm_order_legacy) != 0) {
-                               lsm_enabled_set(major, false);
-                               init_debug("security=%s disabled: %s (only one 
legacy major LSM)\n",
-                                          lsm_order_legacy, major->id->name);
-                       }
-               }
-       }
-
-       sep = kstrdup(order, GFP_KERNEL);
-       next = sep;
-       /* Walk the list, looking for matching LSMs. */
-       while ((name = strsep(&next, ",")) != NULL) {
-               bool found = false;
-
-               for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
-                       if (strcmp(lsm->id->name, name) == 0) {
-                               if (lsm->order == LSM_ORDER_MUTABLE)
-                                       lsm_order_append(lsm, origin);
-                               found = true;
-                       }
-               }
-
-               if (!found)
-                       init_debug("%s ignored: %s (not built into kernel)\n",
-                                  origin, name);
-       }
-
-       /* Process "security=", if given. */
-       if (lsm_order_legacy) {
-               for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
-                       if (lsm_order_exists(lsm))
-                               continue;
-                       if (strcmp(lsm->id->name, lsm_order_legacy) == 0)
-                               lsm_order_append(lsm, "security=");
-               }
-       }
-
-       /* LSM_ORDER_LAST is always last. */
-       for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
-               if (lsm->order == LSM_ORDER_LAST)
-                       lsm_order_append(lsm, "   last");
-       }
-
-       /* Disable all LSMs not in the ordered list. */
-       for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
-               if (lsm_order_exists(lsm))
-                       continue;
-               lsm_enabled_set(lsm, false);
-               init_debug("%s skipped: %s (not in requested order)\n",
-                          origin, lsm->id->name);
-       }
-
-       kfree(sep);
-}
-
 /**
  * lsm_init_ordered - Initialize the ordered LSMs
  */
@@ -324,9 +324,9 @@ static void __init lsm_init_ordered(void)
                                lsm_order_legacy, lsm_order_cmdline);
                        lsm_order_legacy = NULL;
                }
-               ordered_lsm_parse(lsm_order_cmdline, "cmdline");
+               lsm_order_parse(lsm_order_cmdline, "cmdline");
        } else
-               ordered_lsm_parse(lsm_order_builtin, "builtin");
+               lsm_order_parse(lsm_order_builtin, "builtin");
 
        lsm_order_for_each(lsm) {
                lsm_prep_single(*lsm);
@@ -426,6 +426,7 @@ int __init early_security_init(void)
 
        lsm_early_for_each_raw(lsm) {
                lsm_enabled_set(lsm, true);
+               lsm_order_append(lsm, "early");
                lsm_prep_single(lsm);
                lsm_init_single(lsm);
        }
-- 
2.49.0


Reply via email to