xref: /linux/security/lsm_init.c (revision 37f788f65528611f4482e2135d11ca34afb25828)
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 
35*37f788f6SPaul Moore #define lsm_order_for_each(iter)					\
36*37f788f6SPaul Moore 	for ((iter) = ordered_lsms; *(iter); (iter)++)
37*37f788f6SPaul Moore #define lsm_for_each_raw(iter)						\
38*37f788f6SPaul Moore 	for ((iter) = __start_lsm_info;					\
39*37f788f6SPaul Moore 	     (iter) < __end_lsm_info; (iter)++)
40*37f788f6SPaul Moore #define lsm_early_for_each_raw(iter)					\
41*37f788f6SPaul Moore 	for ((iter) = __start_early_lsm_info;				\
42*37f788f6SPaul Moore 	     (iter) < __end_early_lsm_info; (iter)++)
43*37f788f6SPaul 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 
108*37f788f6SPaul Moore 	lsm_order_for_each(check) {
10967a4b6a8SPaul Moore 		if (*check == lsm)
11067a4b6a8SPaul Moore 			return true;
111*37f788f6SPaul 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. */
222*37f788f6SPaul 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 		 */
237*37f788f6SPaul 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 
253*37f788f6SPaul 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) {
268*37f788f6SPaul 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. */
277*37f788f6SPaul 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. */
283*37f788f6SPaul 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 
29467a4b6a8SPaul Moore static void __init report_lsm_order(void)
29567a4b6a8SPaul Moore {
29667a4b6a8SPaul Moore 	struct lsm_info **lsm, *early;
29767a4b6a8SPaul Moore 	int first = 0;
29867a4b6a8SPaul Moore 
29967a4b6a8SPaul Moore 	pr_info("initializing lsm=");
30067a4b6a8SPaul Moore 
30167a4b6a8SPaul Moore 	/* Report each enabled LSM name, comma separated. */
302*37f788f6SPaul Moore 	lsm_early_for_each_raw(early) {
30367a4b6a8SPaul Moore 		if (is_enabled(early))
30467a4b6a8SPaul Moore 			pr_cont("%s%s", first++ == 0 ? "" : ",", early->name);
305*37f788f6SPaul Moore 	}
306*37f788f6SPaul Moore 	lsm_order_for_each(lsm) {
30767a4b6a8SPaul Moore 		if (is_enabled(*lsm))
30867a4b6a8SPaul Moore 			pr_cont("%s%s", first++ == 0 ? "" : ",", (*lsm)->name);
309*37f788f6SPaul Moore 	}
31067a4b6a8SPaul Moore 
31167a4b6a8SPaul Moore 	pr_cont("\n");
31267a4b6a8SPaul Moore }
31367a4b6a8SPaul Moore 
31467a4b6a8SPaul Moore /**
31567a4b6a8SPaul Moore  * lsm_early_cred - during initialization allocate a composite cred blob
31667a4b6a8SPaul Moore  * @cred: the cred that needs a blob
31767a4b6a8SPaul Moore  *
31867a4b6a8SPaul Moore  * Allocate the cred blob for all the modules
31967a4b6a8SPaul Moore  */
32067a4b6a8SPaul Moore static void __init lsm_early_cred(struct cred *cred)
32167a4b6a8SPaul Moore {
32267a4b6a8SPaul Moore 	int rc = lsm_cred_alloc(cred, GFP_KERNEL);
32367a4b6a8SPaul Moore 
32467a4b6a8SPaul Moore 	if (rc)
32567a4b6a8SPaul Moore 		panic("%s: Early cred alloc failed.\n", __func__);
32667a4b6a8SPaul Moore }
32767a4b6a8SPaul Moore 
32867a4b6a8SPaul Moore /**
32967a4b6a8SPaul Moore  * lsm_early_task - during initialization allocate a composite task blob
33067a4b6a8SPaul Moore  * @task: the task that needs a blob
33167a4b6a8SPaul Moore  *
33267a4b6a8SPaul Moore  * Allocate the task blob for all the modules
33367a4b6a8SPaul Moore  */
33467a4b6a8SPaul Moore static void __init lsm_early_task(struct task_struct *task)
33567a4b6a8SPaul Moore {
33667a4b6a8SPaul Moore 	int rc = lsm_task_alloc(task);
33767a4b6a8SPaul Moore 
33867a4b6a8SPaul Moore 	if (rc)
33967a4b6a8SPaul Moore 		panic("%s: Early task alloc failed.\n", __func__);
34067a4b6a8SPaul Moore }
34167a4b6a8SPaul Moore 
34267a4b6a8SPaul Moore static void __init ordered_lsm_init(void)
34367a4b6a8SPaul Moore {
34467a4b6a8SPaul Moore 	struct lsm_info **lsm;
34567a4b6a8SPaul Moore 
34667a4b6a8SPaul Moore 	if (chosen_lsm_order) {
34767a4b6a8SPaul Moore 		if (chosen_major_lsm) {
34867a4b6a8SPaul Moore 			pr_warn("security=%s is ignored because it is superseded by lsm=%s\n",
34967a4b6a8SPaul Moore 				chosen_major_lsm, chosen_lsm_order);
35067a4b6a8SPaul Moore 			chosen_major_lsm = NULL;
35167a4b6a8SPaul Moore 		}
35267a4b6a8SPaul Moore 		ordered_lsm_parse(chosen_lsm_order, "cmdline");
35367a4b6a8SPaul Moore 	} else
35467a4b6a8SPaul Moore 		ordered_lsm_parse(builtin_lsm_order, "builtin");
35567a4b6a8SPaul Moore 
356*37f788f6SPaul Moore 	lsm_order_for_each(lsm) {
357e0257856SPaul Moore 		lsm_prepare(*lsm);
358*37f788f6SPaul Moore 	}
35967a4b6a8SPaul Moore 
36067a4b6a8SPaul Moore 	report_lsm_order();
36167a4b6a8SPaul Moore 
36267a4b6a8SPaul Moore 	init_debug("cred blob size       = %d\n", blob_sizes.lbs_cred);
36367a4b6a8SPaul Moore 	init_debug("file blob size       = %d\n", blob_sizes.lbs_file);
36467a4b6a8SPaul Moore 	init_debug("ib blob size         = %d\n", blob_sizes.lbs_ib);
36567a4b6a8SPaul Moore 	init_debug("inode blob size      = %d\n", blob_sizes.lbs_inode);
36667a4b6a8SPaul Moore 	init_debug("ipc blob size        = %d\n", blob_sizes.lbs_ipc);
36767a4b6a8SPaul Moore #ifdef CONFIG_KEYS
36867a4b6a8SPaul Moore 	init_debug("key blob size        = %d\n", blob_sizes.lbs_key);
36967a4b6a8SPaul Moore #endif /* CONFIG_KEYS */
37067a4b6a8SPaul Moore 	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
37167a4b6a8SPaul Moore 	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
37267a4b6a8SPaul Moore 	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
37367a4b6a8SPaul Moore 	init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event);
37467a4b6a8SPaul Moore 	init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
37567a4b6a8SPaul Moore 	init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev);
37667a4b6a8SPaul Moore 	init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
37767a4b6a8SPaul Moore 	init_debug("bdev blob size       = %d\n", blob_sizes.lbs_bdev);
37867a4b6a8SPaul Moore 	init_debug("bpf map blob size    = %d\n", blob_sizes.lbs_bpf_map);
37967a4b6a8SPaul Moore 	init_debug("bpf prog blob size   = %d\n", blob_sizes.lbs_bpf_prog);
38067a4b6a8SPaul Moore 	init_debug("bpf token blob size  = %d\n", blob_sizes.lbs_bpf_token);
38167a4b6a8SPaul Moore 
38267a4b6a8SPaul Moore 	/*
38367a4b6a8SPaul Moore 	 * Create any kmem_caches needed for blobs
38467a4b6a8SPaul Moore 	 */
38567a4b6a8SPaul Moore 	if (blob_sizes.lbs_file)
38667a4b6a8SPaul Moore 		lsm_file_cache = kmem_cache_create("lsm_file_cache",
38767a4b6a8SPaul Moore 						   blob_sizes.lbs_file, 0,
38867a4b6a8SPaul Moore 						   SLAB_PANIC, NULL);
38967a4b6a8SPaul Moore 	if (blob_sizes.lbs_inode)
39067a4b6a8SPaul Moore 		lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
39167a4b6a8SPaul Moore 						    blob_sizes.lbs_inode, 0,
39267a4b6a8SPaul Moore 						    SLAB_PANIC, NULL);
39367a4b6a8SPaul Moore 
39467a4b6a8SPaul Moore 	lsm_early_cred((struct cred *) current->cred);
39567a4b6a8SPaul Moore 	lsm_early_task(current);
396*37f788f6SPaul Moore 	lsm_order_for_each(lsm) {
39767a4b6a8SPaul Moore 		initialize_lsm(*lsm);
39867a4b6a8SPaul Moore 	}
399*37f788f6SPaul Moore }
40067a4b6a8SPaul Moore 
40167a4b6a8SPaul Moore static bool match_last_lsm(const char *list, const char *lsm)
40267a4b6a8SPaul Moore {
40367a4b6a8SPaul Moore 	const char *last;
40467a4b6a8SPaul Moore 
40567a4b6a8SPaul Moore 	if (WARN_ON(!list || !lsm))
40667a4b6a8SPaul Moore 		return false;
40767a4b6a8SPaul Moore 	last = strrchr(list, ',');
40867a4b6a8SPaul Moore 	if (last)
40967a4b6a8SPaul Moore 		/* Pass the comma, strcmp() will check for '\0' */
41067a4b6a8SPaul Moore 		last++;
41167a4b6a8SPaul Moore 	else
41267a4b6a8SPaul Moore 		last = list;
41367a4b6a8SPaul Moore 	return !strcmp(last, lsm);
41467a4b6a8SPaul Moore }
41567a4b6a8SPaul Moore 
41667a4b6a8SPaul Moore static int lsm_append(const char *new, char **result)
41767a4b6a8SPaul Moore {
41867a4b6a8SPaul Moore 	char *cp;
41967a4b6a8SPaul Moore 
42067a4b6a8SPaul Moore 	if (*result == NULL) {
42167a4b6a8SPaul Moore 		*result = kstrdup(new, GFP_KERNEL);
42267a4b6a8SPaul Moore 		if (*result == NULL)
42367a4b6a8SPaul Moore 			return -ENOMEM;
42467a4b6a8SPaul Moore 	} else {
42567a4b6a8SPaul Moore 		/* Check if it is the last registered name */
42667a4b6a8SPaul Moore 		if (match_last_lsm(*result, new))
42767a4b6a8SPaul Moore 			return 0;
42867a4b6a8SPaul Moore 		cp = kasprintf(GFP_KERNEL, "%s,%s", *result, new);
42967a4b6a8SPaul Moore 		if (cp == NULL)
43067a4b6a8SPaul Moore 			return -ENOMEM;
43167a4b6a8SPaul Moore 		kfree(*result);
43267a4b6a8SPaul Moore 		*result = cp;
43367a4b6a8SPaul Moore 	}
43467a4b6a8SPaul Moore 	return 0;
43567a4b6a8SPaul Moore }
43667a4b6a8SPaul Moore 
43767a4b6a8SPaul Moore static void __init lsm_static_call_init(struct security_hook_list *hl)
43867a4b6a8SPaul Moore {
43967a4b6a8SPaul Moore 	struct lsm_static_call *scall = hl->scalls;
44067a4b6a8SPaul Moore 	int i;
44167a4b6a8SPaul Moore 
44267a4b6a8SPaul Moore 	for (i = 0; i < MAX_LSM_COUNT; i++) {
44367a4b6a8SPaul Moore 		/* Update the first static call that is not used yet */
44467a4b6a8SPaul Moore 		if (!scall->hl) {
44567a4b6a8SPaul Moore 			__static_call_update(scall->key, scall->trampoline,
44667a4b6a8SPaul Moore 					     hl->hook.lsm_func_addr);
44767a4b6a8SPaul Moore 			scall->hl = hl;
44867a4b6a8SPaul Moore 			static_branch_enable(scall->active);
44967a4b6a8SPaul Moore 			return;
45067a4b6a8SPaul Moore 		}
45167a4b6a8SPaul Moore 		scall++;
45267a4b6a8SPaul Moore 	}
45367a4b6a8SPaul Moore 	panic("%s - Ran out of static slots.\n", __func__);
45467a4b6a8SPaul Moore }
45567a4b6a8SPaul Moore 
45667a4b6a8SPaul Moore /**
45767a4b6a8SPaul Moore  * security_add_hooks - Add a modules hooks to the hook lists.
45867a4b6a8SPaul Moore  * @hooks: the hooks to add
45967a4b6a8SPaul Moore  * @count: the number of hooks to add
46067a4b6a8SPaul Moore  * @lsmid: the identification information for the security module
46167a4b6a8SPaul Moore  *
46267a4b6a8SPaul Moore  * Each LSM has to register its hooks with the infrastructure.
46367a4b6a8SPaul Moore  */
46467a4b6a8SPaul Moore void __init security_add_hooks(struct security_hook_list *hooks, int count,
46567a4b6a8SPaul Moore 			       const struct lsm_id *lsmid)
46667a4b6a8SPaul Moore {
46767a4b6a8SPaul Moore 	int i;
46867a4b6a8SPaul Moore 
46967a4b6a8SPaul Moore 	/*
47067a4b6a8SPaul Moore 	 * A security module may call security_add_hooks() more
47167a4b6a8SPaul Moore 	 * than once during initialization, and LSM initialization
47267a4b6a8SPaul Moore 	 * is serialized. Landlock is one such case.
47367a4b6a8SPaul Moore 	 * Look at the previous entry, if there is one, for duplication.
47467a4b6a8SPaul Moore 	 */
47567a4b6a8SPaul Moore 	if (lsm_active_cnt == 0 || lsm_idlist[lsm_active_cnt - 1] != lsmid) {
47667a4b6a8SPaul Moore 		if (lsm_active_cnt >= MAX_LSM_COUNT)
47767a4b6a8SPaul Moore 			panic("%s Too many LSMs registered.\n", __func__);
47867a4b6a8SPaul Moore 		lsm_idlist[lsm_active_cnt++] = lsmid;
47967a4b6a8SPaul Moore 	}
48067a4b6a8SPaul Moore 
48167a4b6a8SPaul Moore 	for (i = 0; i < count; i++) {
48267a4b6a8SPaul Moore 		hooks[i].lsmid = lsmid;
48367a4b6a8SPaul Moore 		lsm_static_call_init(&hooks[i]);
48467a4b6a8SPaul Moore 	}
48567a4b6a8SPaul Moore 
48667a4b6a8SPaul Moore 	/*
48767a4b6a8SPaul Moore 	 * Don't try to append during early_security_init(), we'll come back
48867a4b6a8SPaul Moore 	 * and fix this up afterwards.
48967a4b6a8SPaul Moore 	 */
49067a4b6a8SPaul Moore 	if (slab_is_available()) {
49167a4b6a8SPaul Moore 		if (lsm_append(lsmid->name, &lsm_names) < 0)
49267a4b6a8SPaul Moore 			panic("%s - Cannot get early memory.\n", __func__);
49367a4b6a8SPaul Moore 	}
49467a4b6a8SPaul Moore }
49567a4b6a8SPaul Moore 
49667a4b6a8SPaul Moore int __init early_security_init(void)
49767a4b6a8SPaul Moore {
49867a4b6a8SPaul Moore 	struct lsm_info *lsm;
49967a4b6a8SPaul Moore 
500*37f788f6SPaul Moore 	lsm_early_for_each_raw(lsm) {
50167a4b6a8SPaul Moore 		if (!lsm->enabled)
50267a4b6a8SPaul Moore 			lsm->enabled = &lsm_enabled_true;
503e0257856SPaul Moore 		lsm_prepare(lsm);
50467a4b6a8SPaul Moore 		initialize_lsm(lsm);
50567a4b6a8SPaul Moore 	}
50667a4b6a8SPaul Moore 
50767a4b6a8SPaul Moore 	return 0;
50867a4b6a8SPaul Moore }
50967a4b6a8SPaul Moore 
51067a4b6a8SPaul Moore /**
51167a4b6a8SPaul Moore  * security_init - initializes the security framework
51267a4b6a8SPaul Moore  *
51367a4b6a8SPaul Moore  * This should be called early in the kernel initialization sequence.
51467a4b6a8SPaul Moore  */
51567a4b6a8SPaul Moore int __init security_init(void)
51667a4b6a8SPaul Moore {
51767a4b6a8SPaul Moore 	struct lsm_info *lsm;
51867a4b6a8SPaul Moore 
51967a4b6a8SPaul Moore 	init_debug("legacy security=%s\n", chosen_major_lsm ? : " *unspecified*");
52067a4b6a8SPaul Moore 	init_debug("  CONFIG_LSM=%s\n", builtin_lsm_order);
52167a4b6a8SPaul Moore 	init_debug("boot arg lsm=%s\n", chosen_lsm_order ? : " *unspecified*");
52267a4b6a8SPaul Moore 
52367a4b6a8SPaul Moore 	/*
52467a4b6a8SPaul Moore 	 * Append the names of the early LSM modules now that kmalloc() is
52567a4b6a8SPaul Moore 	 * available
52667a4b6a8SPaul Moore 	 */
527*37f788f6SPaul Moore 	lsm_early_for_each_raw(lsm) {
52867a4b6a8SPaul Moore 		init_debug("  early started: %s (%s)\n", lsm->name,
52967a4b6a8SPaul Moore 			   is_enabled(lsm) ? "enabled" : "disabled");
53067a4b6a8SPaul Moore 		if (lsm->enabled)
53167a4b6a8SPaul Moore 			lsm_append(lsm->name, &lsm_names);
53267a4b6a8SPaul Moore 	}
53367a4b6a8SPaul Moore 
53467a4b6a8SPaul Moore 	/* Load LSMs in specified order. */
53567a4b6a8SPaul Moore 	ordered_lsm_init();
53667a4b6a8SPaul Moore 
53767a4b6a8SPaul Moore 	return 0;
53867a4b6a8SPaul Moore }
539