xref: /linux/security/lsm_init.c (revision 24a9c58978ee368cbd796a03cb6e8ade6e0b6f5f)
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 
132d671726SPaul Moore /* LSM enabled constants. */
142d671726SPaul Moore static __initdata int lsm_enabled_true = 1;
152d671726SPaul Moore static __initdata int lsm_enabled_false = 0;
162d671726SPaul Moore 
1767a4b6a8SPaul Moore /* Pointers to LSM sections defined in include/asm-generic/vmlinux.lds.h */
1867a4b6a8SPaul Moore extern struct lsm_info __start_lsm_info[], __end_lsm_info[];
1967a4b6a8SPaul Moore extern struct lsm_info __start_early_lsm_info[], __end_early_lsm_info[];
2067a4b6a8SPaul Moore 
21592b104fSPaul Moore /* Build and boot-time LSM ordering. */
22592b104fSPaul Moore static __initconst const char *const lsm_order_builtin = CONFIG_LSM;
23592b104fSPaul Moore static __initdata const char *lsm_order_cmdline;
24592b104fSPaul Moore static __initdata const char *lsm_order_legacy;
2567a4b6a8SPaul Moore 
2667a4b6a8SPaul Moore /* Ordered list of LSMs to initialize. */
27592b104fSPaul Moore static __initdata struct lsm_info *lsm_order[MAX_LSM_COUNT + 1];
28592b104fSPaul Moore static __initdata struct lsm_info *lsm_exclusive;
2967a4b6a8SPaul Moore 
3067a4b6a8SPaul Moore static __initdata bool debug;
3167a4b6a8SPaul Moore #define init_debug(...)							\
3267a4b6a8SPaul Moore 	do {								\
3367a4b6a8SPaul Moore 		if (debug)						\
3467a4b6a8SPaul Moore 			pr_info(__VA_ARGS__);				\
3567a4b6a8SPaul Moore 	} while (0)
3667a4b6a8SPaul Moore 
3737f788f6SPaul Moore #define lsm_order_for_each(iter)					\
38592b104fSPaul Moore 	for ((iter) = lsm_order; *(iter); (iter)++)
3937f788f6SPaul Moore #define lsm_for_each_raw(iter)						\
4037f788f6SPaul Moore 	for ((iter) = __start_lsm_info;					\
4137f788f6SPaul Moore 	     (iter) < __end_lsm_info; (iter)++)
4237f788f6SPaul Moore #define lsm_early_for_each_raw(iter)					\
4337f788f6SPaul Moore 	for ((iter) = __start_early_lsm_info;				\
4437f788f6SPaul Moore 	     (iter) < __end_early_lsm_info; (iter)++)
4537f788f6SPaul Moore 
46592b104fSPaul Moore /**
47592b104fSPaul Moore  * lsm_choose_security - Legacy "major" LSM selection
48592b104fSPaul Moore  * @str: kernel command line parameter
49592b104fSPaul Moore  */
50592b104fSPaul Moore static int __init lsm_choose_security(char *str)
5167a4b6a8SPaul Moore {
52592b104fSPaul Moore 	lsm_order_legacy = str;
5367a4b6a8SPaul Moore 	return 1;
5467a4b6a8SPaul Moore }
55592b104fSPaul Moore __setup("security=", lsm_choose_security);
5667a4b6a8SPaul Moore 
57592b104fSPaul Moore /**
58592b104fSPaul Moore  * lsm_choose_lsm - Modern LSM selection
59592b104fSPaul Moore  * @str: kernel command line parameter
60592b104fSPaul Moore  */
61592b104fSPaul Moore static int __init lsm_choose_lsm(char *str)
6267a4b6a8SPaul Moore {
63592b104fSPaul Moore 	lsm_order_cmdline = str;
6467a4b6a8SPaul Moore 	return 1;
6567a4b6a8SPaul Moore }
66592b104fSPaul Moore __setup("lsm=", lsm_choose_lsm);
6767a4b6a8SPaul Moore 
68592b104fSPaul Moore /**
69592b104fSPaul Moore  * lsm_debug_enable - Enable LSM framework debugging
70592b104fSPaul Moore  * @str: kernel command line parameter
71592b104fSPaul Moore  *
72592b104fSPaul Moore  * Currently we only provide debug info during LSM initialization, but we may
73592b104fSPaul Moore  * want to expand this in the future.
74592b104fSPaul Moore  */
75592b104fSPaul Moore static int __init lsm_debug_enable(char *str)
7667a4b6a8SPaul Moore {
7767a4b6a8SPaul Moore 	debug = true;
7867a4b6a8SPaul Moore 	return 1;
7967a4b6a8SPaul Moore }
80592b104fSPaul Moore __setup("lsm.debug", lsm_debug_enable);
8167a4b6a8SPaul Moore 
822d671726SPaul Moore /**
832d671726SPaul Moore  * lsm_enabled_set - Mark a LSM as enabled
842d671726SPaul Moore  * @lsm: LSM definition
852d671726SPaul Moore  * @enabled: enabled flag
862d671726SPaul Moore  */
872d671726SPaul Moore static void __init lsm_enabled_set(struct lsm_info *lsm, bool enabled)
8867a4b6a8SPaul Moore {
8967a4b6a8SPaul Moore 	/*
9067a4b6a8SPaul Moore 	 * When an LSM hasn't configured an enable variable, we can use
9167a4b6a8SPaul Moore 	 * a hard-coded location for storing the default enabled state.
9267a4b6a8SPaul Moore 	 */
932d671726SPaul Moore 	if (!lsm->enabled ||
942d671726SPaul Moore 	    lsm->enabled == &lsm_enabled_true ||
952d671726SPaul Moore 	    lsm->enabled == &lsm_enabled_false) {
962d671726SPaul Moore 		lsm->enabled = enabled ? &lsm_enabled_true : &lsm_enabled_false;
9767a4b6a8SPaul Moore 	} else {
9867a4b6a8SPaul Moore 		*lsm->enabled = enabled;
9967a4b6a8SPaul Moore 	}
10067a4b6a8SPaul Moore }
10167a4b6a8SPaul Moore 
1022d671726SPaul Moore /**
1032d671726SPaul Moore  * lsm_is_enabled - Determine if a LSM is enabled
1042d671726SPaul Moore  * @lsm: LSM definition
1052d671726SPaul Moore  */
1062d671726SPaul Moore static inline bool lsm_is_enabled(struct lsm_info *lsm)
10767a4b6a8SPaul Moore {
1082d671726SPaul Moore 	return (lsm->enabled ? *lsm->enabled : false);
10967a4b6a8SPaul Moore }
11067a4b6a8SPaul Moore 
111a748372aSPaul Moore /**
112a748372aSPaul Moore  * lsm_order_exists - Determine if a LSM exists in the ordered list
113a748372aSPaul Moore  * @lsm: LSM definition
114a748372aSPaul Moore  */
115a748372aSPaul Moore static bool __init lsm_order_exists(struct lsm_info *lsm)
11667a4b6a8SPaul Moore {
11767a4b6a8SPaul Moore 	struct lsm_info **check;
11867a4b6a8SPaul Moore 
11937f788f6SPaul Moore 	lsm_order_for_each(check) {
12067a4b6a8SPaul Moore 		if (*check == lsm)
12167a4b6a8SPaul Moore 			return true;
12237f788f6SPaul Moore 	}
12367a4b6a8SPaul Moore 
12467a4b6a8SPaul Moore 	return false;
12567a4b6a8SPaul Moore }
12667a4b6a8SPaul Moore 
127*24a9c589SPaul Moore /**
128*24a9c589SPaul Moore  * lsm_order_append - Append a LSM to the ordered list
129*24a9c589SPaul Moore  * @lsm: LSM definition
130*24a9c589SPaul Moore  * @src: source of the addition
131*24a9c589SPaul Moore  *
132*24a9c589SPaul Moore  * Append @lsm to the enabled LSM array after ensuring that it hasn't been
133*24a9c589SPaul Moore  * explicitly disabled, is a duplicate entry, or would run afoul of the
134*24a9c589SPaul Moore  * LSM_FLAG_EXCLUSIVE logic.
135*24a9c589SPaul Moore  */
136*24a9c589SPaul Moore static void __init lsm_order_append(struct lsm_info *lsm, const char *src)
13767a4b6a8SPaul Moore {
13867a4b6a8SPaul Moore 	/* Ignore duplicate selections. */
139a748372aSPaul Moore 	if (lsm_order_exists(lsm))
14067a4b6a8SPaul Moore 		return;
14167a4b6a8SPaul Moore 
142*24a9c589SPaul Moore 	/* Skip explicitly disabled LSMs. */
143*24a9c589SPaul Moore 	if (lsm->enabled && !lsm_is_enabled(lsm))
144*24a9c589SPaul Moore 		goto out;
14567a4b6a8SPaul Moore 
146*24a9c589SPaul Moore 	if (WARN(lsm_active_cnt == MAX_LSM_COUNT,
147*24a9c589SPaul Moore 		 "%s: out of LSM static calls!?\n", src)) {
148*24a9c589SPaul Moore 		lsm_enabled_set(lsm, false);
149*24a9c589SPaul Moore 		goto out;
150*24a9c589SPaul Moore 	}
15167a4b6a8SPaul Moore 
152*24a9c589SPaul Moore 	if (lsm->flags & LSM_FLAG_EXCLUSIVE) {
153*24a9c589SPaul Moore 		if (lsm_exclusive) {
154*24a9c589SPaul Moore 			init_debug("exclusive disabled: %s\n", lsm->id->name);
155*24a9c589SPaul Moore 			lsm_enabled_set(lsm, false);
156*24a9c589SPaul Moore 			goto out;
157*24a9c589SPaul Moore 		} else {
158*24a9c589SPaul Moore 			init_debug("exclusive chosen:   %s\n", lsm->id->name);
159*24a9c589SPaul Moore 			lsm_exclusive = lsm;
160*24a9c589SPaul Moore 		}
161*24a9c589SPaul Moore 	}
162*24a9c589SPaul Moore 
163*24a9c589SPaul Moore 	lsm_enabled_set(lsm, true);
164*24a9c589SPaul Moore 	lsm_order[lsm_active_cnt] = lsm;
165*24a9c589SPaul Moore 	lsm_idlist[lsm_active_cnt++] = lsm->id;
166*24a9c589SPaul Moore 
167*24a9c589SPaul Moore out:
168*24a9c589SPaul Moore 	init_debug("%s ordered: %s (%s)\n", src, lsm->id->name,
1692d671726SPaul Moore 		   lsm_is_enabled(lsm) ? "enabled" : "disabled");
17067a4b6a8SPaul Moore }
17167a4b6a8SPaul Moore 
17267a4b6a8SPaul Moore static void __init lsm_set_blob_size(int *need, int *lbs)
17367a4b6a8SPaul Moore {
17467a4b6a8SPaul Moore 	int offset;
17567a4b6a8SPaul Moore 
17667a4b6a8SPaul Moore 	if (*need <= 0)
17767a4b6a8SPaul Moore 		return;
17867a4b6a8SPaul Moore 
17967a4b6a8SPaul Moore 	offset = ALIGN(*lbs, sizeof(void *));
18067a4b6a8SPaul Moore 	*lbs = offset + *need;
18167a4b6a8SPaul Moore 	*need = offset;
18267a4b6a8SPaul Moore }
18367a4b6a8SPaul Moore 
184e0257856SPaul Moore /**
185e0257856SPaul Moore  * lsm_prepare - Prepare the LSM framework for a new LSM
186e0257856SPaul Moore  * @lsm: LSM definition
18767a4b6a8SPaul Moore  */
188e0257856SPaul Moore static void __init lsm_prepare(struct lsm_info *lsm)
18967a4b6a8SPaul Moore {
190*24a9c589SPaul Moore 	struct lsm_blob_sizes *blobs = lsm->blobs;
19167a4b6a8SPaul Moore 
192*24a9c589SPaul Moore 	if (!blobs)
193e0257856SPaul Moore 		return;
19467a4b6a8SPaul Moore 
195e0257856SPaul Moore 	/* Register the LSM blob sizes. */
196e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_cred, &blob_sizes.lbs_cred);
197e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_file, &blob_sizes.lbs_file);
198e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_ib, &blob_sizes.lbs_ib);
199e0257856SPaul Moore 	/* inode blob gets an rcu_head in addition to LSM blobs. */
200e0257856SPaul Moore 	if (blobs->lbs_inode && blob_sizes.lbs_inode == 0)
201e0257856SPaul Moore 		blob_sizes.lbs_inode = sizeof(struct rcu_head);
202e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_inode, &blob_sizes.lbs_inode);
203e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_ipc, &blob_sizes.lbs_ipc);
204e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_key, &blob_sizes.lbs_key);
205e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
206e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_perf_event, &blob_sizes.lbs_perf_event);
207e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_sock, &blob_sizes.lbs_sock);
208e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_superblock, &blob_sizes.lbs_superblock);
209e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_task, &blob_sizes.lbs_task);
210e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
211e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_xattr_count,
212e0257856SPaul Moore 			  &blob_sizes.lbs_xattr_count);
213e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_bdev, &blob_sizes.lbs_bdev);
214e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_bpf_map, &blob_sizes.lbs_bpf_map);
215e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog);
216e0257856SPaul Moore 	lsm_set_blob_size(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token);
21767a4b6a8SPaul Moore }
21867a4b6a8SPaul Moore 
21967a4b6a8SPaul Moore /* Initialize a given LSM, if it is enabled. */
22067a4b6a8SPaul Moore static void __init initialize_lsm(struct lsm_info *lsm)
22167a4b6a8SPaul Moore {
2222d671726SPaul Moore 	if (lsm_is_enabled(lsm)) {
22367a4b6a8SPaul Moore 		int ret;
22467a4b6a8SPaul Moore 
2259f9dc69eSPaul Moore 		init_debug("initializing %s\n", lsm->id->name);
22667a4b6a8SPaul Moore 		ret = lsm->init();
2279f9dc69eSPaul Moore 		WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret);
22867a4b6a8SPaul Moore 	}
22967a4b6a8SPaul Moore }
23067a4b6a8SPaul Moore 
23167a4b6a8SPaul Moore /* Populate ordered LSMs list from comma-separated LSM name list. */
23267a4b6a8SPaul Moore static void __init ordered_lsm_parse(const char *order, const char *origin)
23367a4b6a8SPaul Moore {
23467a4b6a8SPaul Moore 	struct lsm_info *lsm;
23567a4b6a8SPaul Moore 	char *sep, *name, *next;
23667a4b6a8SPaul Moore 
23767a4b6a8SPaul Moore 	/* LSM_ORDER_FIRST is always first. */
23837f788f6SPaul Moore 	lsm_for_each_raw(lsm) {
23967a4b6a8SPaul Moore 		if (lsm->order == LSM_ORDER_FIRST)
240*24a9c589SPaul Moore 			lsm_order_append(lsm, "  first");
24167a4b6a8SPaul Moore 	}
24267a4b6a8SPaul Moore 
24367a4b6a8SPaul Moore 	/* Process "security=", if given. */
244592b104fSPaul Moore 	if (lsm_order_legacy) {
24567a4b6a8SPaul Moore 		struct lsm_info *major;
24667a4b6a8SPaul Moore 
24767a4b6a8SPaul Moore 		/*
24867a4b6a8SPaul Moore 		 * To match the original "security=" behavior, this
24967a4b6a8SPaul Moore 		 * explicitly does NOT fallback to another Legacy Major
25067a4b6a8SPaul Moore 		 * if the selected one was separately disabled: disable
25167a4b6a8SPaul Moore 		 * all non-matching Legacy Major LSMs.
25267a4b6a8SPaul Moore 		 */
25337f788f6SPaul Moore 		lsm_for_each_raw(major) {
25467a4b6a8SPaul Moore 			if ((major->flags & LSM_FLAG_LEGACY_MAJOR) &&
255592b104fSPaul Moore 			    strcmp(major->id->name, lsm_order_legacy) != 0) {
2562d671726SPaul Moore 				lsm_enabled_set(major, false);
25767a4b6a8SPaul Moore 				init_debug("security=%s disabled: %s (only one legacy major LSM)\n",
258592b104fSPaul Moore 					   lsm_order_legacy, major->id->name);
25967a4b6a8SPaul Moore 			}
26067a4b6a8SPaul Moore 		}
26167a4b6a8SPaul Moore 	}
26267a4b6a8SPaul Moore 
26367a4b6a8SPaul Moore 	sep = kstrdup(order, GFP_KERNEL);
26467a4b6a8SPaul Moore 	next = sep;
26567a4b6a8SPaul Moore 	/* Walk the list, looking for matching LSMs. */
26667a4b6a8SPaul Moore 	while ((name = strsep(&next, ",")) != NULL) {
26767a4b6a8SPaul Moore 		bool found = false;
26867a4b6a8SPaul Moore 
26937f788f6SPaul Moore 		lsm_for_each_raw(lsm) {
2709f9dc69eSPaul Moore 			if (strcmp(lsm->id->name, name) == 0) {
27167a4b6a8SPaul Moore 				if (lsm->order == LSM_ORDER_MUTABLE)
272*24a9c589SPaul Moore 					lsm_order_append(lsm, origin);
27367a4b6a8SPaul Moore 				found = true;
27467a4b6a8SPaul Moore 			}
27567a4b6a8SPaul Moore 		}
27667a4b6a8SPaul Moore 
27767a4b6a8SPaul Moore 		if (!found)
27867a4b6a8SPaul Moore 			init_debug("%s ignored: %s (not built into kernel)\n",
27967a4b6a8SPaul Moore 				   origin, name);
28067a4b6a8SPaul Moore 	}
28167a4b6a8SPaul Moore 
28267a4b6a8SPaul Moore 	/* Process "security=", if given. */
283592b104fSPaul Moore 	if (lsm_order_legacy) {
28437f788f6SPaul Moore 		lsm_for_each_raw(lsm) {
285a748372aSPaul Moore 			if (lsm_order_exists(lsm))
28667a4b6a8SPaul Moore 				continue;
287592b104fSPaul Moore 			if (strcmp(lsm->id->name, lsm_order_legacy) == 0)
288*24a9c589SPaul Moore 				lsm_order_append(lsm, "security=");
28967a4b6a8SPaul Moore 		}
29067a4b6a8SPaul Moore 	}
29167a4b6a8SPaul Moore 
29267a4b6a8SPaul Moore 	/* LSM_ORDER_LAST is always last. */
29337f788f6SPaul Moore 	lsm_for_each_raw(lsm) {
29467a4b6a8SPaul Moore 		if (lsm->order == LSM_ORDER_LAST)
295*24a9c589SPaul Moore 			lsm_order_append(lsm, "   last");
29667a4b6a8SPaul Moore 	}
29767a4b6a8SPaul Moore 
29867a4b6a8SPaul Moore 	/* Disable all LSMs not in the ordered list. */
29937f788f6SPaul Moore 	lsm_for_each_raw(lsm) {
300a748372aSPaul Moore 		if (lsm_order_exists(lsm))
30167a4b6a8SPaul Moore 			continue;
3022d671726SPaul Moore 		lsm_enabled_set(lsm, false);
30367a4b6a8SPaul Moore 		init_debug("%s skipped: %s (not in requested order)\n",
3049f9dc69eSPaul Moore 			   origin, lsm->id->name);
30567a4b6a8SPaul Moore 	}
30667a4b6a8SPaul Moore 
30767a4b6a8SPaul Moore 	kfree(sep);
30867a4b6a8SPaul Moore }
30967a4b6a8SPaul Moore 
310faabedcdSPaul Moore /**
311faabedcdSPaul Moore  * lsm_init_ordered - Initialize the ordered LSMs
312faabedcdSPaul Moore  */
313faabedcdSPaul Moore static void __init lsm_init_ordered(void)
31467a4b6a8SPaul Moore {
315cb1513dbSPaul Moore 	unsigned int first = 0;
31667a4b6a8SPaul Moore 	struct lsm_info **lsm;
317cb1513dbSPaul Moore 	struct lsm_info *early;
31867a4b6a8SPaul Moore 
319592b104fSPaul Moore 	if (lsm_order_cmdline) {
320592b104fSPaul Moore 		if (lsm_order_legacy) {
32167a4b6a8SPaul Moore 			pr_warn("security=%s is ignored because it is superseded by lsm=%s\n",
322592b104fSPaul Moore 				lsm_order_legacy, lsm_order_cmdline);
323592b104fSPaul Moore 			lsm_order_legacy = NULL;
32467a4b6a8SPaul Moore 		}
325592b104fSPaul Moore 		ordered_lsm_parse(lsm_order_cmdline, "cmdline");
32667a4b6a8SPaul Moore 	} else
327592b104fSPaul Moore 		ordered_lsm_parse(lsm_order_builtin, "builtin");
32867a4b6a8SPaul Moore 
32937f788f6SPaul Moore 	lsm_order_for_each(lsm) {
330e0257856SPaul Moore 		lsm_prepare(*lsm);
33137f788f6SPaul Moore 	}
33267a4b6a8SPaul Moore 
333cb1513dbSPaul Moore 	pr_info("initializing lsm=");
334cb1513dbSPaul Moore 	lsm_early_for_each_raw(early) {
3352d671726SPaul Moore 		if (lsm_is_enabled(early))
3369f9dc69eSPaul Moore 			pr_cont("%s%s",
3379f9dc69eSPaul Moore 				first++ == 0 ? "" : ",", early->id->name);
338cb1513dbSPaul Moore 	}
339cb1513dbSPaul Moore 	lsm_order_for_each(lsm) {
3402d671726SPaul Moore 		if (lsm_is_enabled(*lsm))
3419f9dc69eSPaul Moore 			pr_cont("%s%s",
3429f9dc69eSPaul Moore 				first++ == 0 ? "" : ",", (*lsm)->id->name);
343cb1513dbSPaul Moore 	}
344cb1513dbSPaul Moore 	pr_cont("\n");
34567a4b6a8SPaul Moore 
34667a4b6a8SPaul Moore 	init_debug("cred blob size       = %d\n", blob_sizes.lbs_cred);
34767a4b6a8SPaul Moore 	init_debug("file blob size       = %d\n", blob_sizes.lbs_file);
34867a4b6a8SPaul Moore 	init_debug("ib blob size         = %d\n", blob_sizes.lbs_ib);
34967a4b6a8SPaul Moore 	init_debug("inode blob size      = %d\n", blob_sizes.lbs_inode);
35067a4b6a8SPaul Moore 	init_debug("ipc blob size        = %d\n", blob_sizes.lbs_ipc);
35167a4b6a8SPaul Moore #ifdef CONFIG_KEYS
35267a4b6a8SPaul Moore 	init_debug("key blob size        = %d\n", blob_sizes.lbs_key);
35367a4b6a8SPaul Moore #endif /* CONFIG_KEYS */
35467a4b6a8SPaul Moore 	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
35567a4b6a8SPaul Moore 	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
35667a4b6a8SPaul Moore 	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
35767a4b6a8SPaul Moore 	init_debug("perf event blob size = %d\n", blob_sizes.lbs_perf_event);
35867a4b6a8SPaul Moore 	init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
35967a4b6a8SPaul Moore 	init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev);
36067a4b6a8SPaul Moore 	init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
36167a4b6a8SPaul Moore 	init_debug("bdev blob size       = %d\n", blob_sizes.lbs_bdev);
36267a4b6a8SPaul Moore 	init_debug("bpf map blob size    = %d\n", blob_sizes.lbs_bpf_map);
36367a4b6a8SPaul Moore 	init_debug("bpf prog blob size   = %d\n", blob_sizes.lbs_bpf_prog);
36467a4b6a8SPaul Moore 	init_debug("bpf token blob size  = %d\n", blob_sizes.lbs_bpf_token);
36567a4b6a8SPaul Moore 
36667a4b6a8SPaul Moore 	if (blob_sizes.lbs_file)
36767a4b6a8SPaul Moore 		lsm_file_cache = kmem_cache_create("lsm_file_cache",
36867a4b6a8SPaul Moore 						   blob_sizes.lbs_file, 0,
36967a4b6a8SPaul Moore 						   SLAB_PANIC, NULL);
37067a4b6a8SPaul Moore 	if (blob_sizes.lbs_inode)
37167a4b6a8SPaul Moore 		lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
37267a4b6a8SPaul Moore 						    blob_sizes.lbs_inode, 0,
37367a4b6a8SPaul Moore 						    SLAB_PANIC, NULL);
37467a4b6a8SPaul Moore 
37592ed3500SPaul Moore 	if (lsm_cred_alloc((struct cred __rcu *)current->cred, GFP_KERNEL))
37692ed3500SPaul Moore 		panic("%s: early cred alloc failed.\n", __func__);
37792ed3500SPaul Moore 	if (lsm_task_alloc(current))
37892ed3500SPaul Moore 		panic("%s: early task alloc failed.\n", __func__);
37992ed3500SPaul Moore 
38037f788f6SPaul Moore 	lsm_order_for_each(lsm) {
38167a4b6a8SPaul Moore 		initialize_lsm(*lsm);
38267a4b6a8SPaul Moore 	}
38337f788f6SPaul Moore }
38467a4b6a8SPaul Moore 
38567a4b6a8SPaul Moore static void __init lsm_static_call_init(struct security_hook_list *hl)
38667a4b6a8SPaul Moore {
38767a4b6a8SPaul Moore 	struct lsm_static_call *scall = hl->scalls;
38867a4b6a8SPaul Moore 	int i;
38967a4b6a8SPaul Moore 
39067a4b6a8SPaul Moore 	for (i = 0; i < MAX_LSM_COUNT; i++) {
39167a4b6a8SPaul Moore 		/* Update the first static call that is not used yet */
39267a4b6a8SPaul Moore 		if (!scall->hl) {
39367a4b6a8SPaul Moore 			__static_call_update(scall->key, scall->trampoline,
39467a4b6a8SPaul Moore 					     hl->hook.lsm_func_addr);
39567a4b6a8SPaul Moore 			scall->hl = hl;
39667a4b6a8SPaul Moore 			static_branch_enable(scall->active);
39767a4b6a8SPaul Moore 			return;
39867a4b6a8SPaul Moore 		}
39967a4b6a8SPaul Moore 		scall++;
40067a4b6a8SPaul Moore 	}
40167a4b6a8SPaul Moore 	panic("%s - Ran out of static slots.\n", __func__);
40267a4b6a8SPaul Moore }
40367a4b6a8SPaul Moore 
40467a4b6a8SPaul Moore /**
40567a4b6a8SPaul Moore  * security_add_hooks - Add a modules hooks to the hook lists.
40667a4b6a8SPaul Moore  * @hooks: the hooks to add
40767a4b6a8SPaul Moore  * @count: the number of hooks to add
40867a4b6a8SPaul Moore  * @lsmid: the identification information for the security module
40967a4b6a8SPaul Moore  *
41067a4b6a8SPaul Moore  * Each LSM has to register its hooks with the infrastructure.
41167a4b6a8SPaul Moore  */
41267a4b6a8SPaul Moore void __init security_add_hooks(struct security_hook_list *hooks, int count,
41367a4b6a8SPaul Moore 			       const struct lsm_id *lsmid)
41467a4b6a8SPaul Moore {
41567a4b6a8SPaul Moore 	int i;
41667a4b6a8SPaul Moore 
41767a4b6a8SPaul Moore 	for (i = 0; i < count; i++) {
41867a4b6a8SPaul Moore 		hooks[i].lsmid = lsmid;
41967a4b6a8SPaul Moore 		lsm_static_call_init(&hooks[i]);
42067a4b6a8SPaul Moore 	}
42167a4b6a8SPaul Moore }
42267a4b6a8SPaul Moore 
42367a4b6a8SPaul Moore int __init early_security_init(void)
42467a4b6a8SPaul Moore {
42567a4b6a8SPaul Moore 	struct lsm_info *lsm;
42667a4b6a8SPaul Moore 
42737f788f6SPaul Moore 	lsm_early_for_each_raw(lsm) {
428*24a9c589SPaul Moore 		lsm_enabled_set(lsm, true);
429*24a9c589SPaul Moore 		lsm_order_append(lsm, "early");
430e0257856SPaul Moore 		lsm_prepare(lsm);
43167a4b6a8SPaul Moore 		initialize_lsm(lsm);
43267a4b6a8SPaul Moore 	}
43367a4b6a8SPaul Moore 
43467a4b6a8SPaul Moore 	return 0;
43567a4b6a8SPaul Moore }
43667a4b6a8SPaul Moore 
43767a4b6a8SPaul Moore /**
43867a4b6a8SPaul Moore  * security_init - initializes the security framework
43967a4b6a8SPaul Moore  *
44067a4b6a8SPaul Moore  * This should be called early in the kernel initialization sequence.
44167a4b6a8SPaul Moore  */
44267a4b6a8SPaul Moore int __init security_init(void)
44367a4b6a8SPaul Moore {
44467a4b6a8SPaul Moore 	struct lsm_info *lsm;
44567a4b6a8SPaul Moore 
446592b104fSPaul Moore 	init_debug("legacy security=%s\n", lsm_order_legacy ? : " *unspecified*");
447592b104fSPaul Moore 	init_debug("  CONFIG_LSM=%s\n", lsm_order_builtin);
448592b104fSPaul Moore 	init_debug("boot arg lsm=%s\n", lsm_order_cmdline ? : " *unspecified*");
44967a4b6a8SPaul Moore 
45067a4b6a8SPaul Moore 	/*
45167a4b6a8SPaul Moore 	 * Append the names of the early LSM modules now that kmalloc() is
45267a4b6a8SPaul Moore 	 * available
45367a4b6a8SPaul Moore 	 */
45437f788f6SPaul Moore 	lsm_early_for_each_raw(lsm) {
4559f9dc69eSPaul Moore 		init_debug("  early started: %s (%s)\n", lsm->id->name,
4562d671726SPaul Moore 			   lsm_is_enabled(lsm) ? "enabled" : "disabled");
45767a4b6a8SPaul Moore 	}
45867a4b6a8SPaul Moore 
45967a4b6a8SPaul Moore 	/* Load LSMs in specified order. */
460faabedcdSPaul Moore 	lsm_init_ordered();
46167a4b6a8SPaul Moore 
46267a4b6a8SPaul Moore 	return 0;
46367a4b6a8SPaul Moore }
464