167a4b6a8SPaul Moore // SPDX-License-Identifier: GPL-2.0-or-later 267a4b6a8SPaul Moore /* 367a4b6a8SPaul Moore * LSM initialization functions 467a4b6a8SPaul Moore */ 567a4b6a8SPaul Moore 667a4b6a8SPaul Moore #define pr_fmt(fmt) "LSM: " fmt 767a4b6a8SPaul Moore 867a4b6a8SPaul Moore #include <linux/init.h> 967a4b6a8SPaul Moore #include <linux/lsm_hooks.h> 1067a4b6a8SPaul Moore 1167a4b6a8SPaul Moore #include "lsm.h" 1267a4b6a8SPaul Moore 1367a4b6a8SPaul Moore char *lsm_names; 1467a4b6a8SPaul Moore 1567a4b6a8SPaul Moore /* Pointers to LSM sections defined in include/asm-generic/vmlinux.lds.h */ 1667a4b6a8SPaul Moore extern struct lsm_info __start_lsm_info[], __end_lsm_info[]; 1767a4b6a8SPaul Moore extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[]; 1867a4b6a8SPaul Moore 1967a4b6a8SPaul Moore /* Boot-time LSM user choice */ 2067a4b6a8SPaul Moore static __initconst const char *const builtin_lsm_order = CONFIG_LSM; 2167a4b6a8SPaul Moore static __initdata const char *chosen_lsm_order; 2267a4b6a8SPaul Moore static __initdata const char *chosen_major_lsm; 2367a4b6a8SPaul Moore 2467a4b6a8SPaul Moore /* Ordered list of LSMs to initialize. */ 2567a4b6a8SPaul Moore static __initdata struct lsm_info *ordered_lsms[MAX_LSM_COUNT + 1]; 2667a4b6a8SPaul Moore static __initdata struct lsm_info *exclusive; 2767a4b6a8SPaul Moore 2867a4b6a8SPaul Moore static __initdata bool debug; 2967a4b6a8SPaul Moore #define init_debug(...) \ 3067a4b6a8SPaul Moore do { \ 3167a4b6a8SPaul Moore if (debug) \ 3267a4b6a8SPaul Moore pr_info(__VA_ARGS__); \ 3367a4b6a8SPaul Moore } while (0) 3467a4b6a8SPaul Moore 3537f788f6SPaul Moore #define lsm_order_for_each(iter) \ 3637f788f6SPaul Moore for ((iter) = ordered_lsms; *(iter); (iter)++) 3737f788f6SPaul Moore #define lsm_for_each_raw(iter) \ 3837f788f6SPaul Moore for ((iter) = __start_lsm_info; \ 3937f788f6SPaul Moore (iter) < __end_lsm_info; (iter)++) 4037f788f6SPaul Moore #define lsm_early_for_each_raw(iter) \ 4137f788f6SPaul Moore for ((iter) = __start_early_lsm_info; \ 4237f788f6SPaul Moore (iter) < __end_early_lsm_info; (iter)++) 4337f788f6SPaul Moore 4467a4b6a8SPaul Moore static int lsm_append(const char *new, char **result); 4567a4b6a8SPaul Moore 4667a4b6a8SPaul Moore /* Save user chosen LSM */ 4767a4b6a8SPaul Moore static int __init choose_major_lsm(char *str) 4867a4b6a8SPaul Moore { 4967a4b6a8SPaul Moore chosen_major_lsm = str; 5067a4b6a8SPaul Moore return 1; 5167a4b6a8SPaul Moore } 5267a4b6a8SPaul Moore __setup("security=", choose_major_lsm); 5367a4b6a8SPaul Moore 5467a4b6a8SPaul Moore /* Explicitly choose LSM initialization order. */ 5567a4b6a8SPaul Moore static int __init choose_lsm_order(char *str) 5667a4b6a8SPaul Moore { 5767a4b6a8SPaul Moore chosen_lsm_order = str; 5867a4b6a8SPaul Moore return 1; 5967a4b6a8SPaul Moore } 6067a4b6a8SPaul Moore __setup("lsm=", choose_lsm_order); 6167a4b6a8SPaul Moore 6267a4b6a8SPaul Moore /* Enable LSM order debugging. */ 6367a4b6a8SPaul Moore static int __init enable_debug(char *str) 6467a4b6a8SPaul Moore { 6567a4b6a8SPaul Moore debug = true; 6667a4b6a8SPaul Moore return 1; 6767a4b6a8SPaul Moore } 6867a4b6a8SPaul Moore __setup("lsm.debug", enable_debug); 6967a4b6a8SPaul Moore 7067a4b6a8SPaul Moore /* Mark an LSM's enabled flag. */ 7167a4b6a8SPaul Moore static int lsm_enabled_true __initdata = 1; 7267a4b6a8SPaul Moore static int lsm_enabled_false __initdata = 0; 7367a4b6a8SPaul Moore static void __init set_enabled(struct lsm_info *lsm, bool enabled) 7467a4b6a8SPaul Moore { 7567a4b6a8SPaul Moore /* 7667a4b6a8SPaul Moore * When an LSM hasn't configured an enable variable, we can use 7767a4b6a8SPaul Moore * a hard-coded location for storing the default enabled state. 7867a4b6a8SPaul Moore */ 7967a4b6a8SPaul Moore if (!lsm->enabled) { 8067a4b6a8SPaul Moore if (enabled) 8167a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 8267a4b6a8SPaul Moore else 8367a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_false; 8467a4b6a8SPaul Moore } else if (lsm->enabled == &lsm_enabled_true) { 8567a4b6a8SPaul Moore if (!enabled) 8667a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_false; 8767a4b6a8SPaul Moore } else if (lsm->enabled == &lsm_enabled_false) { 8867a4b6a8SPaul Moore if (enabled) 8967a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 9067a4b6a8SPaul Moore } else { 9167a4b6a8SPaul Moore *lsm->enabled = enabled; 9267a4b6a8SPaul Moore } 9367a4b6a8SPaul Moore } 9467a4b6a8SPaul Moore 9567a4b6a8SPaul Moore static inline bool is_enabled(struct lsm_info *lsm) 9667a4b6a8SPaul Moore { 9767a4b6a8SPaul Moore if (!lsm->enabled) 9867a4b6a8SPaul Moore return false; 9967a4b6a8SPaul Moore 10067a4b6a8SPaul Moore return *lsm->enabled; 10167a4b6a8SPaul Moore } 10267a4b6a8SPaul Moore 10367a4b6a8SPaul Moore /* Is an LSM already listed in the ordered LSMs list? */ 10467a4b6a8SPaul Moore static bool __init exists_ordered_lsm(struct lsm_info *lsm) 10567a4b6a8SPaul Moore { 10667a4b6a8SPaul Moore struct lsm_info **check; 10767a4b6a8SPaul Moore 10837f788f6SPaul Moore lsm_order_for_each(check) { 10967a4b6a8SPaul Moore if (*check == lsm) 11067a4b6a8SPaul Moore return true; 11137f788f6SPaul Moore } 11267a4b6a8SPaul Moore 11367a4b6a8SPaul Moore return false; 11467a4b6a8SPaul Moore } 11567a4b6a8SPaul Moore 11667a4b6a8SPaul Moore /* Append an LSM to the list of ordered LSMs to initialize. */ 11767a4b6a8SPaul Moore static int last_lsm __initdata; 11867a4b6a8SPaul Moore static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from) 11967a4b6a8SPaul Moore { 12067a4b6a8SPaul Moore /* Ignore duplicate selections. */ 12167a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 12267a4b6a8SPaul Moore return; 12367a4b6a8SPaul Moore 12467a4b6a8SPaul Moore if (WARN(last_lsm == MAX_LSM_COUNT, "%s: out of LSM static calls!?\n", from)) 12567a4b6a8SPaul Moore return; 12667a4b6a8SPaul Moore 12767a4b6a8SPaul Moore /* Enable this LSM, if it is not already set. */ 12867a4b6a8SPaul Moore if (!lsm->enabled) 12967a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 13067a4b6a8SPaul Moore ordered_lsms[last_lsm++] = lsm; 13167a4b6a8SPaul Moore 13267a4b6a8SPaul Moore init_debug("%s ordered: %s (%s)\n", from, lsm->name, 13367a4b6a8SPaul Moore is_enabled(lsm) ? "enabled" : "disabled"); 13467a4b6a8SPaul Moore } 13567a4b6a8SPaul Moore 13667a4b6a8SPaul Moore static void __init lsm_set_blob_size(int *need, int *lbs) 13767a4b6a8SPaul Moore { 13867a4b6a8SPaul Moore int offset; 13967a4b6a8SPaul Moore 14067a4b6a8SPaul Moore if (*need <= 0) 14167a4b6a8SPaul Moore return; 14267a4b6a8SPaul Moore 14367a4b6a8SPaul Moore offset = ALIGN(*lbs, sizeof(void *)); 14467a4b6a8SPaul Moore *lbs = offset + *need; 14567a4b6a8SPaul Moore *need = offset; 14667a4b6a8SPaul Moore } 14767a4b6a8SPaul Moore 148e0257856SPaul Moore /** 149e0257856SPaul Moore * lsm_prepare - Prepare the LSM framework for a new LSM 150e0257856SPaul Moore * @lsm: LSM definition 15167a4b6a8SPaul Moore */ 152e0257856SPaul Moore static void __init lsm_prepare(struct lsm_info *lsm) 15367a4b6a8SPaul Moore { 154e0257856SPaul Moore struct lsm_blob_sizes *blobs; 15567a4b6a8SPaul Moore 156e0257856SPaul Moore if (!is_enabled(lsm)) { 157e0257856SPaul Moore set_enabled(lsm, false); 158e0257856SPaul Moore return; 159e0257856SPaul Moore } else if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) { 160e0257856SPaul Moore init_debug("exclusive disabled: %s\n", lsm->name); 161e0257856SPaul Moore set_enabled(lsm, false); 162e0257856SPaul Moore return; 163e0257856SPaul Moore } 16467a4b6a8SPaul Moore 165e0257856SPaul Moore /* Mark the LSM as enabled. */ 166e0257856SPaul Moore set_enabled(lsm, true); 16767a4b6a8SPaul Moore if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) { 16867a4b6a8SPaul Moore init_debug("exclusive chosen: %s\n", lsm->name); 169e0257856SPaul Moore exclusive = lsm; 17067a4b6a8SPaul Moore } 17167a4b6a8SPaul Moore 172e0257856SPaul Moore /* Register the LSM blob sizes. */ 173e0257856SPaul Moore blobs = lsm->blobs; 174e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_cred, &blob_sizes.lbs_cred); 175e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_file, &blob_sizes.lbs_file); 176e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_ib, &blob_sizes.lbs_ib); 177e0257856SPaul Moore /* inode blob gets an rcu_head in addition to LSM blobs. */ 178e0257856SPaul Moore if (blobs->lbs_inode && blob_sizes.lbs_inode == 0) 179e0257856SPaul Moore blob_sizes.lbs_inode = sizeof(struct rcu_head); 180e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_inode, &blob_sizes.lbs_inode); 181e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_ipc, &blob_sizes.lbs_ipc); 182e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_key, &blob_sizes.lbs_key); 183e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg); 184e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_perf_event, &blob_sizes.lbs_perf_event); 185e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_sock, &blob_sizes.lbs_sock); 186e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_superblock, &blob_sizes.lbs_superblock); 187e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_task, &blob_sizes.lbs_task); 188e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev); 189e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_xattr_count, 190e0257856SPaul Moore &blob_sizes.lbs_xattr_count); 191e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bdev, &blob_sizes.lbs_bdev); 192e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_map, &blob_sizes.lbs_bpf_map); 193e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog); 194e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token); 19567a4b6a8SPaul Moore } 19667a4b6a8SPaul Moore 19767a4b6a8SPaul Moore /* Initialize a given LSM, if it is enabled. */ 19867a4b6a8SPaul Moore static void __init initialize_lsm(struct lsm_info *lsm) 19967a4b6a8SPaul Moore { 20067a4b6a8SPaul Moore if (is_enabled(lsm)) { 20167a4b6a8SPaul Moore int ret; 20267a4b6a8SPaul Moore 20367a4b6a8SPaul Moore init_debug("initializing %s\n", lsm->name); 20467a4b6a8SPaul Moore ret = lsm->init(); 20567a4b6a8SPaul Moore WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); 20667a4b6a8SPaul Moore } 20767a4b6a8SPaul Moore } 20867a4b6a8SPaul Moore 20967a4b6a8SPaul Moore /* 21067a4b6a8SPaul Moore * Current index to use while initializing the lsm id list. 21167a4b6a8SPaul Moore */ 21267a4b6a8SPaul Moore u32 lsm_active_cnt __ro_after_init; 21367a4b6a8SPaul Moore const struct lsm_id *lsm_idlist[MAX_LSM_COUNT]; 21467a4b6a8SPaul Moore 21567a4b6a8SPaul Moore /* Populate ordered LSMs list from comma-separated LSM name list. */ 21667a4b6a8SPaul Moore static void __init ordered_lsm_parse(const char *order, const char *origin) 21767a4b6a8SPaul Moore { 21867a4b6a8SPaul Moore struct lsm_info *lsm; 21967a4b6a8SPaul Moore char *sep, *name, *next; 22067a4b6a8SPaul Moore 22167a4b6a8SPaul Moore /* LSM_ORDER_FIRST is always first. */ 22237f788f6SPaul Moore lsm_for_each_raw(lsm) { 22367a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_FIRST) 22467a4b6a8SPaul Moore append_ordered_lsm(lsm, " first"); 22567a4b6a8SPaul Moore } 22667a4b6a8SPaul Moore 22767a4b6a8SPaul Moore /* Process "security=", if given. */ 22867a4b6a8SPaul Moore if (chosen_major_lsm) { 22967a4b6a8SPaul Moore struct lsm_info *major; 23067a4b6a8SPaul Moore 23167a4b6a8SPaul Moore /* 23267a4b6a8SPaul Moore * To match the original "security=" behavior, this 23367a4b6a8SPaul Moore * explicitly does NOT fallback to another Legacy Major 23467a4b6a8SPaul Moore * if the selected one was separately disabled: disable 23567a4b6a8SPaul Moore * all non-matching Legacy Major LSMs. 23667a4b6a8SPaul Moore */ 23737f788f6SPaul Moore lsm_for_each_raw(major) { 23867a4b6a8SPaul Moore if ((major->flags & LSM_FLAG_LEGACY_MAJOR) && 23967a4b6a8SPaul Moore strcmp(major->name, chosen_major_lsm) != 0) { 24067a4b6a8SPaul Moore set_enabled(major, false); 24167a4b6a8SPaul Moore init_debug("security=%s disabled: %s (only one legacy major LSM)\n", 24267a4b6a8SPaul Moore chosen_major_lsm, major->name); 24367a4b6a8SPaul Moore } 24467a4b6a8SPaul Moore } 24567a4b6a8SPaul Moore } 24667a4b6a8SPaul Moore 24767a4b6a8SPaul Moore sep = kstrdup(order, GFP_KERNEL); 24867a4b6a8SPaul Moore next = sep; 24967a4b6a8SPaul Moore /* Walk the list, looking for matching LSMs. */ 25067a4b6a8SPaul Moore while ((name = strsep(&next, ",")) != NULL) { 25167a4b6a8SPaul Moore bool found = false; 25267a4b6a8SPaul Moore 25337f788f6SPaul Moore lsm_for_each_raw(lsm) { 25467a4b6a8SPaul Moore if (strcmp(lsm->name, name) == 0) { 25567a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_MUTABLE) 25667a4b6a8SPaul Moore append_ordered_lsm(lsm, origin); 25767a4b6a8SPaul Moore found = true; 25867a4b6a8SPaul Moore } 25967a4b6a8SPaul Moore } 26067a4b6a8SPaul Moore 26167a4b6a8SPaul Moore if (!found) 26267a4b6a8SPaul Moore init_debug("%s ignored: %s (not built into kernel)\n", 26367a4b6a8SPaul Moore origin, name); 26467a4b6a8SPaul Moore } 26567a4b6a8SPaul Moore 26667a4b6a8SPaul Moore /* Process "security=", if given. */ 26767a4b6a8SPaul Moore if (chosen_major_lsm) { 26837f788f6SPaul Moore lsm_for_each_raw(lsm) { 26967a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 27067a4b6a8SPaul Moore continue; 27167a4b6a8SPaul Moore if (strcmp(lsm->name, chosen_major_lsm) == 0) 27267a4b6a8SPaul Moore append_ordered_lsm(lsm, "security="); 27367a4b6a8SPaul Moore } 27467a4b6a8SPaul Moore } 27567a4b6a8SPaul Moore 27667a4b6a8SPaul Moore /* LSM_ORDER_LAST is always last. */ 27737f788f6SPaul Moore lsm_for_each_raw(lsm) { 27867a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_LAST) 27967a4b6a8SPaul Moore append_ordered_lsm(lsm, " last"); 28067a4b6a8SPaul Moore } 28167a4b6a8SPaul Moore 28267a4b6a8SPaul Moore /* Disable all LSMs not in the ordered list. */ 28337f788f6SPaul Moore lsm_for_each_raw(lsm) { 28467a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 28567a4b6a8SPaul Moore continue; 28667a4b6a8SPaul Moore set_enabled(lsm, false); 28767a4b6a8SPaul Moore init_debug("%s skipped: %s (not in requested order)\n", 28867a4b6a8SPaul Moore origin, lsm->name); 28967a4b6a8SPaul Moore } 29067a4b6a8SPaul Moore 29167a4b6a8SPaul Moore kfree(sep); 29267a4b6a8SPaul Moore } 29367a4b6a8SPaul Moore 294*faabedcdSPaul Moore /** 295*faabedcdSPaul Moore * lsm_init_ordered - Initialize the ordered LSMs 296*faabedcdSPaul Moore */ 297*faabedcdSPaul Moore static void __init lsm_init_ordered(void) 29867a4b6a8SPaul Moore { 299cb1513dbSPaul Moore unsigned int first = 0; 30067a4b6a8SPaul Moore struct lsm_info **lsm; 301cb1513dbSPaul Moore struct lsm_info *early; 30267a4b6a8SPaul Moore 30367a4b6a8SPaul Moore if (chosen_lsm_order) { 30467a4b6a8SPaul Moore if (chosen_major_lsm) { 30567a4b6a8SPaul Moore pr_warn("security=%s is ignored because it is superseded by lsm=%s\n", 30667a4b6a8SPaul Moore chosen_major_lsm, chosen_lsm_order); 30767a4b6a8SPaul Moore chosen_major_lsm = NULL; 30867a4b6a8SPaul Moore } 30967a4b6a8SPaul Moore ordered_lsm_parse(chosen_lsm_order, "cmdline"); 31067a4b6a8SPaul Moore } else 31167a4b6a8SPaul Moore ordered_lsm_parse(builtin_lsm_order, "builtin"); 31267a4b6a8SPaul Moore 31337f788f6SPaul Moore lsm_order_for_each(lsm) { 314e0257856SPaul Moore lsm_prepare(*lsm); 31537f788f6SPaul Moore } 31667a4b6a8SPaul Moore 317cb1513dbSPaul Moore pr_info("initializing lsm="); 318cb1513dbSPaul Moore lsm_early_for_each_raw(early) { 319cb1513dbSPaul Moore if (is_enabled(early)) 320cb1513dbSPaul Moore pr_cont("%s%s", first++ == 0 ? "" : ",", early->name); 321cb1513dbSPaul Moore } 322cb1513dbSPaul Moore lsm_order_for_each(lsm) { 323cb1513dbSPaul Moore if (is_enabled(*lsm)) 324cb1513dbSPaul Moore pr_cont("%s%s", first++ == 0 ? "" : ",", (*lsm)->name); 325cb1513dbSPaul Moore } 326cb1513dbSPaul Moore pr_cont("\n"); 32767a4b6a8SPaul Moore 32867a4b6a8SPaul Moore init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); 32967a4b6a8SPaul Moore init_debug("file blob size = %d\n", blob_sizes.lbs_file); 33067a4b6a8SPaul Moore init_debug("ib blob size = %d\n", blob_sizes.lbs_ib); 33167a4b6a8SPaul Moore init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); 33267a4b6a8SPaul Moore init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); 33367a4b6a8SPaul Moore #ifdef CONFIG_KEYS 33467a4b6a8SPaul Moore init_debug("key blob size = %d\n", blob_sizes.lbs_key); 33567a4b6a8SPaul Moore #endif /* CONFIG_KEYS */ 33667a4b6a8SPaul Moore init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); 33767a4b6a8SPaul Moore init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); 33867a4b6a8SPaul Moore init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock); 33967a4b6a8SPaul Moore init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event); 34067a4b6a8SPaul Moore init_debug("task blob size = %d\n", blob_sizes.lbs_task); 34167a4b6a8SPaul Moore init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev); 34267a4b6a8SPaul Moore init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count); 34367a4b6a8SPaul Moore init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); 34467a4b6a8SPaul Moore init_debug("bpf map blob size = %d\n", blob_sizes.lbs_bpf_map); 34567a4b6a8SPaul Moore init_debug("bpf prog blob size = %d\n", blob_sizes.lbs_bpf_prog); 34667a4b6a8SPaul Moore init_debug("bpf token blob size = %d\n", blob_sizes.lbs_bpf_token); 34767a4b6a8SPaul Moore 34867a4b6a8SPaul Moore if (blob_sizes.lbs_file) 34967a4b6a8SPaul Moore lsm_file_cache = kmem_cache_create("lsm_file_cache", 35067a4b6a8SPaul Moore blob_sizes.lbs_file, 0, 35167a4b6a8SPaul Moore SLAB_PANIC, NULL); 35267a4b6a8SPaul Moore if (blob_sizes.lbs_inode) 35367a4b6a8SPaul Moore lsm_inode_cache = kmem_cache_create("lsm_inode_cache", 35467a4b6a8SPaul Moore blob_sizes.lbs_inode, 0, 35567a4b6a8SPaul Moore SLAB_PANIC, NULL); 35667a4b6a8SPaul Moore 35792ed3500SPaul Moore if (lsm_cred_alloc((struct cred __rcu *)current->cred, GFP_KERNEL)) 35892ed3500SPaul Moore panic("%s: early cred alloc failed.\n", __func__); 35992ed3500SPaul Moore if (lsm_task_alloc(current)) 36092ed3500SPaul Moore panic("%s: early task alloc failed.\n", __func__); 36192ed3500SPaul Moore 36237f788f6SPaul Moore lsm_order_for_each(lsm) { 36367a4b6a8SPaul Moore initialize_lsm(*lsm); 36467a4b6a8SPaul Moore } 36537f788f6SPaul Moore } 36667a4b6a8SPaul Moore 36767a4b6a8SPaul Moore static bool match_last_lsm(const char *list, const char *lsm) 36867a4b6a8SPaul Moore { 36967a4b6a8SPaul Moore const char *last; 37067a4b6a8SPaul Moore 37167a4b6a8SPaul Moore if (WARN_ON(!list || !lsm)) 37267a4b6a8SPaul Moore return false; 37367a4b6a8SPaul Moore last = strrchr(list, ','); 37467a4b6a8SPaul Moore if (last) 37567a4b6a8SPaul Moore /* Pass the comma, strcmp() will check for '\0' */ 37667a4b6a8SPaul Moore last++; 37767a4b6a8SPaul Moore else 37867a4b6a8SPaul Moore last = list; 37967a4b6a8SPaul Moore return !strcmp(last, lsm); 38067a4b6a8SPaul Moore } 38167a4b6a8SPaul Moore 38267a4b6a8SPaul Moore static int lsm_append(const char *new, char **result) 38367a4b6a8SPaul Moore { 38467a4b6a8SPaul Moore char *cp; 38567a4b6a8SPaul Moore 38667a4b6a8SPaul Moore if (*result == NULL) { 38767a4b6a8SPaul Moore *result = kstrdup(new, GFP_KERNEL); 38867a4b6a8SPaul Moore if (*result == NULL) 38967a4b6a8SPaul Moore return -ENOMEM; 39067a4b6a8SPaul Moore } else { 39167a4b6a8SPaul Moore /* Check if it is the last registered name */ 39267a4b6a8SPaul Moore if (match_last_lsm(*result, new)) 39367a4b6a8SPaul Moore return 0; 39467a4b6a8SPaul Moore cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new); 39567a4b6a8SPaul Moore if (cp == NULL) 39667a4b6a8SPaul Moore return -ENOMEM; 39767a4b6a8SPaul Moore kfree(*result); 39867a4b6a8SPaul Moore *result = cp; 39967a4b6a8SPaul Moore } 40067a4b6a8SPaul Moore return 0; 40167a4b6a8SPaul Moore } 40267a4b6a8SPaul Moore 40367a4b6a8SPaul Moore static void __init lsm_static_call_init(struct security_hook_list *hl) 40467a4b6a8SPaul Moore { 40567a4b6a8SPaul Moore struct lsm_static_call *scall = hl->scalls; 40667a4b6a8SPaul Moore int i; 40767a4b6a8SPaul Moore 40867a4b6a8SPaul Moore for (i = 0; i < MAX_LSM_COUNT; i++) { 40967a4b6a8SPaul Moore /* Update the first static call that is not used yet */ 41067a4b6a8SPaul Moore if (!scall->hl) { 41167a4b6a8SPaul Moore __static_call_update(scall->key, scall->trampoline, 41267a4b6a8SPaul Moore hl->hook.lsm_func_addr); 41367a4b6a8SPaul Moore scall->hl = hl; 41467a4b6a8SPaul Moore static_branch_enable(scall->active); 41567a4b6a8SPaul Moore return; 41667a4b6a8SPaul Moore } 41767a4b6a8SPaul Moore scall++; 41867a4b6a8SPaul Moore } 41967a4b6a8SPaul Moore panic("%s - Ran out of static slots.\n", __func__); 42067a4b6a8SPaul Moore } 42167a4b6a8SPaul Moore 42267a4b6a8SPaul Moore /** 42367a4b6a8SPaul Moore * security_add_hooks - Add a modules hooks to the hook lists. 42467a4b6a8SPaul Moore * @hooks: the hooks to add 42567a4b6a8SPaul Moore * @count: the number of hooks to add 42667a4b6a8SPaul Moore * @lsmid: the identification information for the security module 42767a4b6a8SPaul Moore * 42867a4b6a8SPaul Moore * Each LSM has to register its hooks with the infrastructure. 42967a4b6a8SPaul Moore */ 43067a4b6a8SPaul Moore void __init security_add_hooks(struct security_hook_list *hooks, int count, 43167a4b6a8SPaul Moore const struct lsm_id *lsmid) 43267a4b6a8SPaul Moore { 43367a4b6a8SPaul Moore int i; 43467a4b6a8SPaul Moore 43567a4b6a8SPaul Moore /* 43667a4b6a8SPaul Moore * A security module may call security_add_hooks() more 43767a4b6a8SPaul Moore * than once during initialization, and LSM initialization 43867a4b6a8SPaul Moore * is serialized. Landlock is one such case. 43967a4b6a8SPaul Moore * Look at the previous entry, if there is one, for duplication. 44067a4b6a8SPaul Moore */ 44167a4b6a8SPaul Moore if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid) { 44267a4b6a8SPaul Moore if (lsm_active_cnt >= MAX_LSM_COUNT) 44367a4b6a8SPaul Moore panic("%s Too many LSMs registered.\n", __func__); 44467a4b6a8SPaul Moore lsm_idlist[lsm_active_cnt++] = lsmid; 44567a4b6a8SPaul Moore } 44667a4b6a8SPaul Moore 44767a4b6a8SPaul Moore for (i = 0; i < count; i++) { 44867a4b6a8SPaul Moore hooks[i].lsmid = lsmid; 44967a4b6a8SPaul Moore lsm_static_call_init(&hooks[i]); 45067a4b6a8SPaul Moore } 45167a4b6a8SPaul Moore 45267a4b6a8SPaul Moore /* 45367a4b6a8SPaul Moore * Don't try to append during early_security_init(), we'll come back 45467a4b6a8SPaul Moore * and fix this up afterwards. 45567a4b6a8SPaul Moore */ 45667a4b6a8SPaul Moore if (slab_is_available()) { 45767a4b6a8SPaul Moore if (lsm_append(lsmid->name, &lsm_names) < 0) 45867a4b6a8SPaul Moore panic("%s - Cannot get early memory.\n", __func__); 45967a4b6a8SPaul Moore } 46067a4b6a8SPaul Moore } 46167a4b6a8SPaul Moore 46267a4b6a8SPaul Moore int __init early_security_init(void) 46367a4b6a8SPaul Moore { 46467a4b6a8SPaul Moore struct lsm_info *lsm; 46567a4b6a8SPaul Moore 46637f788f6SPaul Moore lsm_early_for_each_raw(lsm) { 46767a4b6a8SPaul Moore if (!lsm->enabled) 46867a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 469e0257856SPaul Moore lsm_prepare(lsm); 47067a4b6a8SPaul Moore initialize_lsm(lsm); 47167a4b6a8SPaul Moore } 47267a4b6a8SPaul Moore 47367a4b6a8SPaul Moore return 0; 47467a4b6a8SPaul Moore } 47567a4b6a8SPaul Moore 47667a4b6a8SPaul Moore /** 47767a4b6a8SPaul Moore * security_init - initializes the security framework 47867a4b6a8SPaul Moore * 47967a4b6a8SPaul Moore * This should be called early in the kernel initialization sequence. 48067a4b6a8SPaul Moore */ 48167a4b6a8SPaul Moore int __init security_init(void) 48267a4b6a8SPaul Moore { 48367a4b6a8SPaul Moore struct lsm_info *lsm; 48467a4b6a8SPaul Moore 48567a4b6a8SPaul Moore init_debug("legacy security=%s\n", chosen_major_lsm ? : " *unspecified*"); 48667a4b6a8SPaul Moore init_debug(" CONFIG_LSM=%s\n", builtin_lsm_order); 48767a4b6a8SPaul Moore init_debug("boot arg lsm=%s\n", chosen_lsm_order ? : " *unspecified*"); 48867a4b6a8SPaul Moore 48967a4b6a8SPaul Moore /* 49067a4b6a8SPaul Moore * Append the names of the early LSM modules now that kmalloc() is 49167a4b6a8SPaul Moore * available 49267a4b6a8SPaul Moore */ 49337f788f6SPaul Moore lsm_early_for_each_raw(lsm) { 49467a4b6a8SPaul Moore init_debug(" early started: %s (%s)\n", lsm->name, 49567a4b6a8SPaul Moore is_enabled(lsm) ? "enabled" : "disabled"); 49667a4b6a8SPaul Moore if (lsm->enabled) 49767a4b6a8SPaul Moore lsm_append(lsm->name, &lsm_names); 49867a4b6a8SPaul Moore } 49967a4b6a8SPaul Moore 50067a4b6a8SPaul Moore /* Load LSMs in specified order. */ 501*faabedcdSPaul Moore lsm_init_ordered(); 50267a4b6a8SPaul Moore 50367a4b6a8SPaul Moore return 0; 50467a4b6a8SPaul Moore } 505