[RFC PATCH 03/29] lsm: simplify prepare_lsm() and rename to lsm_prep_single()
Kees Cook
kees at kernel.org
Wed Apr 9 21:30:44 UTC 2025
On Wed, Apr 09, 2025 at 02:49:48PM -0400, Paul Moore wrote:
> One part of a larger effort to cleanup the LSM framework initialization
> code.
This commit log needs improvement. i.e. explain what and why:
The execution flow through lsm_allowed(), prepare_lsm(), and
lsm_set_blob_sizes() is a bit convoluted. Merge the logic of all three
into a single new function, lsm_prep_single().
>
> Signed-off-by: Paul Moore <paul at paul-moore.com>
> ---
> security/lsm_init.c | 103 ++++++++++++++++++--------------------------
> 1 file changed, 43 insertions(+), 60 deletions(-)
>
> diff --git a/security/lsm_init.c b/security/lsm_init.c
> index 70e7d4207dae..dffa8dc2da36 100644
> --- a/security/lsm_init.c
> +++ b/security/lsm_init.c
> @@ -123,22 +123,6 @@ static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
> is_enabled(lsm) ? "enabled" : "disabled");
> }
>
> -/* Is an LSM allowed to be initialized? */
> -static bool __init lsm_allowed(struct lsm_info *lsm)
> -{
> - /* Skip if the LSM is disabled. */
> - if (!is_enabled(lsm))
> - return false;
> -
> - /* Not allowed if another exclusive LSM already initialized. */
> - if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) {
> - init_debug("exclusive disabled: %s\n", lsm->name);
> - return false;
> - }
> -
> - return true;
> -}
> -
> static void __init lsm_set_blob_size(int *need, int *lbs)
> {
> int offset;
> @@ -151,51 +135,50 @@ static void __init lsm_set_blob_size(int *need, int *lbs)
> *need = offset;
> }
>
> -static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
> +/**
> + * lsm_prep_single - Prepare the LSM framework for a new LSM
> + * @lsm: LSM definition
> + */
> +static void __init lsm_prep_single(struct lsm_info *lsm)
Nit-pick on naming: why shorten "prepare"?
> {
> - if (!needed)
> + struct lsm_blob_sizes *blobs;
> +
> + if (!is_enabled(lsm)) {
> + set_enabled(lsm, false);
> + return;
> + } else if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) {
> + init_debug("exclusive disabled: %s\n", lsm->name);
> + set_enabled(lsm, false);
> return;
> -
> - lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
> - lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file);
> - lsm_set_blob_size(&needed->lbs_ib, &blob_sizes.lbs_ib);
> - /*
> - * The inode blob gets an rcu_head in addition to
> - * what the modules might need.
> - */
> - if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
> - blob_sizes.lbs_inode = sizeof(struct rcu_head);
> - lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
> - lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
> - lsm_set_blob_size(&needed->lbs_key, &blob_sizes.lbs_key);
> - lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
> - lsm_set_blob_size(&needed->lbs_perf_event, &blob_sizes.lbs_perf_event);
> - lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
> - lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
> - lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
> - lsm_set_blob_size(&needed->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
> - lsm_set_blob_size(&needed->lbs_xattr_count,
> - &blob_sizes.lbs_xattr_count);
> - lsm_set_blob_size(&needed->lbs_bdev, &blob_sizes.lbs_bdev);
> -}
> -
> -/* Prepare LSM for initialization. */
> -static void __init prepare_lsm(struct lsm_info *lsm)
> -{
> - int enabled = lsm_allowed(lsm);
> -
> - /* Record enablement (to handle any following exclusive LSMs). */
> - set_enabled(lsm, enabled);
> -
> - /* If enabled, do pre-initialization work. */
> - if (enabled) {
> - if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) {
> - exclusive = lsm;
> - init_debug("exclusive chosen: %s\n", lsm->name);
> - }
> -
> - lsm_set_blob_sizes(lsm->blobs);
> }
> +
> + /* Mark the LSM as enabled. */
> + set_enabled(lsm, true);
> + if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) {
> + init_debug("exclusive chosen: %s\n", lsm->name);
> + exclusive = lsm;
> + }
> +
> + /* Register the LSM blob sizes. */
> + blobs = lsm->blobs;
> + lsm_set_blob_size(&blobs->lbs_cred, &blob_sizes.lbs_cred);
> + lsm_set_blob_size(&blobs->lbs_file, &blob_sizes.lbs_file);
> + lsm_set_blob_size(&blobs->lbs_ib, &blob_sizes.lbs_ib);
> + /* inode blob gets an rcu_head in addition to LSM blobs. */
> + if (blobs->lbs_inode && blob_sizes.lbs_inode == 0)
> + blob_sizes.lbs_inode = sizeof(struct rcu_head);
> + lsm_set_blob_size(&blobs->lbs_inode, &blob_sizes.lbs_inode);
> + lsm_set_blob_size(&blobs->lbs_ipc, &blob_sizes.lbs_ipc);
> + lsm_set_blob_size(&blobs->lbs_key, &blob_sizes.lbs_key);
> + lsm_set_blob_size(&blobs->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
> + lsm_set_blob_size(&blobs->lbs_perf_event, &blob_sizes.lbs_perf_event);
> + lsm_set_blob_size(&blobs->lbs_sock, &blob_sizes.lbs_sock);
> + lsm_set_blob_size(&blobs->lbs_superblock, &blob_sizes.lbs_superblock);
> + lsm_set_blob_size(&blobs->lbs_task, &blob_sizes.lbs_task);
> + lsm_set_blob_size(&blobs->lbs_tun_dev, &blob_sizes.lbs_tun_dev);
> + lsm_set_blob_size(&blobs->lbs_xattr_count,
> + &blob_sizes.lbs_xattr_count);
> + lsm_set_blob_size(&blobs->lbs_bdev, &blob_sizes.lbs_bdev);
Another refactoring idea I saw recently from the sysctl subsystem was
turning these named "same things" into an array with enum names, so
instead of &blobs->lbs_ipc, &blobs->lbs_key, they can still have useful
names but also be iterated in a loop:
enum lsm_blob_types {
LSM_BLOB_IPC,
LSM_BLOB_KEY,
...
LSM_BLOB_MAX
};
...
for (i = 0; i < ARRAY_SIZE(blobs->lbs); i++) {
lsm_set_blob_size(&blobs->lbs[i], &blob_sizes[i]);
> }
>
> /* Initialize a given LSM, if it is enabled. */
> @@ -358,7 +341,7 @@ static void __init ordered_lsm_init(void)
> ordered_lsm_parse(builtin_lsm_order, "builtin");
>
> for (lsm = ordered_lsms; *lsm; lsm++)
> - prepare_lsm(*lsm);
> + lsm_prep_single(*lsm);
>
> report_lsm_order();
>
> @@ -499,7 +482,7 @@ int __init early_security_init(void)
> for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) {
> if (!lsm->enabled)
> lsm->enabled = &lsm_enabled_true;
> - prepare_lsm(lsm);
> + lsm_prep_single(lsm);
> initialize_lsm(lsm);
> }
Regardless, this looks correct to me. With or without renaming the
function:
Reviewed-by: Kees Cook <kees at kernel.org>
--
Kees Cook
More information about the Linux-security-module-archive
mailing list