Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+117 -5
+28 -5
include/linux/lsm_hooks.h
··· 151 151 LSM_ORDER_LAST = 1, /* This is only for integrity. */ 152 152 }; 153 153 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 + */ 154 170 struct lsm_info { 155 171 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); 161 184 }; 162 185 163 186 #define DEFINE_LSM(lsm) \
+89
security/lsm_init.c
··· 39 39 for ((iter) = __start_early_lsm_info; \ 40 40 (iter) < __end_early_lsm_info; (iter)++) 41 41 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 + 42 63 /** 43 64 * lsm_choose_security - Legacy "major" LSM selection 44 65 * @str: kernel command line parameter ··· 482 461 483 462 return 0; 484 463 } 464 + 465 + /** 466 + * security_initcall_pure - Run the LSM pure initcalls 467 + */ 468 + static int __init security_initcall_pure(void) 469 + { 470 + return lsm_initcall(pure); 471 + } 472 + pure_initcall(security_initcall_pure); 473 + 474 + /** 475 + * security_initcall_early - Run the LSM early initcalls 476 + */ 477 + static int __init security_initcall_early(void) 478 + { 479 + return lsm_initcall(early); 480 + } 481 + early_initcall(security_initcall_early); 482 + 483 + /** 484 + * security_initcall_core - Run the LSM core initcalls 485 + */ 486 + static int __init security_initcall_core(void) 487 + { 488 + return lsm_initcall(core); 489 + } 490 + core_initcall(security_initcall_core); 491 + 492 + /** 493 + * security_initcall_subsys - Run the LSM subsys initcalls 494 + */ 495 + static int __init security_initcall_subsys(void) 496 + { 497 + return lsm_initcall(subsys); 498 + } 499 + subsys_initcall(security_initcall_subsys); 500 + 501 + /** 502 + * security_initcall_fs - Run the LSM fs initcalls 503 + */ 504 + static int __init security_initcall_fs(void) 505 + { 506 + return lsm_initcall(fs); 507 + } 508 + fs_initcall(security_initcall_fs); 509 + 510 + /** 511 + * security_initcall_device - Run the LSM device initcalls 512 + */ 513 + static int __init security_initcall_device(void) 514 + { 515 + return lsm_initcall(device); 516 + } 517 + device_initcall(security_initcall_device); 518 + 519 + /** 520 + * security_initcall_late - Run the LSM late initcalls 521 + */ 522 + static int __init security_initcall_late(void) 523 + { 524 + int rc; 525 + 526 + rc = lsm_initcall(late); 527 + lsm_pr_dbg("all enabled LSMs fully activated\n"); 528 + 529 + return rc; 530 + } 531 + late_initcall(security_initcall_late);