Skip to content

Commit cdc0288

Browse files
committed
lsm: introduce an initcall mechanism into the LSM framework
Currently the individual LSMs register their own initcalls, and while this should be harmless, it can be wasteful in the case where a LSM is disabled at boot as the initcall will still be executed. This patch introduces support for managing the initcalls in the LSM framework, and future patches will convert the existing LSMs over to this new mechanism. Only initcall types which are used by the current in-tree LSMs are supported, additional initcall types can easily be added in the future if needed. Reviewed-by: Kees Cook <kees@kernel.org> Reviewed-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: John Johansen <john.johhansen@canonical.com> Reviewed-by: Mimi Zohar <zohar@linux.ibm.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent 3423c63 commit cdc0288

File tree

2 files changed

+117
-5
lines changed

2 files changed

+117
-5
lines changed

include/linux/lsm_hooks.h

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,36 @@ enum lsm_order {
151151
LSM_ORDER_LAST = 1, /* This is only for integrity. */
152152
};
153153

154+
/**
155+
* struct lsm_info - Define an individual LSM for the LSM framework.
156+
* @id: LSM name/ID info
157+
* @order: ordering with respect to other LSMs, optional
158+
* @flags: descriptive flags, optional
159+
* @blobs: LSM blob sharing, optional
160+
* @enabled: controlled by CONFIG_LSM, optional
161+
* @init: LSM specific initialization routine
162+
* @initcall_pure: LSM callback for initcall_pure() setup, optional
163+
* @initcall_early: LSM callback for early_initcall setup, optional
164+
* @initcall_core: LSM callback for core_initcall() setup, optional
165+
* @initcall_subsys: LSM callback for subsys_initcall() setup, optional
166+
* @initcall_fs: LSM callback for fs_initcall setup, optional
167+
* @nitcall_device: LSM callback for device_initcall() setup, optional
168+
* @initcall_late: LSM callback for late_initcall() setup, optional
169+
*/
154170
struct lsm_info {
155171
const struct lsm_id *id;
156-
enum lsm_order order; /* Optional: default is LSM_ORDER_MUTABLE */
157-
unsigned long flags; /* Optional: flags describing LSM */
158-
int *enabled; /* Optional: controlled by CONFIG_LSM */
159-
int (*init)(void); /* Required. */
160-
struct lsm_blob_sizes *blobs; /* Optional: for blob sharing. */
172+
enum lsm_order order;
173+
unsigned long flags;
174+
struct lsm_blob_sizes *blobs;
175+
int *enabled;
176+
int (*init)(void);
177+
int (*initcall_pure)(void);
178+
int (*initcall_early)(void);
179+
int (*initcall_core)(void);
180+
int (*initcall_subsys)(void);
181+
int (*initcall_fs)(void);
182+
int (*initcall_device)(void);
183+
int (*initcall_late)(void);
161184
};
162185

163186
#define DEFINE_LSM(lsm) \

security/lsm_init.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,27 @@ static __initdata struct lsm_info *lsm_exclusive;
3939
for ((iter) = __start_early_lsm_info; \
4040
(iter) < __end_early_lsm_info; (iter)++)
4141

42+
#define lsm_initcall(level) \
43+
({ \
44+
int _r, _rc = 0; \
45+
struct lsm_info **_lp, *_l; \
46+
lsm_order_for_each(_lp) { \
47+
_l = *_lp; \
48+
if (!_l->initcall_##level) \
49+
continue; \
50+
lsm_pr_dbg("running %s %s initcall", \
51+
_l->id->name, #level); \
52+
_r = _l->initcall_##level(); \
53+
if (_r) { \
54+
pr_warn("failed LSM %s %s initcall with errno %d\n", \
55+
_l->id->name, #level, _r); \
56+
if (!_rc) \
57+
_rc = _r; \
58+
} \
59+
} \
60+
_rc; \
61+
})
62+
4263
/**
4364
* lsm_choose_security - Legacy "major" LSM selection
4465
* @str: kernel command line parameter
@@ -461,3 +482,71 @@ int __init security_init(void)
461482

462483
return 0;
463484
}
485+
486+
/**
487+
* security_initcall_pure - Run the LSM pure initcalls
488+
*/
489+
static int __init security_initcall_pure(void)
490+
{
491+
return lsm_initcall(pure);
492+
}
493+
pure_initcall(security_initcall_pure);
494+
495+
/**
496+
* security_initcall_early - Run the LSM early initcalls
497+
*/
498+
static int __init security_initcall_early(void)
499+
{
500+
return lsm_initcall(early);
501+
}
502+
early_initcall(security_initcall_early);
503+
504+
/**
505+
* security_initcall_core - Run the LSM core initcalls
506+
*/
507+
static int __init security_initcall_core(void)
508+
{
509+
return lsm_initcall(core);
510+
}
511+
core_initcall(security_initcall_core);
512+
513+
/**
514+
* security_initcall_subsys - Run the LSM subsys initcalls
515+
*/
516+
static int __init security_initcall_subsys(void)
517+
{
518+
return lsm_initcall(subsys);
519+
}
520+
subsys_initcall(security_initcall_subsys);
521+
522+
/**
523+
* security_initcall_fs - Run the LSM fs initcalls
524+
*/
525+
static int __init security_initcall_fs(void)
526+
{
527+
return lsm_initcall(fs);
528+
}
529+
fs_initcall(security_initcall_fs);
530+
531+
/**
532+
* security_initcall_device - Run the LSM device initcalls
533+
*/
534+
static int __init security_initcall_device(void)
535+
{
536+
return lsm_initcall(device);
537+
}
538+
device_initcall(security_initcall_device);
539+
540+
/**
541+
* security_initcall_late - Run the LSM late initcalls
542+
*/
543+
static int __init security_initcall_late(void)
544+
{
545+
int rc;
546+
547+
rc = lsm_initcall(late);
548+
lsm_pr_dbg("all enabled LSMs fully activated\n");
549+
550+
return rc;
551+
}
552+
late_initcall(security_initcall_late);

0 commit comments

Comments
 (0)