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 19*592b104fSPaul Moore /* Build and boot-time LSM ordering. */ 20*592b104fSPaul Moore static __initconst const char *const lsm_order_builtin = CONFIG_LSM; 21*592b104fSPaul Moore static __initdata const char *lsm_order_cmdline; 22*592b104fSPaul Moore static __initdata const char *lsm_order_legacy; 2367a4b6a8SPaul Moore 2467a4b6a8SPaul Moore /* Ordered list of LSMs to initialize. */ 25*592b104fSPaul Moore static __initdata struct lsm_info *lsm_order[MAX_LSM_COUNT + 1]; 26*592b104fSPaul Moore static __initdata struct lsm_info *lsm_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) \ 36*592b104fSPaul Moore for ((iter) = lsm_order; *(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 44*592b104fSPaul Moore /** 45*592b104fSPaul Moore * lsm_choose_security - Legacy "major" LSM selection 46*592b104fSPaul Moore * @str: kernel command line parameter 47*592b104fSPaul Moore */ 48*592b104fSPaul Moore static int __init lsm_choose_security(char *str) 4967a4b6a8SPaul Moore { 50*592b104fSPaul Moore lsm_order_legacy = str; 5167a4b6a8SPaul Moore return 1; 5267a4b6a8SPaul Moore } 53*592b104fSPaul Moore __setup("security=", lsm_choose_security); 5467a4b6a8SPaul Moore 55*592b104fSPaul Moore /** 56*592b104fSPaul Moore * lsm_choose_lsm - Modern LSM selection 57*592b104fSPaul Moore * @str: kernel command line parameter 58*592b104fSPaul Moore */ 59*592b104fSPaul Moore static int __init lsm_choose_lsm(char *str) 6067a4b6a8SPaul Moore { 61*592b104fSPaul Moore lsm_order_cmdline = str; 6267a4b6a8SPaul Moore return 1; 6367a4b6a8SPaul Moore } 64*592b104fSPaul Moore __setup("lsm=", lsm_choose_lsm); 6567a4b6a8SPaul Moore 66*592b104fSPaul Moore /** 67*592b104fSPaul Moore * lsm_debug_enable - Enable LSM framework debugging 68*592b104fSPaul Moore * @str: kernel command line parameter 69*592b104fSPaul Moore * 70*592b104fSPaul Moore * Currently we only provide debug info during LSM initialization, but we may 71*592b104fSPaul Moore * want to expand this in the future. 72*592b104fSPaul Moore */ 73*592b104fSPaul Moore static int __init lsm_debug_enable(char *str) 7467a4b6a8SPaul Moore { 7567a4b6a8SPaul Moore debug = true; 7667a4b6a8SPaul Moore return 1; 7767a4b6a8SPaul Moore } 78*592b104fSPaul Moore __setup("lsm.debug", lsm_debug_enable); 7967a4b6a8SPaul Moore 8067a4b6a8SPaul Moore /* Mark an LSM's enabled flag. */ 8167a4b6a8SPaul Moore static int lsm_enabled_true __initdata = 1; 8267a4b6a8SPaul Moore static int lsm_enabled_false __initdata = 0; 8367a4b6a8SPaul Moore static void __init set_enabled(struct lsm_info *lsm, bool enabled) 8467a4b6a8SPaul Moore { 8567a4b6a8SPaul Moore /* 8667a4b6a8SPaul Moore * When an LSM hasn't configured an enable variable, we can use 8767a4b6a8SPaul Moore * a hard-coded location for storing the default enabled state. 8867a4b6a8SPaul Moore */ 8967a4b6a8SPaul Moore if (!lsm->enabled) { 9067a4b6a8SPaul Moore if (enabled) 9167a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 9267a4b6a8SPaul Moore else 9367a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_false; 9467a4b6a8SPaul Moore } else if (lsm->enabled == &lsm_enabled_true) { 9567a4b6a8SPaul Moore if (!enabled) 9667a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_false; 9767a4b6a8SPaul Moore } else if (lsm->enabled == &lsm_enabled_false) { 9867a4b6a8SPaul Moore if (enabled) 9967a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 10067a4b6a8SPaul Moore } else { 10167a4b6a8SPaul Moore *lsm->enabled = enabled; 10267a4b6a8SPaul Moore } 10367a4b6a8SPaul Moore } 10467a4b6a8SPaul Moore 10567a4b6a8SPaul Moore static inline bool is_enabled(struct lsm_info *lsm) 10667a4b6a8SPaul Moore { 10767a4b6a8SPaul Moore if (!lsm->enabled) 10867a4b6a8SPaul Moore return false; 10967a4b6a8SPaul Moore 11067a4b6a8SPaul Moore return *lsm->enabled; 11167a4b6a8SPaul Moore } 11267a4b6a8SPaul Moore 11367a4b6a8SPaul Moore /* Is an LSM already listed in the ordered LSMs list? */ 11467a4b6a8SPaul Moore static bool __init exists_ordered_lsm(struct lsm_info *lsm) 11567a4b6a8SPaul Moore { 11667a4b6a8SPaul Moore struct lsm_info **check; 11767a4b6a8SPaul Moore 11837f788f6SPaul Moore lsm_order_for_each(check) { 11967a4b6a8SPaul Moore if (*check == lsm) 12067a4b6a8SPaul Moore return true; 12137f788f6SPaul Moore } 12267a4b6a8SPaul Moore 12367a4b6a8SPaul Moore return false; 12467a4b6a8SPaul Moore } 12567a4b6a8SPaul Moore 12667a4b6a8SPaul Moore /* Append an LSM to the list of ordered LSMs to initialize. */ 12767a4b6a8SPaul Moore static int last_lsm __initdata; 12867a4b6a8SPaul Moore static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from) 12967a4b6a8SPaul Moore { 13067a4b6a8SPaul Moore /* Ignore duplicate selections. */ 13167a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 13267a4b6a8SPaul Moore return; 13367a4b6a8SPaul Moore 13467a4b6a8SPaul Moore if (WARN(last_lsm == MAX_LSM_COUNT, "%s: out of LSM static calls!?\n", from)) 13567a4b6a8SPaul Moore return; 13667a4b6a8SPaul Moore 13767a4b6a8SPaul Moore /* Enable this LSM, if it is not already set. */ 13867a4b6a8SPaul Moore if (!lsm->enabled) 13967a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 140*592b104fSPaul Moore lsm_order[last_lsm] = lsm; 1419f9dc69eSPaul Moore lsm_idlist[last_lsm++] = lsm->id; 14267a4b6a8SPaul Moore 1439f9dc69eSPaul Moore init_debug("%s ordered: %s (%s)\n", from, lsm->id->name, 14467a4b6a8SPaul Moore is_enabled(lsm) ? "enabled" : "disabled"); 14567a4b6a8SPaul Moore } 14667a4b6a8SPaul Moore 14767a4b6a8SPaul Moore static void __init lsm_set_blob_size(int *need, int *lbs) 14867a4b6a8SPaul Moore { 14967a4b6a8SPaul Moore int offset; 15067a4b6a8SPaul Moore 15167a4b6a8SPaul Moore if (*need <= 0) 15267a4b6a8SPaul Moore return; 15367a4b6a8SPaul Moore 15467a4b6a8SPaul Moore offset = ALIGN(*lbs, sizeof(void *)); 15567a4b6a8SPaul Moore *lbs = offset + *need; 15667a4b6a8SPaul Moore *need = offset; 15767a4b6a8SPaul Moore } 15867a4b6a8SPaul Moore 159e0257856SPaul Moore /** 160e0257856SPaul Moore * lsm_prepare - Prepare the LSM framework for a new LSM 161e0257856SPaul Moore * @lsm: LSM definition 16267a4b6a8SPaul Moore */ 163e0257856SPaul Moore static void __init lsm_prepare(struct lsm_info *lsm) 16467a4b6a8SPaul Moore { 165e0257856SPaul Moore struct lsm_blob_sizes *blobs; 16667a4b6a8SPaul Moore 167e0257856SPaul Moore if (!is_enabled(lsm)) { 168e0257856SPaul Moore set_enabled(lsm, false); 169e0257856SPaul Moore return; 170*592b104fSPaul Moore } else if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && lsm_exclusive) { 1719f9dc69eSPaul Moore init_debug("exclusive disabled: %s\n", lsm->id->name); 172e0257856SPaul Moore set_enabled(lsm, false); 173e0257856SPaul Moore return; 174e0257856SPaul Moore } 17567a4b6a8SPaul Moore 176e0257856SPaul Moore /* Mark the LSM as enabled. */ 177e0257856SPaul Moore set_enabled(lsm, true); 178*592b104fSPaul Moore if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !lsm_exclusive) { 1799f9dc69eSPaul Moore init_debug("exclusive chosen: %s\n", lsm->id->name); 180*592b104fSPaul Moore lsm_exclusive = lsm; 18167a4b6a8SPaul Moore } 18267a4b6a8SPaul Moore 183e0257856SPaul Moore /* Register the LSM blob sizes. */ 184e0257856SPaul Moore blobs = lsm->blobs; 185e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_cred, &blob_sizes.lbs_cred); 186e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_file, &blob_sizes.lbs_file); 187e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_ib, &blob_sizes.lbs_ib); 188e0257856SPaul Moore /* inode blob gets an rcu_head in addition to LSM blobs. */ 189e0257856SPaul Moore if (blobs->lbs_inode && blob_sizes.lbs_inode == 0) 190e0257856SPaul Moore blob_sizes.lbs_inode = sizeof(struct rcu_head); 191e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_inode, &blob_sizes.lbs_inode); 192e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_ipc, &blob_sizes.lbs_ipc); 193e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_key, &blob_sizes.lbs_key); 194e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg); 195e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_perf_event, &blob_sizes.lbs_perf_event); 196e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_sock, &blob_sizes.lbs_sock); 197e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_superblock, &blob_sizes.lbs_superblock); 198e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_task, &blob_sizes.lbs_task); 199e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev); 200e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_xattr_count, 201e0257856SPaul Moore &blob_sizes.lbs_xattr_count); 202e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bdev, &blob_sizes.lbs_bdev); 203e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_map, &blob_sizes.lbs_bpf_map); 204e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog); 205e0257856SPaul Moore lsm_set_blob_size(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token); 20667a4b6a8SPaul Moore } 20767a4b6a8SPaul Moore 20867a4b6a8SPaul Moore /* Initialize a given LSM, if it is enabled. */ 20967a4b6a8SPaul Moore static void __init initialize_lsm(struct lsm_info *lsm) 21067a4b6a8SPaul Moore { 21167a4b6a8SPaul Moore if (is_enabled(lsm)) { 21267a4b6a8SPaul Moore int ret; 21367a4b6a8SPaul Moore 2149f9dc69eSPaul Moore init_debug("initializing %s\n", lsm->id->name); 21567a4b6a8SPaul Moore ret = lsm->init(); 2169f9dc69eSPaul Moore WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret); 21767a4b6a8SPaul Moore } 21867a4b6a8SPaul Moore } 21967a4b6a8SPaul Moore 22067a4b6a8SPaul Moore /* 22167a4b6a8SPaul Moore * Current index to use while initializing the lsm id list. 22267a4b6a8SPaul Moore */ 22367a4b6a8SPaul Moore u32 lsm_active_cnt __ro_after_init; 22467a4b6a8SPaul Moore const struct lsm_id *lsm_idlist[MAX_LSM_COUNT]; 22567a4b6a8SPaul Moore 22667a4b6a8SPaul Moore /* Populate ordered LSMs list from comma-separated LSM name list. */ 22767a4b6a8SPaul Moore static void __init ordered_lsm_parse(const char *order, const char *origin) 22867a4b6a8SPaul Moore { 22967a4b6a8SPaul Moore struct lsm_info *lsm; 23067a4b6a8SPaul Moore char *sep, *name, *next; 23167a4b6a8SPaul Moore 23267a4b6a8SPaul Moore /* LSM_ORDER_FIRST is always first. */ 23337f788f6SPaul Moore lsm_for_each_raw(lsm) { 23467a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_FIRST) 23567a4b6a8SPaul Moore append_ordered_lsm(lsm, " first"); 23667a4b6a8SPaul Moore } 23767a4b6a8SPaul Moore 23867a4b6a8SPaul Moore /* Process "security=", if given. */ 239*592b104fSPaul Moore if (lsm_order_legacy) { 24067a4b6a8SPaul Moore struct lsm_info *major; 24167a4b6a8SPaul Moore 24267a4b6a8SPaul Moore /* 24367a4b6a8SPaul Moore * To match the original "security=" behavior, this 24467a4b6a8SPaul Moore * explicitly does NOT fallback to another Legacy Major 24567a4b6a8SPaul Moore * if the selected one was separately disabled: disable 24667a4b6a8SPaul Moore * all non-matching Legacy Major LSMs. 24767a4b6a8SPaul Moore */ 24837f788f6SPaul Moore lsm_for_each_raw(major) { 24967a4b6a8SPaul Moore if ((major->flags & LSM_FLAG_LEGACY_MAJOR) && 250*592b104fSPaul Moore strcmp(major->id->name, lsm_order_legacy) != 0) { 25167a4b6a8SPaul Moore set_enabled(major, false); 25267a4b6a8SPaul Moore init_debug("security=%s disabled: %s (only one legacy major LSM)\n", 253*592b104fSPaul Moore lsm_order_legacy, major->id->name); 25467a4b6a8SPaul Moore } 25567a4b6a8SPaul Moore } 25667a4b6a8SPaul Moore } 25767a4b6a8SPaul Moore 25867a4b6a8SPaul Moore sep = kstrdup(order, GFP_KERNEL); 25967a4b6a8SPaul Moore next = sep; 26067a4b6a8SPaul Moore /* Walk the list, looking for matching LSMs. */ 26167a4b6a8SPaul Moore while ((name = strsep(&next, ",")) != NULL) { 26267a4b6a8SPaul Moore bool found = false; 26367a4b6a8SPaul Moore 26437f788f6SPaul Moore lsm_for_each_raw(lsm) { 2659f9dc69eSPaul Moore if (strcmp(lsm->id->name, name) == 0) { 26667a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_MUTABLE) 26767a4b6a8SPaul Moore append_ordered_lsm(lsm, origin); 26867a4b6a8SPaul Moore found = true; 26967a4b6a8SPaul Moore } 27067a4b6a8SPaul Moore } 27167a4b6a8SPaul Moore 27267a4b6a8SPaul Moore if (!found) 27367a4b6a8SPaul Moore init_debug("%s ignored: %s (not built into kernel)\n", 27467a4b6a8SPaul Moore origin, name); 27567a4b6a8SPaul Moore } 27667a4b6a8SPaul Moore 27767a4b6a8SPaul Moore /* Process "security=", if given. */ 278*592b104fSPaul Moore if (lsm_order_legacy) { 27937f788f6SPaul Moore lsm_for_each_raw(lsm) { 28067a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 28167a4b6a8SPaul Moore continue; 282*592b104fSPaul Moore if (strcmp(lsm->id->name, lsm_order_legacy) == 0) 28367a4b6a8SPaul Moore append_ordered_lsm(lsm, "security="); 28467a4b6a8SPaul Moore } 28567a4b6a8SPaul Moore } 28667a4b6a8SPaul Moore 28767a4b6a8SPaul Moore /* LSM_ORDER_LAST is always last. */ 28837f788f6SPaul Moore lsm_for_each_raw(lsm) { 28967a4b6a8SPaul Moore if (lsm->order == LSM_ORDER_LAST) 29067a4b6a8SPaul Moore append_ordered_lsm(lsm, " last"); 29167a4b6a8SPaul Moore } 29267a4b6a8SPaul Moore 29367a4b6a8SPaul Moore /* Disable all LSMs not in the ordered list. */ 29437f788f6SPaul Moore lsm_for_each_raw(lsm) { 29567a4b6a8SPaul Moore if (exists_ordered_lsm(lsm)) 29667a4b6a8SPaul Moore continue; 29767a4b6a8SPaul Moore set_enabled(lsm, false); 29867a4b6a8SPaul Moore init_debug("%s skipped: %s (not in requested order)\n", 2999f9dc69eSPaul Moore origin, lsm->id->name); 30067a4b6a8SPaul Moore } 30167a4b6a8SPaul Moore 30267a4b6a8SPaul Moore kfree(sep); 30367a4b6a8SPaul Moore } 30467a4b6a8SPaul Moore 305faabedcdSPaul Moore /** 306faabedcdSPaul Moore * lsm_init_ordered - Initialize the ordered LSMs 307faabedcdSPaul Moore */ 308faabedcdSPaul Moore static void __init lsm_init_ordered(void) 30967a4b6a8SPaul Moore { 310cb1513dbSPaul Moore unsigned int first = 0; 31167a4b6a8SPaul Moore struct lsm_info **lsm; 312cb1513dbSPaul Moore struct lsm_info *early; 31367a4b6a8SPaul Moore 314*592b104fSPaul Moore if (lsm_order_cmdline) { 315*592b104fSPaul Moore if (lsm_order_legacy) { 31667a4b6a8SPaul Moore pr_warn("security=%s is ignored because it is superseded by lsm=%s\n", 317*592b104fSPaul Moore lsm_order_legacy, lsm_order_cmdline); 318*592b104fSPaul Moore lsm_order_legacy = NULL; 31967a4b6a8SPaul Moore } 320*592b104fSPaul Moore ordered_lsm_parse(lsm_order_cmdline, "cmdline"); 32167a4b6a8SPaul Moore } else 322*592b104fSPaul Moore ordered_lsm_parse(lsm_order_builtin, "builtin"); 32367a4b6a8SPaul Moore 32437f788f6SPaul Moore lsm_order_for_each(lsm) { 325e0257856SPaul Moore lsm_prepare(*lsm); 32637f788f6SPaul Moore } 32767a4b6a8SPaul Moore 328cb1513dbSPaul Moore pr_info("initializing lsm="); 329cb1513dbSPaul Moore lsm_early_for_each_raw(early) { 330cb1513dbSPaul Moore if (is_enabled(early)) 3319f9dc69eSPaul Moore pr_cont("%s%s", 3329f9dc69eSPaul Moore first++ == 0 ? "" : ",", early->id->name); 333cb1513dbSPaul Moore } 334cb1513dbSPaul Moore lsm_order_for_each(lsm) { 335cb1513dbSPaul Moore if (is_enabled(*lsm)) 3369f9dc69eSPaul Moore pr_cont("%s%s", 3379f9dc69eSPaul Moore first++ == 0 ? "" : ",", (*lsm)->id->name); 338cb1513dbSPaul Moore } 339cb1513dbSPaul Moore pr_cont("\n"); 34067a4b6a8SPaul Moore 34167a4b6a8SPaul Moore init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); 34267a4b6a8SPaul Moore init_debug("file blob size = %d\n", blob_sizes.lbs_file); 34367a4b6a8SPaul Moore init_debug("ib blob size = %d\n", blob_sizes.lbs_ib); 34467a4b6a8SPaul Moore init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); 34567a4b6a8SPaul Moore init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); 34667a4b6a8SPaul Moore #ifdef CONFIG_KEYS 34767a4b6a8SPaul Moore init_debug("key blob size = %d\n", blob_sizes.lbs_key); 34867a4b6a8SPaul Moore #endif /* CONFIG_KEYS */ 34967a4b6a8SPaul Moore init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); 35067a4b6a8SPaul Moore init_debug("sock blob size = %d\n", blob_sizes.lbs_sock); 35167a4b6a8SPaul Moore init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock); 35267a4b6a8SPaul Moore init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event); 35367a4b6a8SPaul Moore init_debug("task blob size = %d\n", blob_sizes.lbs_task); 35467a4b6a8SPaul Moore init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev); 35567a4b6a8SPaul Moore init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count); 35667a4b6a8SPaul Moore init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev); 35767a4b6a8SPaul Moore init_debug("bpf map blob size = %d\n", blob_sizes.lbs_bpf_map); 35867a4b6a8SPaul Moore init_debug("bpf prog blob size = %d\n", blob_sizes.lbs_bpf_prog); 35967a4b6a8SPaul Moore init_debug("bpf token blob size = %d\n", blob_sizes.lbs_bpf_token); 36067a4b6a8SPaul Moore 36167a4b6a8SPaul Moore if (blob_sizes.lbs_file) 36267a4b6a8SPaul Moore lsm_file_cache = kmem_cache_create("lsm_file_cache", 36367a4b6a8SPaul Moore blob_sizes.lbs_file, 0, 36467a4b6a8SPaul Moore SLAB_PANIC, NULL); 36567a4b6a8SPaul Moore if (blob_sizes.lbs_inode) 36667a4b6a8SPaul Moore lsm_inode_cache = kmem_cache_create("lsm_inode_cache", 36767a4b6a8SPaul Moore blob_sizes.lbs_inode, 0, 36867a4b6a8SPaul Moore SLAB_PANIC, NULL); 36967a4b6a8SPaul Moore 37092ed3500SPaul Moore if (lsm_cred_alloc((struct cred __rcu *)current->cred, GFP_KERNEL)) 37192ed3500SPaul Moore panic("%s: early cred alloc failed.\n", __func__); 37292ed3500SPaul Moore if (lsm_task_alloc(current)) 37392ed3500SPaul Moore panic("%s: early task alloc failed.\n", __func__); 37492ed3500SPaul Moore 37537f788f6SPaul Moore lsm_order_for_each(lsm) { 37667a4b6a8SPaul Moore initialize_lsm(*lsm); 37767a4b6a8SPaul Moore } 37837f788f6SPaul Moore } 37967a4b6a8SPaul Moore 38067a4b6a8SPaul Moore static bool match_last_lsm(const char *list, const char *lsm) 38167a4b6a8SPaul Moore { 38267a4b6a8SPaul Moore const char *last; 38367a4b6a8SPaul Moore 38467a4b6a8SPaul Moore if (WARN_ON(!list || !lsm)) 38567a4b6a8SPaul Moore return false; 38667a4b6a8SPaul Moore last = strrchr(list, ','); 38767a4b6a8SPaul Moore if (last) 38867a4b6a8SPaul Moore /* Pass the comma, strcmp() will check for '\0' */ 38967a4b6a8SPaul Moore last++; 39067a4b6a8SPaul Moore else 39167a4b6a8SPaul Moore last = list; 39267a4b6a8SPaul Moore return !strcmp(last, lsm); 39367a4b6a8SPaul Moore } 39467a4b6a8SPaul Moore 39567a4b6a8SPaul Moore static int lsm_append(const char *new, char **result) 39667a4b6a8SPaul Moore { 39767a4b6a8SPaul Moore char *cp; 39867a4b6a8SPaul Moore 39967a4b6a8SPaul Moore if (*result == NULL) { 40067a4b6a8SPaul Moore *result = kstrdup(new, GFP_KERNEL); 40167a4b6a8SPaul Moore if (*result == NULL) 40267a4b6a8SPaul Moore return -ENOMEM; 40367a4b6a8SPaul Moore } else { 40467a4b6a8SPaul Moore /* Check if it is the last registered name */ 40567a4b6a8SPaul Moore if (match_last_lsm(*result, new)) 40667a4b6a8SPaul Moore return 0; 40767a4b6a8SPaul Moore cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new); 40867a4b6a8SPaul Moore if (cp == NULL) 40967a4b6a8SPaul Moore return -ENOMEM; 41067a4b6a8SPaul Moore kfree(*result); 41167a4b6a8SPaul Moore *result = cp; 41267a4b6a8SPaul Moore } 41367a4b6a8SPaul Moore return 0; 41467a4b6a8SPaul Moore } 41567a4b6a8SPaul Moore 41667a4b6a8SPaul Moore static void __init lsm_static_call_init(struct security_hook_list *hl) 41767a4b6a8SPaul Moore { 41867a4b6a8SPaul Moore struct lsm_static_call *scall = hl->scalls; 41967a4b6a8SPaul Moore int i; 42067a4b6a8SPaul Moore 42167a4b6a8SPaul Moore for (i = 0; i < MAX_LSM_COUNT; i++) { 42267a4b6a8SPaul Moore /* Update the first static call that is not used yet */ 42367a4b6a8SPaul Moore if (!scall->hl) { 42467a4b6a8SPaul Moore __static_call_update(scall->key, scall->trampoline, 42567a4b6a8SPaul Moore hl->hook.lsm_func_addr); 42667a4b6a8SPaul Moore scall->hl = hl; 42767a4b6a8SPaul Moore static_branch_enable(scall->active); 42867a4b6a8SPaul Moore return; 42967a4b6a8SPaul Moore } 43067a4b6a8SPaul Moore scall++; 43167a4b6a8SPaul Moore } 43267a4b6a8SPaul Moore panic("%s - Ran out of static slots.\n", __func__); 43367a4b6a8SPaul Moore } 43467a4b6a8SPaul Moore 43567a4b6a8SPaul Moore /** 43667a4b6a8SPaul Moore * security_add_hooks - Add a modules hooks to the hook lists. 43767a4b6a8SPaul Moore * @hooks: the hooks to add 43867a4b6a8SPaul Moore * @count: the number of hooks to add 43967a4b6a8SPaul Moore * @lsmid: the identification information for the security module 44067a4b6a8SPaul Moore * 44167a4b6a8SPaul Moore * Each LSM has to register its hooks with the infrastructure. 44267a4b6a8SPaul Moore */ 44367a4b6a8SPaul Moore void __init security_add_hooks(struct security_hook_list *hooks, int count, 44467a4b6a8SPaul Moore const struct lsm_id *lsmid) 44567a4b6a8SPaul Moore { 44667a4b6a8SPaul Moore int i; 44767a4b6a8SPaul Moore 44867a4b6a8SPaul Moore for (i = 0; i < count; i++) { 44967a4b6a8SPaul Moore hooks[i].lsmid = lsmid; 45067a4b6a8SPaul Moore lsm_static_call_init(&hooks[i]); 45167a4b6a8SPaul Moore } 45267a4b6a8SPaul Moore 45367a4b6a8SPaul Moore /* 45467a4b6a8SPaul Moore * Don't try to append during early_security_init(), we'll come back 45567a4b6a8SPaul Moore * and fix this up afterwards. 45667a4b6a8SPaul Moore */ 45767a4b6a8SPaul Moore if (slab_is_available()) { 45867a4b6a8SPaul Moore if (lsm_append(lsmid->name, &lsm_names) < 0) 45967a4b6a8SPaul Moore panic("%s - Cannot get early memory.\n", __func__); 46067a4b6a8SPaul Moore } 46167a4b6a8SPaul Moore } 46267a4b6a8SPaul Moore 46367a4b6a8SPaul Moore int __init early_security_init(void) 46467a4b6a8SPaul Moore { 46567a4b6a8SPaul Moore struct lsm_info *lsm; 46667a4b6a8SPaul Moore 46737f788f6SPaul Moore lsm_early_for_each_raw(lsm) { 46867a4b6a8SPaul Moore if (!lsm->enabled) 46967a4b6a8SPaul Moore lsm->enabled = &lsm_enabled_true; 470e0257856SPaul Moore lsm_prepare(lsm); 47167a4b6a8SPaul Moore initialize_lsm(lsm); 47267a4b6a8SPaul Moore } 47367a4b6a8SPaul Moore 47467a4b6a8SPaul Moore return 0; 47567a4b6a8SPaul Moore } 47667a4b6a8SPaul Moore 47767a4b6a8SPaul Moore /** 47867a4b6a8SPaul Moore * security_init - initializes the security framework 47967a4b6a8SPaul Moore * 48067a4b6a8SPaul Moore * This should be called early in the kernel initialization sequence. 48167a4b6a8SPaul Moore */ 48267a4b6a8SPaul Moore int __init security_init(void) 48367a4b6a8SPaul Moore { 48467a4b6a8SPaul Moore struct lsm_info *lsm; 48567a4b6a8SPaul Moore 486*592b104fSPaul Moore init_debug("legacy security=%s\n", lsm_order_legacy ? : " *unspecified*"); 487*592b104fSPaul Moore init_debug(" CONFIG_LSM=%s\n", lsm_order_builtin); 488*592b104fSPaul Moore init_debug("boot arg lsm=%s\n", lsm_order_cmdline ? : " *unspecified*"); 48967a4b6a8SPaul Moore 49067a4b6a8SPaul Moore /* 49167a4b6a8SPaul Moore * Append the names of the early LSM modules now that kmalloc() is 49267a4b6a8SPaul Moore * available 49367a4b6a8SPaul Moore */ 49437f788f6SPaul Moore lsm_early_for_each_raw(lsm) { 4959f9dc69eSPaul Moore init_debug(" early started: %s (%s)\n", lsm->id->name, 49667a4b6a8SPaul Moore is_enabled(lsm) ? "enabled" : "disabled"); 49767a4b6a8SPaul Moore if (lsm->enabled) 4989f9dc69eSPaul Moore lsm_append(lsm->id->name, &lsm_names); 49967a4b6a8SPaul Moore } 50067a4b6a8SPaul Moore 50167a4b6a8SPaul Moore /* Load LSMs in specified order. */ 502faabedcdSPaul Moore lsm_init_ordered(); 50367a4b6a8SPaul Moore 50467a4b6a8SPaul Moore return 0; 50567a4b6a8SPaul Moore } 506