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 3567a4b6a8SPaul Moore static int lsm_append(const char *new, char **result); 3667a4b6a8SPaul Moore 3767a4b6a8SPaul Moore /* Save user chosen LSM */ 3867a4b6a8SPaul Moore static int __init choose_major_lsm(char *str) 3967a4b6a8SPaul Moore { 4067a4b6a8SPaul Moore chosen_major_lsm = str; 4167a4b6a8SPaul Moore return 1; 4267a4b6a8SPaul Moore } 4367a4b6a8SPaul Moore __setup("security=", choose_major_lsm); 4467a4b6a8SPaul Moore 4567a4b6a8SPaul Moore /* Explicitly choose LSM initialization order. */ 4667a4b6a8SPaul Moore static int __init choose_lsm_order(char *str) 4767a4b6a8SPaul Moore { 4867a4b6a8SPaul Moore chosen_lsm_order = str; 4967a4b6a8SPaul Moore return 1; 5067a4b6a8SPaul Moore } 5167a4b6a8SPaul Moore __setup("lsm=", choose_lsm_order); 5267a4b6a8SPaul Moore 5367a4b6a8SPaul Moore /* Enable LSM order debugging. */ 5467a4b6a8SPaul Moore static int __init enable_debug(char *str) 5567a4b6a8SPaul Moore { 5667a4b6a8SPaul Moore debug = true; 5767a4b6a8SPaul Moore return 1; 5867a4b6a8SPaul Moore } 5967a4b6a8SPaul Moore __setup("lsm.debug", enable_debug); 6067a4b6a8SPaul Moore 6167a4b6a8SPaul Moore /* Mark an LSM's enabled flag. */ 6267a4b6a8SPaul Moore static int lsm_enabled_true __initdata = 1; 6367a4b6a8SPaul Moore static int lsm_enabled_false __initdata = 0; 6467a4b6a8SPaul Moore static void __init set_enabled(struct lsm_info *lsm, bool enabled) 6567a4b6a8SPaul Moore { 6667a4b6a8SPaul Moore /* 6767a4b6a8SPaul Moore * When an LSM hasn't configured an enable variable, we can use 6867a4b6a8SPaul Moore * a hard-coded location for storing the default enabled state. 6967a4b6a8SPaul Moore */ 7067a4b6a8SPaul Moore if (!lsm->enabled) { 7167a4b6a8SPaul Moore if (enabled) 7267a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 7367a4b6a8SPaul Moore else 7467a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_false; 7567a4b6a8SPaul Moore } else if (lsm->enabled == &lsm_enabled_true) { 7667a4b6a8SPaul Moore if (!enabled) 7767a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_false; 7867a4b6a8SPaul Moore } else if (lsm->enabled == &lsm_enabled_false) { 7967a4b6a8SPaul Moore if (enabled) 8067a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 8167a4b6a8SPaul Moore } else { 8267a4b6a8SPaul Moore *lsm->enabled = enabled; 8367a4b6a8SPaul Moore } 8467a4b6a8SPaul Moore } 8567a4b6a8SPaul Moore 8667a4b6a8SPaul Moore static inline bool is_enabled(struct lsm_info *lsm) 8767a4b6a8SPaul Moore { 8867a4b6a8SPaul Moore if (!lsm->enabled) 8967a4b6a8SPaul Moore return false; 9067a4b6a8SPaul Moore 9167a4b6a8SPaul Moore return *lsm->enabled; 9267a4b6a8SPaul Moore } 9367a4b6a8SPaul Moore 9467a4b6a8SPaul Moore /* Is an LSM already listed in the ordered LSMs list? */ 9567a4b6a8SPaul Moore static bool __init exists_ordered_lsm(struct lsm_info *lsm) 9667a4b6a8SPaul Moore { 9767a4b6a8SPaul Moore struct lsm_info **check; 9867a4b6a8SPaul Moore 9967a4b6a8SPaul Moore for (check = ordered_lsms; *check; check++) 10067a4b6a8SPaul Moore if (*check == lsm) 10167a4b6a8SPaul Moore return true; 10267a4b6a8SPaul Moore 10367a4b6a8SPaul Moore return false; 10467a4b6a8SPaul Moore } 10567a4b6a8SPaul Moore 10667a4b6a8SPaul Moore /* Append an LSM to the list of ordered LSMs to initialize. */ 10767a4b6a8SPaul Moore static int last_lsm __initdata; 10867a4b6a8SPaul Moore static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from) 10967a4b6a8SPaul Moore { 11067a4b6a8SPaul Moore /* Ignore duplicate selections. */ 11167a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 11267a4b6a8SPaul Moore return; 11367a4b6a8SPaul Moore 11467a4b6a8SPaul Moore if (WARN(last_lsm == MAX_LSM_COUNT, "%s: out of LSM static calls!?\n", from)) 11567a4b6a8SPaul Moore return; 11667a4b6a8SPaul Moore 11767a4b6a8SPaul Moore /* Enable this LSM, if it is not already set. */ 11867a4b6a8SPaul Moore if (!lsm->enabled) 11967a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 12067a4b6a8SPaul Moore ordered_lsms[last_lsm++] = lsm; 12167a4b6a8SPaul Moore 12267a4b6a8SPaul Moore init_debug("%s ordered: %s (%s)\n", from, lsm->name, 12367a4b6a8SPaul Moore is_enabled(lsm) ? "enabled" : "disabled"); 12467a4b6a8SPaul Moore } 12567a4b6a8SPaul Moore 12667a4b6a8SPaul Moore static void __init lsm_set_blob_size(int *need, int *lbs) 12767a4b6a8SPaul Moore { 12867a4b6a8SPaul Moore int offset; 12967a4b6a8SPaul Moore 13067a4b6a8SPaul Moore if (*need <= 0) 13167a4b6a8SPaul Moore return; 13267a4b6a8SPaul Moore 13367a4b6a8SPaul Moore offset = ALIGN(*lbs, sizeof(void *)); 13467a4b6a8SPaul Moore *lbs = offset + *need; 13567a4b6a8SPaul Moore *need = offset; 13667a4b6a8SPaul Moore } 13767a4b6a8SPaul Moore 138*e0257856SPaul Moore /** 139*e0257856SPaul Moore * lsm_prepare - Prepare the LSM framework for a new LSM 140*e0257856SPaul Moore * @lsm: LSM definition 14167a4b6a8SPaul Moore */ 142*e0257856SPaul Moore static void __init lsm_prepare(struct lsm_info *lsm) 14367a4b6a8SPaul Moore { 144*e0257856SPaul Moore struct lsm_blob_sizes *blobs; 14567a4b6a8SPaul Moore 146*e0257856SPaul Moore if (!is_enabled(lsm)) { 147*e0257856SPaul Moore set_enabled(lsm, false); 148*e0257856SPaul Moore return; 149*e0257856SPaul Moore } else if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) { 150*e0257856SPaul Moore init_debug("exclusive disabled: %s\n", lsm->name); 151*e0257856SPaul Moore set_enabled(lsm, false); 152*e0257856SPaul Moore return; 153*e0257856SPaul Moore } 15467a4b6a8SPaul Moore 155*e0257856SPaul Moore /* Mark the LSM as enabled. */ 156*e0257856SPaul Moore set_enabled(lsm, true); 15767a4b6a8SPaul Moore if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) { 15867a4b6a8SPaul Moore init_debug("exclusive chosen: %s\n", lsm->name); 159*e0257856SPaul Moore exclusive = lsm; 16067a4b6a8SPaul Moore } 16167a4b6a8SPaul Moore 162*e0257856SPaul Moore /* Register the LSM blob sizes. */ 163*e0257856SPaul Moore blobs = lsm->blobs; 164*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_cred, &blob_sizes.lbs_cred); 165*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_file, &blob_sizes.lbs_file); 166*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_ib, &blob_sizes.lbs_ib); 167*e0257856SPaul Moore /* inode blob gets an rcu_head in addition to LSM blobs. */ 168*e0257856SPaul Moore if (blobs->lbs_inode && blob_sizes.lbs_inode == 0) 169*e0257856SPaul Moore blob_sizes.lbs_inode = sizeof(struct rcu_head); 170*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_inode, &blob_sizes.lbs_inode); 171*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_ipc, &blob_sizes.lbs_ipc); 172*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_key, &blob_sizes.lbs_key); 173*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg); 174*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_perf_event, &blob_sizes.lbs_perf_event); 175*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_sock, &blob_sizes.lbs_sock); 176*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_superblock, &blob_sizes.lbs_superblock); 177*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_task, &blob_sizes.lbs_task); 178*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev); 179*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_xattr_count, 180*e0257856SPaul Moore &blob_sizes.lbs_xattr_count); 181*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bdev, &blob_sizes.lbs_bdev); 182*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_map, &blob_sizes.lbs_bpf_map); 183*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog); 184*e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token); 18567a4b6a8SPaul Moore } 18667a4b6a8SPaul Moore 18767a4b6a8SPaul Moore /* Initialize a given LSM, if it is enabled. */ 18867a4b6a8SPaul Moore static void __init initialize_lsm(struct lsm_info *lsm) 18967a4b6a8SPaul Moore { 19067a4b6a8SPaul Moore if (is_enabled(lsm)) { 19167a4b6a8SPaul Moore int ret; 19267a4b6a8SPaul Moore 19367a4b6a8SPaul Moore init_debug("initializing %s\n", lsm->name); 19467a4b6a8SPaul Moore ret = lsm->init(); 19567a4b6a8SPaul Moore WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); 19667a4b6a8SPaul Moore } 19767a4b6a8SPaul Moore } 19867a4b6a8SPaul Moore 19967a4b6a8SPaul Moore /* 20067a4b6a8SPaul Moore * Current index to use while initializing the lsm id list. 20167a4b6a8SPaul Moore */ 20267a4b6a8SPaul Moore u32 lsm_active_cnt __ro_after_init; 20367a4b6a8SPaul Moore const struct lsm_id *lsm_idlist[MAX_LSM_COUNT]; 20467a4b6a8SPaul Moore 20567a4b6a8SPaul Moore /* Populate ordered LSMs list from comma-separated LSM name list. */ 20667a4b6a8SPaul Moore static void __init ordered_lsm_parse(const char *order, const char *origin) 20767a4b6a8SPaul Moore { 20867a4b6a8SPaul Moore struct lsm_info *lsm; 20967a4b6a8SPaul Moore char *sep, *name, *next; 21067a4b6a8SPaul Moore 21167a4b6a8SPaul Moore /* LSM_ORDER_FIRST is always first. */ 21267a4b6a8SPaul Moore for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 21367a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_FIRST) 21467a4b6a8SPaul Moore append_ordered_lsm(lsm, " first"); 21567a4b6a8SPaul Moore } 21667a4b6a8SPaul Moore 21767a4b6a8SPaul Moore /* Process "security=", if given. */ 21867a4b6a8SPaul Moore if (chosen_major_lsm) { 21967a4b6a8SPaul Moore struct lsm_info *major; 22067a4b6a8SPaul Moore 22167a4b6a8SPaul Moore /* 22267a4b6a8SPaul Moore * To match the original "security=" behavior, this 22367a4b6a8SPaul Moore * explicitly does NOT fallback to another Legacy Major 22467a4b6a8SPaul Moore * if the selected one was separately disabled: disable 22567a4b6a8SPaul Moore * all non-matching Legacy Major LSMs. 22667a4b6a8SPaul Moore */ 22767a4b6a8SPaul Moore for (major = __start_lsm_info; major < __end_lsm_info; 22867a4b6a8SPaul Moore major++) { 22967a4b6a8SPaul Moore if ((major->flags & LSM_FLAG_LEGACY_MAJOR) && 23067a4b6a8SPaul Moore strcmp(major->name, chosen_major_lsm) != 0) { 23167a4b6a8SPaul Moore set_enabled(major, false); 23267a4b6a8SPaul Moore init_debug("security=%s disabled: %s (only one legacy major LSM)\n", 23367a4b6a8SPaul Moore chosen_major_lsm, major->name); 23467a4b6a8SPaul Moore } 23567a4b6a8SPaul Moore } 23667a4b6a8SPaul Moore } 23767a4b6a8SPaul Moore 23867a4b6a8SPaul Moore sep = kstrdup(order, GFP_KERNEL); 23967a4b6a8SPaul Moore next = sep; 24067a4b6a8SPaul Moore /* Walk the list, looking for matching LSMs. */ 24167a4b6a8SPaul Moore while ((name = strsep(&next, ",")) != NULL) { 24267a4b6a8SPaul Moore bool found = false; 24367a4b6a8SPaul Moore 24467a4b6a8SPaul Moore for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 24567a4b6a8SPaul Moore if (strcmp(lsm->name, name) == 0) { 24667a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_MUTABLE) 24767a4b6a8SPaul Moore append_ordered_lsm(lsm, origin); 24867a4b6a8SPaul Moore found = true; 24967a4b6a8SPaul Moore } 25067a4b6a8SPaul Moore } 25167a4b6a8SPaul Moore 25267a4b6a8SPaul Moore if (!found) 25367a4b6a8SPaul Moore init_debug("%s ignored: %s (not built into kernel)\n", 25467a4b6a8SPaul Moore origin, name); 25567a4b6a8SPaul Moore } 25667a4b6a8SPaul Moore 25767a4b6a8SPaul Moore /* Process "security=", if given. */ 25867a4b6a8SPaul Moore if (chosen_major_lsm) { 25967a4b6a8SPaul Moore for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 26067a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 26167a4b6a8SPaul Moore continue; 26267a4b6a8SPaul Moore if (strcmp(lsm->name, chosen_major_lsm) == 0) 26367a4b6a8SPaul Moore append_ordered_lsm(lsm, "security="); 26467a4b6a8SPaul Moore } 26567a4b6a8SPaul Moore } 26667a4b6a8SPaul Moore 26767a4b6a8SPaul Moore /* LSM_ORDER_LAST is always last. */ 26867a4b6a8SPaul Moore for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 26967a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_LAST) 27067a4b6a8SPaul Moore append_ordered_lsm(lsm, " last"); 27167a4b6a8SPaul Moore } 27267a4b6a8SPaul Moore 27367a4b6a8SPaul Moore /* Disable all LSMs not in the ordered list. */ 27467a4b6a8SPaul Moore for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { 27567a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 27667a4b6a8SPaul Moore continue; 27767a4b6a8SPaul Moore set_enabled(lsm, false); 27867a4b6a8SPaul Moore init_debug("%s skipped: %s (not in requested order)\n", 27967a4b6a8SPaul Moore origin, lsm->name); 28067a4b6a8SPaul Moore } 28167a4b6a8SPaul Moore 28267a4b6a8SPaul Moore kfree(sep); 28367a4b6a8SPaul Moore } 28467a4b6a8SPaul Moore 28567a4b6a8SPaul Moore static void __init report_lsm_order(void) 28667a4b6a8SPaul Moore { 28767a4b6a8SPaul Moore struct lsm_info **lsm, *early; 28867a4b6a8SPaul Moore int first = 0; 28967a4b6a8SPaul Moore 29067a4b6a8SPaul Moore pr_info("initializing lsm="); 29167a4b6a8SPaul Moore 29267a4b6a8SPaul Moore /* Report each enabled LSM name, comma separated. */ 29367a4b6a8SPaul Moore for (early = __start_early_lsm_info; 29467a4b6a8SPaul Moore early < __end_early_lsm_info; early++) 29567a4b6a8SPaul Moore if (is_enabled(early)) 29667a4b6a8SPaul Moore pr_cont("%s%s", first++ == 0 ? "" : ",", early->name); 29767a4b6a8SPaul Moore for (lsm = ordered_lsms; *lsm; lsm++) 29867a4b6a8SPaul Moore if (is_enabled(*lsm)) 29967a4b6a8SPaul Moore pr_cont("%s%s", first++ == 0 ? "" : ",", (*lsm)->name); 30067a4b6a8SPaul Moore 30167a4b6a8SPaul Moore pr_cont("\n"); 30267a4b6a8SPaul Moore } 30367a4b6a8SPaul Moore 30467a4b6a8SPaul Moore /** 30567a4b6a8SPaul Moore * lsm_early_cred - during initialization allocate a composite cred blob 30667a4b6a8SPaul Moore * @cred: the cred that needs a blob 30767a4b6a8SPaul Moore * 30867a4b6a8SPaul Moore * Allocate the cred blob for all the modules 30967a4b6a8SPaul Moore */ 31067a4b6a8SPaul Moore static void __init lsm_early_cred(struct cred *cred) 31167a4b6a8SPaul Moore { 31267a4b6a8SPaul Moore int rc = lsm_cred_alloc(cred, GFP_KERNEL); 31367a4b6a8SPaul Moore 31467a4b6a8SPaul Moore if (rc) 31567a4b6a8SPaul Moore panic("%s: Early cred alloc failed.\n", __func__); 31667a4b6a8SPaul Moore } 31767a4b6a8SPaul Moore 31867a4b6a8SPaul Moore /** 31967a4b6a8SPaul Moore * lsm_early_task - during initialization allocate a composite task blob 32067a4b6a8SPaul Moore * @task: the task that needs a blob 32167a4b6a8SPaul Moore * 32267a4b6a8SPaul Moore * Allocate the task blob for all the modules 32367a4b6a8SPaul Moore */ 32467a4b6a8SPaul Moore static void __init lsm_early_task(struct task_struct *task) 32567a4b6a8SPaul Moore { 32667a4b6a8SPaul Moore int rc = lsm_task_alloc(task); 32767a4b6a8SPaul Moore 32867a4b6a8SPaul Moore if (rc) 32967a4b6a8SPaul Moore panic("%s: Early task alloc failed.\n", __func__); 33067a4b6a8SPaul Moore } 33167a4b6a8SPaul Moore 33267a4b6a8SPaul Moore static void __init ordered_lsm_init(void) 33367a4b6a8SPaul Moore { 33467a4b6a8SPaul Moore struct lsm_info **lsm; 33567a4b6a8SPaul Moore 33667a4b6a8SPaul Moore if (chosen_lsm_order) { 33767a4b6a8SPaul Moore if (chosen_major_lsm) { 33867a4b6a8SPaul Moore pr_warn("security=%s is ignored because it is superseded by lsm=%s\n", 33967a4b6a8SPaul Moore chosen_major_lsm, chosen_lsm_order); 34067a4b6a8SPaul Moore chosen_major_lsm = NULL; 34167a4b6a8SPaul Moore } 34267a4b6a8SPaul Moore ordered_lsm_parse(chosen_lsm_order, "cmdline"); 34367a4b6a8SPaul Moore } else 34467a4b6a8SPaul Moore ordered_lsm_parse(builtin_lsm_order, "builtin"); 34567a4b6a8SPaul Moore 34667a4b6a8SPaul Moore for (lsm = ordered_lsms; *lsm; lsm++) 347*e0257856SPaul Moore lsm_prepare(*lsm); 34867a4b6a8SPaul Moore 34967a4b6a8SPaul Moore report_lsm_order(); 35067a4b6a8SPaul Moore 35167a4b6a8SPaul Moore init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); 35267a4b6a8SPaul Moore init_debug("file blob size = %d\n", blob_sizes.lbs_file); 35367a4b6a8SPaul Moore init_debug("ib blob size = %d\n", blob_sizes.lbs_ib); 35467a4b6a8SPaul Moore init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); 35567a4b6a8SPaul Moore init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); 35667a4b6a8SPaul Moore #ifdef CONFIG_KEYS 35767a4b6a8SPaul Moore init_debug("key blob size = %d\n", blob_sizes.lbs_key); 35867a4b6a8SPaul Moore #endif /* CONFIG_KEYS */ 35967a4b6a8SPaul Moore init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); 36067a4b6a8SPaul Moore init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); 36167a4b6a8SPaul Moore init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock); 36267a4b6a8SPaul Moore init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event); 36367a4b6a8SPaul Moore init_debug("task blob size = %d\n", blob_sizes.lbs_task); 36467a4b6a8SPaul Moore init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev); 36567a4b6a8SPaul Moore init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count); 36667a4b6a8SPaul Moore init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); 36767a4b6a8SPaul Moore init_debug("bpf map blob size = %d\n", blob_sizes.lbs_bpf_map); 36867a4b6a8SPaul Moore init_debug("bpf prog blob size = %d\n", blob_sizes.lbs_bpf_prog); 36967a4b6a8SPaul Moore init_debug("bpf token blob size = %d\n", blob_sizes.lbs_bpf_token); 37067a4b6a8SPaul Moore 37167a4b6a8SPaul Moore /* 37267a4b6a8SPaul Moore * Create any kmem_caches needed for blobs 37367a4b6a8SPaul Moore */ 37467a4b6a8SPaul Moore if (blob_sizes.lbs_file) 37567a4b6a8SPaul Moore lsm_file_cache = kmem_cache_create("lsm_file_cache", 37667a4b6a8SPaul Moore blob_sizes.lbs_file, 0, 37767a4b6a8SPaul Moore SLAB_PANIC, NULL); 37867a4b6a8SPaul Moore if (blob_sizes.lbs_inode) 37967a4b6a8SPaul Moore lsm_inode_cache = kmem_cache_create("lsm_inode_cache", 38067a4b6a8SPaul Moore blob_sizes.lbs_inode, 0, 38167a4b6a8SPaul Moore SLAB_PANIC, NULL); 38267a4b6a8SPaul Moore 38367a4b6a8SPaul Moore lsm_early_cred((struct cred *) current->cred); 38467a4b6a8SPaul Moore lsm_early_task(current); 38567a4b6a8SPaul Moore for (lsm = ordered_lsms; *lsm; lsm++) 38667a4b6a8SPaul Moore initialize_lsm(*lsm); 38767a4b6a8SPaul Moore } 38867a4b6a8SPaul Moore 38967a4b6a8SPaul Moore static bool match_last_lsm(const char *list, const char *lsm) 39067a4b6a8SPaul Moore { 39167a4b6a8SPaul Moore const char *last; 39267a4b6a8SPaul Moore 39367a4b6a8SPaul Moore if (WARN_ON(!list || !lsm)) 39467a4b6a8SPaul Moore return false; 39567a4b6a8SPaul Moore last = strrchr(list, ','); 39667a4b6a8SPaul Moore if (last) 39767a4b6a8SPaul Moore /* Pass the comma, strcmp() will check for '\0' */ 39867a4b6a8SPaul Moore last++; 39967a4b6a8SPaul Moore else 40067a4b6a8SPaul Moore last = list; 40167a4b6a8SPaul Moore return !strcmp(last, lsm); 40267a4b6a8SPaul Moore } 40367a4b6a8SPaul Moore 40467a4b6a8SPaul Moore static int lsm_append(const char *new, char **result) 40567a4b6a8SPaul Moore { 40667a4b6a8SPaul Moore char *cp; 40767a4b6a8SPaul Moore 40867a4b6a8SPaul Moore if (*result == NULL) { 40967a4b6a8SPaul Moore *result = kstrdup(new, GFP_KERNEL); 41067a4b6a8SPaul Moore if (*result == NULL) 41167a4b6a8SPaul Moore return -ENOMEM; 41267a4b6a8SPaul Moore } else { 41367a4b6a8SPaul Moore /* Check if it is the last registered name */ 41467a4b6a8SPaul Moore if (match_last_lsm(*result, new)) 41567a4b6a8SPaul Moore return 0; 41667a4b6a8SPaul Moore cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new); 41767a4b6a8SPaul Moore if (cp == NULL) 41867a4b6a8SPaul Moore return -ENOMEM; 41967a4b6a8SPaul Moore kfree(*result); 42067a4b6a8SPaul Moore *result = cp; 42167a4b6a8SPaul Moore } 42267a4b6a8SPaul Moore return 0; 42367a4b6a8SPaul Moore } 42467a4b6a8SPaul Moore 42567a4b6a8SPaul Moore static void __init lsm_static_call_init(struct security_hook_list *hl) 42667a4b6a8SPaul Moore { 42767a4b6a8SPaul Moore struct lsm_static_call *scall = hl->scalls; 42867a4b6a8SPaul Moore int i; 42967a4b6a8SPaul Moore 43067a4b6a8SPaul Moore for (i = 0; i < MAX_LSM_COUNT; i++) { 43167a4b6a8SPaul Moore /* Update the first static call that is not used yet */ 43267a4b6a8SPaul Moore if (!scall->hl) { 43367a4b6a8SPaul Moore __static_call_update(scall->key, scall->trampoline, 43467a4b6a8SPaul Moore hl->hook.lsm_func_addr); 43567a4b6a8SPaul Moore scall->hl = hl; 43667a4b6a8SPaul Moore static_branch_enable(scall->active); 43767a4b6a8SPaul Moore return; 43867a4b6a8SPaul Moore } 43967a4b6a8SPaul Moore scall++; 44067a4b6a8SPaul Moore } 44167a4b6a8SPaul Moore panic("%s - Ran out of static slots.\n", __func__); 44267a4b6a8SPaul Moore } 44367a4b6a8SPaul Moore 44467a4b6a8SPaul Moore /** 44567a4b6a8SPaul Moore * security_add_hooks - Add a modules hooks to the hook lists. 44667a4b6a8SPaul Moore * @hooks: the hooks to add 44767a4b6a8SPaul Moore * @count: the number of hooks to add 44867a4b6a8SPaul Moore * @lsmid: the identification information for the security module 44967a4b6a8SPaul Moore * 45067a4b6a8SPaul Moore * Each LSM has to register its hooks with the infrastructure. 45167a4b6a8SPaul Moore */ 45267a4b6a8SPaul Moore void __init security_add_hooks(struct security_hook_list *hooks, int count, 45367a4b6a8SPaul Moore const struct lsm_id *lsmid) 45467a4b6a8SPaul Moore { 45567a4b6a8SPaul Moore int i; 45667a4b6a8SPaul Moore 45767a4b6a8SPaul Moore /* 45867a4b6a8SPaul Moore * A security module may call security_add_hooks() more 45967a4b6a8SPaul Moore * than once during initialization, and LSM initialization 46067a4b6a8SPaul Moore * is serialized. Landlock is one such case. 46167a4b6a8SPaul Moore * Look at the previous entry, if there is one, for duplication. 46267a4b6a8SPaul Moore */ 46367a4b6a8SPaul Moore if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid) { 46467a4b6a8SPaul Moore if (lsm_active_cnt >= MAX_LSM_COUNT) 46567a4b6a8SPaul Moore panic("%s Too many LSMs registered.\n", __func__); 46667a4b6a8SPaul Moore lsm_idlist[lsm_active_cnt++] = lsmid; 46767a4b6a8SPaul Moore } 46867a4b6a8SPaul Moore 46967a4b6a8SPaul Moore for (i = 0; i < count; i++) { 47067a4b6a8SPaul Moore hooks[i].lsmid = lsmid; 47167a4b6a8SPaul Moore lsm_static_call_init(&hooks[i]); 47267a4b6a8SPaul Moore } 47367a4b6a8SPaul Moore 47467a4b6a8SPaul Moore /* 47567a4b6a8SPaul Moore * Don't try to append during early_security_init(), we'll come back 47667a4b6a8SPaul Moore * and fix this up afterwards. 47767a4b6a8SPaul Moore */ 47867a4b6a8SPaul Moore if (slab_is_available()) { 47967a4b6a8SPaul Moore if (lsm_append(lsmid->name, &lsm_names) < 0) 48067a4b6a8SPaul Moore panic("%s - Cannot get early memory.\n", __func__); 48167a4b6a8SPaul Moore } 48267a4b6a8SPaul Moore } 48367a4b6a8SPaul Moore 48467a4b6a8SPaul Moore int __init early_security_init(void) 48567a4b6a8SPaul Moore { 48667a4b6a8SPaul Moore struct lsm_info *lsm; 48767a4b6a8SPaul Moore 48867a4b6a8SPaul Moore for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) { 48967a4b6a8SPaul Moore if (!lsm->enabled) 49067a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 491*e0257856SPaul Moore lsm_prepare(lsm); 49267a4b6a8SPaul Moore initialize_lsm(lsm); 49367a4b6a8SPaul Moore } 49467a4b6a8SPaul Moore 49567a4b6a8SPaul Moore return 0; 49667a4b6a8SPaul Moore } 49767a4b6a8SPaul Moore 49867a4b6a8SPaul Moore /** 49967a4b6a8SPaul Moore * security_init - initializes the security framework 50067a4b6a8SPaul Moore * 50167a4b6a8SPaul Moore * This should be called early in the kernel initialization sequence. 50267a4b6a8SPaul Moore */ 50367a4b6a8SPaul Moore int __init security_init(void) 50467a4b6a8SPaul Moore { 50567a4b6a8SPaul Moore struct lsm_info *lsm; 50667a4b6a8SPaul Moore 50767a4b6a8SPaul Moore init_debug("legacy security=%s\n", chosen_major_lsm ? : " *unspecified*"); 50867a4b6a8SPaul Moore init_debug(" CONFIG_LSM=%s\n", builtin_lsm_order); 50967a4b6a8SPaul Moore init_debug("boot arg lsm=%s\n", chosen_lsm_order ? : " *unspecified*"); 51067a4b6a8SPaul Moore 51167a4b6a8SPaul Moore /* 51267a4b6a8SPaul Moore * Append the names of the early LSM modules now that kmalloc() is 51367a4b6a8SPaul Moore * available 51467a4b6a8SPaul Moore */ 51567a4b6a8SPaul Moore for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) { 51667a4b6a8SPaul Moore init_debug(" early started: %s (%s)\n", lsm->name, 51767a4b6a8SPaul Moore is_enabled(lsm) ? "enabled" : "disabled"); 51867a4b6a8SPaul Moore if (lsm->enabled) 51967a4b6a8SPaul Moore lsm_append(lsm->name, &lsm_names); 52067a4b6a8SPaul Moore } 52167a4b6a8SPaul Moore 52267a4b6a8SPaul Moore /* Load LSMs in specified order. */ 52367a4b6a8SPaul Moore ordered_lsm_init(); 52467a4b6a8SPaul Moore 52567a4b6a8SPaul Moore return 0; 52667a4b6a8SPaul Moore } 527