xref: /linux/security/lsm_init.c (revision cdc028812f727907d1575cf454a5f01ddffa7750)
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 
2145a41d13SPaul Moore /* Number of "early" LSMs */
2245a41d13SPaul Moore static __initdata unsigned int lsm_count_early;
2345a41d13SPaul Moore 
24592b104fSPaul Moore /* Build and boot-time LSM ordering. */
25592b104fSPaul Moore static __initconst const char *const lsm_order_builtin = CONFIG_LSM;
26592b104fSPaul Moore static __initdata const char *lsm_order_cmdline;
27592b104fSPaul Moore static __initdata const char *lsm_order_legacy;
2867a4b6a8SPaul Moore 
2967a4b6a8SPaul Moore /* Ordered list of LSMs to initialize. */
30592b104fSPaul Moore static __initdata struct lsm_info *lsm_order[MAX_LSM_COUNT + 1];
31592b104fSPaul Moore static __initdata struct lsm_info *lsm_exclusive;
3267a4b6a8SPaul Moore 
3337f788f6SPaul Moore #define lsm_order_for_each(iter)					\
34592b104fSPaul Moore 	for ((iter) = lsm_order; *(iter); (iter)++)
3537f788f6SPaul Moore #define lsm_for_each_raw(iter)						\
3637f788f6SPaul Moore 	for ((iter) = __start_lsm_info;					\
3737f788f6SPaul Moore 	     (iter) < __end_lsm_info; (iter)++)
3837f788f6SPaul Moore #define lsm_early_for_each_raw(iter)					\
3937f788f6SPaul Moore 	for ((iter) = __start_early_lsm_info;				\
4037f788f6SPaul Moore 	     (iter) < __end_early_lsm_info; (iter)++)
4137f788f6SPaul Moore 
42*cdc02881SPaul Moore #define lsm_initcall(level)						\
43*cdc02881SPaul Moore 	({								\
44*cdc02881SPaul Moore 		int _r, _rc = 0;					\
45*cdc02881SPaul Moore 		struct lsm_info **_lp, *_l;				\
46*cdc02881SPaul Moore 		lsm_order_for_each(_lp) {				\
47*cdc02881SPaul Moore 			_l = *_lp;					\
48*cdc02881SPaul Moore 			if (!_l->initcall_##level)			\
49*cdc02881SPaul Moore 				continue;				\
50*cdc02881SPaul Moore 			lsm_pr_dbg("running %s %s initcall",		\
51*cdc02881SPaul Moore 				   _l->id->name, #level);		\
52*cdc02881SPaul Moore 			_r = _l->initcall_##level();			\
53*cdc02881SPaul Moore 			if (_r) {					\
54*cdc02881SPaul Moore 				pr_warn("failed LSM %s %s initcall with errno %d\n", \
55*cdc02881SPaul Moore 					_l->id->name, #level, _r);	\
56*cdc02881SPaul Moore 				if (!_rc)				\
57*cdc02881SPaul Moore 					_rc = _r;			\
58*cdc02881SPaul Moore 			}						\
59*cdc02881SPaul Moore 		}							\
60*cdc02881SPaul Moore 		_rc;							\
61*cdc02881SPaul Moore 	})
62*cdc02881SPaul Moore 
63592b104fSPaul Moore /**
64592b104fSPaul Moore  * lsm_choose_security - Legacy "major" LSM selection
65592b104fSPaul Moore  * @str: kernel command line parameter
66592b104fSPaul Moore  */
67592b104fSPaul Moore static int __init lsm_choose_security(char *str)
6867a4b6a8SPaul Moore {
69592b104fSPaul Moore 	lsm_order_legacy = str;
7067a4b6a8SPaul Moore 	return 1;
7167a4b6a8SPaul Moore }
72592b104fSPaul Moore __setup("security=", lsm_choose_security);
7367a4b6a8SPaul Moore 
74592b104fSPaul Moore /**
75592b104fSPaul Moore  * lsm_choose_lsm - Modern LSM selection
76592b104fSPaul Moore  * @str: kernel command line parameter
77592b104fSPaul Moore  */
78592b104fSPaul Moore static int __init lsm_choose_lsm(char *str)
7967a4b6a8SPaul Moore {
80592b104fSPaul Moore 	lsm_order_cmdline = str;
8167a4b6a8SPaul Moore 	return 1;
8267a4b6a8SPaul Moore }
83592b104fSPaul Moore __setup("lsm=", lsm_choose_lsm);
8467a4b6a8SPaul Moore 
85592b104fSPaul Moore /**
86592b104fSPaul Moore  * lsm_debug_enable - Enable LSM framework debugging
87592b104fSPaul Moore  * @str: kernel command line parameter
88592b104fSPaul Moore  *
89592b104fSPaul Moore  * Currently we only provide debug info during LSM initialization, but we may
90592b104fSPaul Moore  * want to expand this in the future.
91592b104fSPaul Moore  */
92592b104fSPaul Moore static int __init lsm_debug_enable(char *str)
9367a4b6a8SPaul Moore {
945137e583SPaul Moore 	lsm_debug = true;
9567a4b6a8SPaul Moore 	return 1;
9667a4b6a8SPaul Moore }
97592b104fSPaul Moore __setup("lsm.debug", lsm_debug_enable);
9867a4b6a8SPaul Moore 
992d671726SPaul Moore /**
1002d671726SPaul Moore  * lsm_enabled_set - Mark a LSM as enabled
1012d671726SPaul Moore  * @lsm: LSM definition
1022d671726SPaul Moore  * @enabled: enabled flag
1032d671726SPaul Moore  */
1042d671726SPaul Moore static void __init lsm_enabled_set(struct lsm_info *lsm, bool enabled)
10567a4b6a8SPaul Moore {
10667a4b6a8SPaul Moore 	/*
10767a4b6a8SPaul Moore 	 * When an LSM hasn't configured an enable variable, we can use
10867a4b6a8SPaul Moore 	 * a hard-coded location for storing the default enabled state.
10967a4b6a8SPaul Moore 	 */
1102d671726SPaul Moore 	if (!lsm->enabled ||
1112d671726SPaul Moore 	    lsm->enabled == &lsm_enabled_true ||
1122d671726SPaul Moore 	    lsm->enabled == &lsm_enabled_false) {
1132d671726SPaul Moore 		lsm->enabled = enabled ? &lsm_enabled_true : &lsm_enabled_false;
11467a4b6a8SPaul Moore 	} else {
11567a4b6a8SPaul Moore 		*lsm->enabled = enabled;
11667a4b6a8SPaul Moore 	}
11767a4b6a8SPaul Moore }
11867a4b6a8SPaul Moore 
1192d671726SPaul Moore /**
1202d671726SPaul Moore  * lsm_is_enabled - Determine if a LSM is enabled
1212d671726SPaul Moore  * @lsm: LSM definition
1222d671726SPaul Moore  */
1232d671726SPaul Moore static inline bool lsm_is_enabled(struct lsm_info *lsm)
12467a4b6a8SPaul Moore {
1252d671726SPaul Moore 	return (lsm->enabled ? *lsm->enabled : false);
12667a4b6a8SPaul Moore }
12767a4b6a8SPaul Moore 
128a748372aSPaul Moore /**
129a748372aSPaul Moore  * lsm_order_exists - Determine if a LSM exists in the ordered list
130a748372aSPaul Moore  * @lsm: LSM definition
131a748372aSPaul Moore  */
132a748372aSPaul Moore static bool __init lsm_order_exists(struct lsm_info *lsm)
13367a4b6a8SPaul Moore {
13467a4b6a8SPaul Moore 	struct lsm_info **check;
13567a4b6a8SPaul Moore 
13637f788f6SPaul Moore 	lsm_order_for_each(check) {
13767a4b6a8SPaul Moore 		if (*check == lsm)
13867a4b6a8SPaul Moore 			return true;
13937f788f6SPaul Moore 	}
14067a4b6a8SPaul Moore 
14167a4b6a8SPaul Moore 	return false;
14267a4b6a8SPaul Moore }
14367a4b6a8SPaul Moore 
14424a9c589SPaul Moore /**
14524a9c589SPaul Moore  * lsm_order_append - Append a LSM to the ordered list
14624a9c589SPaul Moore  * @lsm: LSM definition
14724a9c589SPaul Moore  * @src: source of the addition
14824a9c589SPaul Moore  *
14924a9c589SPaul Moore  * Append @lsm to the enabled LSM array after ensuring that it hasn't been
15024a9c589SPaul Moore  * explicitly disabled, is a duplicate entry, or would run afoul of the
15124a9c589SPaul Moore  * LSM_FLAG_EXCLUSIVE logic.
15224a9c589SPaul Moore  */
15324a9c589SPaul Moore static void __init lsm_order_append(struct lsm_info *lsm, const char *src)
15467a4b6a8SPaul Moore {
15567a4b6a8SPaul Moore 	/* Ignore duplicate selections. */
156a748372aSPaul Moore 	if (lsm_order_exists(lsm))
15767a4b6a8SPaul Moore 		return;
15867a4b6a8SPaul Moore 
15924a9c589SPaul Moore 	/* Skip explicitly disabled LSMs. */
1605137e583SPaul Moore 	if (lsm->enabled && !lsm_is_enabled(lsm)) {
1615137e583SPaul Moore 		lsm_pr_dbg("skip previously disabled LSM %s:%s\n",
1625137e583SPaul Moore 			   src, lsm->id->name);
1635137e583SPaul Moore 		return;
1645137e583SPaul Moore 	}
16567a4b6a8SPaul Moore 
1665137e583SPaul Moore 	if (lsm_active_cnt == MAX_LSM_COUNT) {
1675137e583SPaul Moore 		pr_warn("exceeded maximum LSM count on %s:%s\n",
1685137e583SPaul Moore 			src, lsm->id->name);
16924a9c589SPaul Moore 		lsm_enabled_set(lsm, false);
1705137e583SPaul Moore 		return;
17124a9c589SPaul Moore 	}
17267a4b6a8SPaul Moore 
17324a9c589SPaul Moore 	if (lsm->flags & LSM_FLAG_EXCLUSIVE) {
17424a9c589SPaul Moore 		if (lsm_exclusive) {
1755137e583SPaul Moore 			lsm_pr_dbg("skip exclusive LSM conflict %s:%s\n",
1765137e583SPaul Moore 				   src, lsm->id->name);
17724a9c589SPaul Moore 			lsm_enabled_set(lsm, false);
1785137e583SPaul Moore 			return;
17924a9c589SPaul Moore 		} else {
1805137e583SPaul Moore 			lsm_pr_dbg("select exclusive LSM %s:%s\n",
1815137e583SPaul Moore 				   src, lsm->id->name);
18224a9c589SPaul Moore 			lsm_exclusive = lsm;
18324a9c589SPaul Moore 		}
18424a9c589SPaul Moore 	}
18524a9c589SPaul Moore 
18624a9c589SPaul Moore 	lsm_enabled_set(lsm, true);
18724a9c589SPaul Moore 	lsm_order[lsm_active_cnt] = lsm;
18824a9c589SPaul Moore 	lsm_idlist[lsm_active_cnt++] = lsm->id;
18924a9c589SPaul Moore 
1905137e583SPaul Moore 	lsm_pr_dbg("enabling LSM %s:%s\n", src, lsm->id->name);
19167a4b6a8SPaul Moore }
19267a4b6a8SPaul Moore 
193291271e6SPaul Moore /**
1943423c639SPaul Moore  * lsm_order_parse - Parse the comma delimited LSM list
1953423c639SPaul Moore  * @list: LSM list
1963423c639SPaul Moore  * @src: source of the list
1973423c639SPaul Moore  */
1983423c639SPaul Moore static void __init lsm_order_parse(const char *list, const char *src)
1993423c639SPaul Moore {
2003423c639SPaul Moore 	struct lsm_info *lsm;
2013423c639SPaul Moore 	char *sep, *name, *next;
2023423c639SPaul Moore 
2033423c639SPaul Moore 	/* Handle any Legacy LSM exclusions if one was specified. */
2043423c639SPaul Moore 	if (lsm_order_legacy) {
2053423c639SPaul Moore 		/*
2063423c639SPaul Moore 		 * To match the original "security=" behavior, this explicitly
2073423c639SPaul Moore 		 * does NOT fallback to another Legacy Major if the selected
2083423c639SPaul Moore 		 * one was separately disabled: disable all non-matching
2093423c639SPaul Moore 		 * Legacy Major LSMs.
2103423c639SPaul Moore 		 */
2113423c639SPaul Moore 		lsm_for_each_raw(lsm) {
2123423c639SPaul Moore 			if ((lsm->flags & LSM_FLAG_LEGACY_MAJOR) &&
2133423c639SPaul Moore 			     strcmp(lsm->id->name, lsm_order_legacy)) {
2143423c639SPaul Moore 				lsm_enabled_set(lsm, false);
2153423c639SPaul Moore 				lsm_pr_dbg("skip legacy LSM conflict %s:%s\n",
2163423c639SPaul Moore 					   src, lsm->id->name);
2173423c639SPaul Moore 			}
2183423c639SPaul Moore 		}
2193423c639SPaul Moore 	}
2203423c639SPaul Moore 
2213423c639SPaul Moore 	/* LSM_ORDER_FIRST */
2223423c639SPaul Moore 	lsm_for_each_raw(lsm) {
2233423c639SPaul Moore 		if (lsm->order == LSM_ORDER_FIRST)
2243423c639SPaul Moore 			lsm_order_append(lsm, "first");
2253423c639SPaul Moore 	}
2263423c639SPaul Moore 
2273423c639SPaul Moore 	/* Normal or "mutable" LSMs */
2283423c639SPaul Moore 	sep = kstrdup(list, GFP_KERNEL);
2293423c639SPaul Moore 	next = sep;
2303423c639SPaul Moore 	/* Walk the list, looking for matching LSMs. */
2313423c639SPaul Moore 	while ((name = strsep(&next, ",")) != NULL) {
2323423c639SPaul Moore 		lsm_for_each_raw(lsm) {
2333423c639SPaul Moore 			if (!strcmp(lsm->id->name, name) &&
2343423c639SPaul Moore 			    lsm->order == LSM_ORDER_MUTABLE)
2353423c639SPaul Moore 				lsm_order_append(lsm, src);
2363423c639SPaul Moore 		}
2373423c639SPaul Moore 	}
2383423c639SPaul Moore 	kfree(sep);
2393423c639SPaul Moore 
2403423c639SPaul Moore 	/* Legacy LSM if specified. */
2413423c639SPaul Moore 	if (lsm_order_legacy) {
2423423c639SPaul Moore 		lsm_for_each_raw(lsm) {
2433423c639SPaul Moore 			if (!strcmp(lsm->id->name, lsm_order_legacy))
2443423c639SPaul Moore 				lsm_order_append(lsm, src);
2453423c639SPaul Moore 		}
2463423c639SPaul Moore 	}
2473423c639SPaul Moore 
2483423c639SPaul Moore 	/* LSM_ORDER_LAST */
2493423c639SPaul Moore 	lsm_for_each_raw(lsm) {
2503423c639SPaul Moore 		if (lsm->order == LSM_ORDER_LAST)
2513423c639SPaul Moore 			lsm_order_append(lsm, "last");
2523423c639SPaul Moore 	}
2533423c639SPaul Moore 
2543423c639SPaul Moore 	/* Disable all LSMs not previously enabled. */
2553423c639SPaul Moore 	lsm_for_each_raw(lsm) {
2563423c639SPaul Moore 		if (lsm_order_exists(lsm))
2573423c639SPaul Moore 			continue;
2583423c639SPaul Moore 		lsm_enabled_set(lsm, false);
2593423c639SPaul Moore 		lsm_pr_dbg("skip disabled LSM %s:%s\n", src, lsm->id->name);
2603423c639SPaul Moore 	}
2613423c639SPaul Moore }
2623423c639SPaul Moore 
2633423c639SPaul Moore /**
264291271e6SPaul Moore  * lsm_blob_size_update - Update the LSM blob size and offset information
265291271e6SPaul Moore  * @sz_req: the requested additional blob size
266291271e6SPaul Moore  * @sz_cur: the existing blob size
267291271e6SPaul Moore  */
268291271e6SPaul Moore static void __init lsm_blob_size_update(unsigned int *sz_req,
269291271e6SPaul Moore 					unsigned int *sz_cur)
27067a4b6a8SPaul Moore {
271291271e6SPaul Moore 	unsigned int offset;
27267a4b6a8SPaul Moore 
273291271e6SPaul Moore 	if (*sz_req == 0)
27467a4b6a8SPaul Moore 		return;
27567a4b6a8SPaul Moore 
276291271e6SPaul Moore 	offset = ALIGN(*sz_cur, sizeof(void *));
277291271e6SPaul Moore 	*sz_cur = offset + *sz_req;
278291271e6SPaul Moore 	*sz_req = offset;
27967a4b6a8SPaul Moore }
28067a4b6a8SPaul Moore 
281e0257856SPaul Moore /**
282e0257856SPaul Moore  * lsm_prepare - Prepare the LSM framework for a new LSM
283e0257856SPaul Moore  * @lsm: LSM definition
28467a4b6a8SPaul Moore  */
285e0257856SPaul Moore static void __init lsm_prepare(struct lsm_info *lsm)
28667a4b6a8SPaul Moore {
28724a9c589SPaul Moore 	struct lsm_blob_sizes *blobs = lsm->blobs;
28867a4b6a8SPaul Moore 
28924a9c589SPaul Moore 	if (!blobs)
290e0257856SPaul Moore 		return;
29167a4b6a8SPaul Moore 
292e0257856SPaul Moore 	/* Register the LSM blob sizes. */
293291271e6SPaul Moore 	blobs = lsm->blobs;
294291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred);
295291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file);
296291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_ib, &blob_sizes.lbs_ib);
297e0257856SPaul Moore 	/* inode blob gets an rcu_head in addition to LSM blobs. */
298e0257856SPaul Moore 	if (blobs->lbs_inode && blob_sizes.lbs_inode == 0)
299e0257856SPaul Moore 		blob_sizes.lbs_inode = sizeof(struct rcu_head);
300291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_inode, &blob_sizes.lbs_inode);
301291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_ipc, &blob_sizes.lbs_ipc);
302291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_key, &blob_sizes.lbs_key);
303291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
304291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_perf_event,
305291271e6SPaul Moore 			     &blob_sizes.lbs_perf_event);
306291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_sock, &blob_sizes.lbs_sock);
307291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_superblock,
308291271e6SPaul Moore 			     &blob_sizes.lbs_superblock);
309291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_task, &blob_sizes.lbs_task);
310291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
311291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_xattr_count,
312e0257856SPaul Moore 			     &blob_sizes.lbs_xattr_count);
313291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_bdev, &blob_sizes.lbs_bdev);
314291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_bpf_map, &blob_sizes.lbs_bpf_map);
315291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog);
316291271e6SPaul Moore 	lsm_blob_size_update(&blobs->lbs_bpf_token, &blob_sizes.lbs_bpf_token);
31767a4b6a8SPaul Moore }
31867a4b6a8SPaul Moore 
31927be5600SPaul Moore /**
32027be5600SPaul Moore  * lsm_init_single - Initialize a given LSM
32127be5600SPaul Moore  * @lsm: LSM definition
32227be5600SPaul Moore  */
32327be5600SPaul Moore static void __init lsm_init_single(struct lsm_info *lsm)
32467a4b6a8SPaul Moore {
32567a4b6a8SPaul Moore 	int ret;
32667a4b6a8SPaul Moore 
32727be5600SPaul Moore 	if (!lsm_is_enabled(lsm))
32827be5600SPaul Moore 		return;
32927be5600SPaul Moore 
3305137e583SPaul Moore 	lsm_pr_dbg("initializing %s\n", lsm->id->name);
33167a4b6a8SPaul Moore 	ret = lsm->init();
3329f9dc69eSPaul Moore 	WARN(ret, "%s failed to initialize: %d\n", lsm->id->name, ret);
33367a4b6a8SPaul Moore }
33467a4b6a8SPaul Moore 
335752db065SPaul Moore /**
33645070533SPaul Moore  * lsm_static_call_init - Initialize a LSM's static calls
33745070533SPaul Moore  * @hl: LSM hook list
33845070533SPaul Moore  */
3395137e583SPaul Moore static int __init lsm_static_call_init(struct security_hook_list *hl)
34067a4b6a8SPaul Moore {
34145a41d13SPaul Moore 	struct lsm_static_call *scall = hl->scalls;
34245a41d13SPaul Moore 	int i;
34345a41d13SPaul Moore 
34445a41d13SPaul Moore 	for (i = 0; i < MAX_LSM_COUNT; i++) {
34545a41d13SPaul Moore 		/* Update the first static call that is not used yet */
34645a41d13SPaul Moore 		if (!scall->hl) {
34745a41d13SPaul Moore 			__static_call_update(scall->key, scall->trampoline,
34845a41d13SPaul Moore 					     hl->hook.lsm_func_addr);
34945a41d13SPaul Moore 			scall->hl = hl;
35045a41d13SPaul Moore 			static_branch_enable(scall->active);
3515137e583SPaul Moore 			return 0;
35245a41d13SPaul Moore 		}
35345a41d13SPaul Moore 		scall++;
35445a41d13SPaul Moore 	}
3555137e583SPaul Moore 
3565137e583SPaul Moore 	return -ENOSPC;
35745a41d13SPaul Moore }
35845a41d13SPaul Moore 
35945a41d13SPaul Moore /**
36045070533SPaul Moore  * security_add_hooks - Add a LSM's hooks to the LSM framework's hook lists
36145070533SPaul Moore  * @hooks: LSM hooks to add
36245070533SPaul Moore  * @count: number of hooks to add
36345070533SPaul Moore  * @lsmid: identification information for the LSM
36445a41d13SPaul Moore  *
36545070533SPaul Moore  * Each LSM has to register its hooks with the LSM framework.
36645a41d13SPaul Moore  */
36745a41d13SPaul Moore void __init security_add_hooks(struct security_hook_list *hooks, int count,
36845a41d13SPaul Moore 			       const struct lsm_id *lsmid)
36945a41d13SPaul Moore {
37045a41d13SPaul Moore 	int i;
37145a41d13SPaul Moore 
37245a41d13SPaul Moore 	for (i = 0; i < count; i++) {
37345a41d13SPaul Moore 		hooks[i].lsmid = lsmid;
3745137e583SPaul Moore 		if (lsm_static_call_init(&hooks[i]))
3755137e583SPaul Moore 			panic("exhausted LSM callback slots with LSM %s\n",
3765137e583SPaul Moore 			      lsmid->name);
37745a41d13SPaul Moore 	}
37845a41d13SPaul Moore }
37945a41d13SPaul Moore 
38045070533SPaul Moore /**
38145070533SPaul Moore  * early_security_init - Initialize the early LSMs
38245070533SPaul Moore  */
38345a41d13SPaul Moore int __init early_security_init(void)
38445a41d13SPaul Moore {
38545a41d13SPaul Moore 	struct lsm_info *lsm;
38645a41d13SPaul Moore 
387ac3c47ceSPaul Moore 	/* NOTE: lsm_pr_dbg() doesn't work here as lsm_debug is not yet set */
388ac3c47ceSPaul Moore 
38945a41d13SPaul Moore 	lsm_early_for_each_raw(lsm) {
39045a41d13SPaul Moore 		lsm_enabled_set(lsm, true);
39145a41d13SPaul Moore 		lsm_order_append(lsm, "early");
39245a41d13SPaul Moore 		lsm_prepare(lsm);
39345a41d13SPaul Moore 		lsm_init_single(lsm);
39445a41d13SPaul Moore 		lsm_count_early++;
39545a41d13SPaul Moore 	}
39645a41d13SPaul Moore 
39745a41d13SPaul Moore 	return 0;
39845a41d13SPaul Moore }
39945a41d13SPaul Moore 
40045a41d13SPaul Moore /**
40145a41d13SPaul Moore  * security_init - Initializes the LSM framework
40245a41d13SPaul Moore  *
40345a41d13SPaul Moore  * This should be called early in the kernel initialization sequence.
40445a41d13SPaul Moore  */
40545a41d13SPaul Moore int __init security_init(void)
40645a41d13SPaul Moore {
40745a41d13SPaul Moore 	unsigned int cnt;
40867a4b6a8SPaul Moore 	struct lsm_info **lsm;
40945a41d13SPaul Moore 
4105137e583SPaul Moore 	if (lsm_debug) {
411ac3c47ceSPaul Moore 		struct lsm_info *i;
412ac3c47ceSPaul Moore 
413ac3c47ceSPaul Moore 		cnt = 0;
414ac3c47ceSPaul Moore 		lsm_pr("available LSMs: ");
415ac3c47ceSPaul Moore 		lsm_early_for_each_raw(i)
416ac3c47ceSPaul Moore 			lsm_pr_cont("%s%s(E)", (cnt++ ? "," : ""), i->id->name);
417ac3c47ceSPaul Moore 		lsm_for_each_raw(i)
418ac3c47ceSPaul Moore 			lsm_pr_cont("%s%s", (cnt++ ? "," : ""), i->id->name);
419ac3c47ceSPaul Moore 		lsm_pr_cont("\n");
420ac3c47ceSPaul Moore 
421ac3c47ceSPaul Moore 		lsm_pr("built-in LSM config: %s\n", lsm_order_builtin);
422ac3c47ceSPaul Moore 
4235137e583SPaul Moore 		lsm_pr("legacy LSM parameter: %s\n", lsm_order_legacy);
4245137e583SPaul Moore 		lsm_pr("boot LSM parameter: %s\n", lsm_order_cmdline);
425ac3c47ceSPaul Moore 
426ac3c47ceSPaul Moore 		/* see the note about lsm_pr_dbg() in early_security_init() */
427ac3c47ceSPaul Moore 		lsm_early_for_each_raw(i)
428ac3c47ceSPaul Moore 			lsm_pr("enabled LSM early:%s\n", i->id->name);
4295137e583SPaul Moore 	}
43067a4b6a8SPaul Moore 
431592b104fSPaul Moore 	if (lsm_order_cmdline) {
4325137e583SPaul Moore 		if (lsm_order_legacy)
433592b104fSPaul Moore 			lsm_order_legacy = NULL;
434752db065SPaul Moore 		lsm_order_parse(lsm_order_cmdline, "cmdline");
43567a4b6a8SPaul Moore 	} else
436752db065SPaul Moore 		lsm_order_parse(lsm_order_builtin, "builtin");
43767a4b6a8SPaul Moore 
43845a41d13SPaul Moore 	lsm_order_for_each(lsm)
439e0257856SPaul Moore 		lsm_prepare(*lsm);
44067a4b6a8SPaul Moore 
4415137e583SPaul Moore 	if (lsm_debug) {
4425137e583SPaul Moore 		lsm_pr("blob(cred) size %d\n", blob_sizes.lbs_cred);
4435137e583SPaul Moore 		lsm_pr("blob(file) size %d\n", blob_sizes.lbs_file);
4445137e583SPaul Moore 		lsm_pr("blob(ib) size %d\n", blob_sizes.lbs_ib);
4455137e583SPaul Moore 		lsm_pr("blob(inode) size %d\n", blob_sizes.lbs_inode);
4465137e583SPaul Moore 		lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc);
4475137e583SPaul Moore 		lsm_pr("blob(key) size %d\n", blob_sizes.lbs_key);
4485137e583SPaul Moore 		lsm_pr("blob(msg_msg)_size %d\n", blob_sizes.lbs_msg_msg);
4495137e583SPaul Moore 		lsm_pr("blob(sock) size %d\n", blob_sizes.lbs_sock);
4505137e583SPaul Moore 		lsm_pr("blob(superblock) size %d\n", blob_sizes.lbs_superblock);
4515137e583SPaul Moore 		lsm_pr("blob(perf_event) size %d\n", blob_sizes.lbs_perf_event);
4525137e583SPaul Moore 		lsm_pr("blob(task) size %d\n", blob_sizes.lbs_task);
4535137e583SPaul Moore 		lsm_pr("blob(tun_dev) size %d\n", blob_sizes.lbs_tun_dev);
4545137e583SPaul Moore 		lsm_pr("blob(xattr) count %d\n", blob_sizes.lbs_xattr_count);
4555137e583SPaul Moore 		lsm_pr("blob(bdev) size %d\n", blob_sizes.lbs_bdev);
4565137e583SPaul Moore 		lsm_pr("blob(bpf_map) size %d\n", blob_sizes.lbs_bpf_map);
4575137e583SPaul Moore 		lsm_pr("blob(bpf_prog) size %d\n", blob_sizes.lbs_bpf_prog);
4585137e583SPaul Moore 		lsm_pr("blob(bpf_token) size %d\n", blob_sizes.lbs_bpf_token);
459cb1513dbSPaul Moore 	}
46067a4b6a8SPaul Moore 
46167a4b6a8SPaul Moore 	if (blob_sizes.lbs_file)
46267a4b6a8SPaul Moore 		lsm_file_cache = kmem_cache_create("lsm_file_cache",
46367a4b6a8SPaul Moore 						   blob_sizes.lbs_file, 0,
46467a4b6a8SPaul Moore 						   SLAB_PANIC, NULL);
46567a4b6a8SPaul Moore 	if (blob_sizes.lbs_inode)
46667a4b6a8SPaul Moore 		lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
46767a4b6a8SPaul Moore 						    blob_sizes.lbs_inode, 0,
46867a4b6a8SPaul Moore 						    SLAB_PANIC, NULL);
46967a4b6a8SPaul Moore 
47092ed3500SPaul Moore 	if (lsm_cred_alloc((struct cred __rcu *)current->cred, GFP_KERNEL))
4715137e583SPaul Moore 		panic("early LSM cred alloc failed\n");
47292ed3500SPaul Moore 	if (lsm_task_alloc(current))
4735137e583SPaul Moore 		panic("early LSM task alloc failed\n");
47492ed3500SPaul Moore 
47545a41d13SPaul Moore 	cnt = 0;
47637f788f6SPaul Moore 	lsm_order_for_each(lsm) {
47745a41d13SPaul Moore 		/* skip the "early" LSMs as they have already been setup */
47845a41d13SPaul Moore 		if (cnt++ < lsm_count_early)
47945a41d13SPaul Moore 			continue;
48027be5600SPaul Moore 		lsm_init_single(*lsm);
48167a4b6a8SPaul Moore 	}
48267a4b6a8SPaul Moore 
48367a4b6a8SPaul Moore 	return 0;
48467a4b6a8SPaul Moore }
485*cdc02881SPaul Moore 
486*cdc02881SPaul Moore /**
487*cdc02881SPaul Moore  * security_initcall_pure - Run the LSM pure initcalls
488*cdc02881SPaul Moore  */
489*cdc02881SPaul Moore static int __init security_initcall_pure(void)
490*cdc02881SPaul Moore {
491*cdc02881SPaul Moore 	return lsm_initcall(pure);
492*cdc02881SPaul Moore }
493*cdc02881SPaul Moore pure_initcall(security_initcall_pure);
494*cdc02881SPaul Moore 
495*cdc02881SPaul Moore /**
496*cdc02881SPaul Moore  * security_initcall_early - Run the LSM early initcalls
497*cdc02881SPaul Moore  */
498*cdc02881SPaul Moore static int __init security_initcall_early(void)
499*cdc02881SPaul Moore {
500*cdc02881SPaul Moore 	return lsm_initcall(early);
501*cdc02881SPaul Moore }
502*cdc02881SPaul Moore early_initcall(security_initcall_early);
503*cdc02881SPaul Moore 
504*cdc02881SPaul Moore /**
505*cdc02881SPaul Moore  * security_initcall_core - Run the LSM core initcalls
506*cdc02881SPaul Moore  */
507*cdc02881SPaul Moore static int __init security_initcall_core(void)
508*cdc02881SPaul Moore {
509*cdc02881SPaul Moore 	return lsm_initcall(core);
510*cdc02881SPaul Moore }
511*cdc02881SPaul Moore core_initcall(security_initcall_core);
512*cdc02881SPaul Moore 
513*cdc02881SPaul Moore /**
514*cdc02881SPaul Moore  * security_initcall_subsys - Run the LSM subsys initcalls
515*cdc02881SPaul Moore  */
516*cdc02881SPaul Moore static int __init security_initcall_subsys(void)
517*cdc02881SPaul Moore {
518*cdc02881SPaul Moore 	return lsm_initcall(subsys);
519*cdc02881SPaul Moore }
520*cdc02881SPaul Moore subsys_initcall(security_initcall_subsys);
521*cdc02881SPaul Moore 
522*cdc02881SPaul Moore /**
523*cdc02881SPaul Moore  * security_initcall_fs - Run the LSM fs initcalls
524*cdc02881SPaul Moore  */
525*cdc02881SPaul Moore static int __init security_initcall_fs(void)
526*cdc02881SPaul Moore {
527*cdc02881SPaul Moore 	return lsm_initcall(fs);
528*cdc02881SPaul Moore }
529*cdc02881SPaul Moore fs_initcall(security_initcall_fs);
530*cdc02881SPaul Moore 
531*cdc02881SPaul Moore /**
532*cdc02881SPaul Moore  * security_initcall_device - Run the LSM device initcalls
533*cdc02881SPaul Moore  */
534*cdc02881SPaul Moore static int __init security_initcall_device(void)
535*cdc02881SPaul Moore {
536*cdc02881SPaul Moore 	return lsm_initcall(device);
537*cdc02881SPaul Moore }
538*cdc02881SPaul Moore device_initcall(security_initcall_device);
539*cdc02881SPaul Moore 
540*cdc02881SPaul Moore /**
541*cdc02881SPaul Moore  * security_initcall_late - Run the LSM late initcalls
542*cdc02881SPaul Moore  */
543*cdc02881SPaul Moore static int __init security_initcall_late(void)
544*cdc02881SPaul Moore {
545*cdc02881SPaul Moore 	int rc;
546*cdc02881SPaul Moore 
547*cdc02881SPaul Moore 	rc = lsm_initcall(late);
548*cdc02881SPaul Moore 	lsm_pr_dbg("all enabled LSMs fully activated\n");
549*cdc02881SPaul Moore 
550*cdc02881SPaul Moore 	return rc;
551*cdc02881SPaul Moore }
552*cdc02881SPaul Moore late_initcall(security_initcall_late);
553