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
42cdc02881SPaul Moore #define lsm_initcall(level) \
43cdc02881SPaul Moore ({ \
44cdc02881SPaul Moore int _r, _rc = 0; \
45cdc02881SPaul Moore struct lsm_info **_lp, *_l; \
46cdc02881SPaul Moore lsm_order_for_each(_lp) { \
47cdc02881SPaul Moore _l = *_lp; \
48cdc02881SPaul Moore if (!_l->initcall_##level) \
49cdc02881SPaul Moore continue; \
50cdc02881SPaul Moore lsm_pr_dbg("running %s %s initcall", \
51cdc02881SPaul Moore _l->id->name, #level); \
52cdc02881SPaul Moore _r = _l->initcall_##level(); \
53cdc02881SPaul Moore if (_r) { \
54cdc02881SPaul Moore pr_warn("failed LSM %s %s initcall with errno %d\n", \
55cdc02881SPaul Moore _l->id->name, #level, _r); \
56cdc02881SPaul Moore if (!_rc) \
57cdc02881SPaul Moore _rc = _r; \
58cdc02881SPaul Moore } \
59cdc02881SPaul Moore } \
60cdc02881SPaul Moore _rc; \
61cdc02881SPaul Moore })
62cdc02881SPaul Moore
63592b104fSPaul Moore /**
64592b104fSPaul Moore * lsm_choose_security - Legacy "major" LSM selection
65592b104fSPaul Moore * @str: kernel command line parameter
66592b104fSPaul Moore */
lsm_choose_security(char * str)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 */
lsm_choose_lsm(char * str)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 */
lsm_debug_enable(char * str)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 */
lsm_enabled_set(struct lsm_info * lsm,bool enabled)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 */
lsm_is_enabled(struct lsm_info * lsm)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 */
lsm_order_exists(struct lsm_info * lsm)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 */
lsm_order_append(struct lsm_info * lsm,const char * src)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 */
lsm_order_parse(const char * list,const char * src)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 */
lsm_blob_size_update(unsigned int * sz_req,unsigned int * sz_cur)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 */
lsm_prepare(struct lsm_info * lsm)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 */
lsm_init_single(struct lsm_info * lsm)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 */
lsm_static_call_init(struct security_hook_list * hl)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 */
security_add_hooks(struct security_hook_list * hooks,int count,const struct lsm_id * lsmid)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 */
early_security_init(void)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 */
security_init(void)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
470*9a948eefSPaul Moore if (lsm_cred_alloc((struct cred *)unrcu_pointer(current->cred),
471*9a948eefSPaul Moore GFP_KERNEL))
4725137e583SPaul Moore panic("early LSM cred alloc failed\n");
47392ed3500SPaul Moore if (lsm_task_alloc(current))
4745137e583SPaul Moore panic("early LSM task alloc failed\n");
47592ed3500SPaul Moore
47645a41d13SPaul Moore cnt = 0;
47737f788f6SPaul Moore lsm_order_for_each(lsm) {
47845a41d13SPaul Moore /* skip the "early" LSMs as they have already been setup */
47945a41d13SPaul Moore if (cnt++ < lsm_count_early)
48045a41d13SPaul Moore continue;
48127be5600SPaul Moore lsm_init_single(*lsm);
48267a4b6a8SPaul Moore }
48367a4b6a8SPaul Moore
48467a4b6a8SPaul Moore return 0;
48567a4b6a8SPaul Moore }
486cdc02881SPaul Moore
487cdc02881SPaul Moore /**
488cdc02881SPaul Moore * security_initcall_pure - Run the LSM pure initcalls
489cdc02881SPaul Moore */
security_initcall_pure(void)490cdc02881SPaul Moore static int __init security_initcall_pure(void)
491cdc02881SPaul Moore {
4924ab5efccSPaul Moore int rc_adr, rc_lsm;
4934ab5efccSPaul Moore
4944ab5efccSPaul Moore rc_adr = min_addr_init();
4954ab5efccSPaul Moore rc_lsm = lsm_initcall(pure);
4964ab5efccSPaul Moore
4974ab5efccSPaul Moore return (rc_adr ? rc_adr : rc_lsm);
498cdc02881SPaul Moore }
499cdc02881SPaul Moore pure_initcall(security_initcall_pure);
500cdc02881SPaul Moore
501cdc02881SPaul Moore /**
502cdc02881SPaul Moore * security_initcall_early - Run the LSM early initcalls
503cdc02881SPaul Moore */
security_initcall_early(void)504cdc02881SPaul Moore static int __init security_initcall_early(void)
505cdc02881SPaul Moore {
506cdc02881SPaul Moore return lsm_initcall(early);
507cdc02881SPaul Moore }
508cdc02881SPaul Moore early_initcall(security_initcall_early);
509cdc02881SPaul Moore
510cdc02881SPaul Moore /**
511cdc02881SPaul Moore * security_initcall_core - Run the LSM core initcalls
512cdc02881SPaul Moore */
security_initcall_core(void)513cdc02881SPaul Moore static int __init security_initcall_core(void)
514cdc02881SPaul Moore {
5154ab5efccSPaul Moore int rc_sfs, rc_lsm;
5164ab5efccSPaul Moore
5174ab5efccSPaul Moore rc_sfs = securityfs_init();
5184ab5efccSPaul Moore rc_lsm = lsm_initcall(core);
5194ab5efccSPaul Moore
5204ab5efccSPaul Moore return (rc_sfs ? rc_sfs : rc_lsm);
521cdc02881SPaul Moore }
522cdc02881SPaul Moore core_initcall(security_initcall_core);
523cdc02881SPaul Moore
524cdc02881SPaul Moore /**
525cdc02881SPaul Moore * security_initcall_subsys - Run the LSM subsys initcalls
526cdc02881SPaul Moore */
security_initcall_subsys(void)527cdc02881SPaul Moore static int __init security_initcall_subsys(void)
528cdc02881SPaul Moore {
529cdc02881SPaul Moore return lsm_initcall(subsys);
530cdc02881SPaul Moore }
531cdc02881SPaul Moore subsys_initcall(security_initcall_subsys);
532cdc02881SPaul Moore
533cdc02881SPaul Moore /**
534cdc02881SPaul Moore * security_initcall_fs - Run the LSM fs initcalls
535cdc02881SPaul Moore */
security_initcall_fs(void)536cdc02881SPaul Moore static int __init security_initcall_fs(void)
537cdc02881SPaul Moore {
538cdc02881SPaul Moore return lsm_initcall(fs);
539cdc02881SPaul Moore }
540cdc02881SPaul Moore fs_initcall(security_initcall_fs);
541cdc02881SPaul Moore
542cdc02881SPaul Moore /**
543cdc02881SPaul Moore * security_initcall_device - Run the LSM device initcalls
544cdc02881SPaul Moore */
security_initcall_device(void)545cdc02881SPaul Moore static int __init security_initcall_device(void)
546cdc02881SPaul Moore {
547cdc02881SPaul Moore return lsm_initcall(device);
548cdc02881SPaul Moore }
549cdc02881SPaul Moore device_initcall(security_initcall_device);
550cdc02881SPaul Moore
551cdc02881SPaul Moore /**
552cdc02881SPaul Moore * security_initcall_late - Run the LSM late initcalls
553cdc02881SPaul Moore */
security_initcall_late(void)554cdc02881SPaul Moore static int __init security_initcall_late(void)
555cdc02881SPaul Moore {
556cdc02881SPaul Moore int rc;
557cdc02881SPaul Moore
558cdc02881SPaul Moore rc = lsm_initcall(late);
559cdc02881SPaul Moore lsm_pr_dbg("all enabled LSMs fully activated\n");
560dfa024bcSPaul Moore call_blocking_lsm_notifier(LSM_STARTED_ALL, NULL);
561cdc02881SPaul Moore
562cdc02881SPaul Moore return rc;
563cdc02881SPaul Moore }
564cdc02881SPaul Moore late_initcall(security_initcall_late);
565