Merge tag 'lsm-pr-20250926' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm

Pull lsm updates from Paul Moore:

 - Move the management of the LSM BPF security blobs into the framework

   In order to enable multiple LSMs we need to allocate and free the
   various security blobs in the LSM framework and not the individual
   LSMs as they would end up stepping all over each other.

 - Leverage the lsm_bdev_alloc() helper in lsm_bdev_alloc()

   Make better use of our existing helper functions to reduce some code
   duplication.

 - Update the Rust cred code to use 'sync::aref'

   Part of a larger effort to move the Rust code over to the 'sync'
   module.

 - Make CONFIG_LSM dependent on CONFIG_SECURITY

   As the CONFIG_LSM Kconfig setting is an ordered list of the LSMs to
   enable a boot, it obviously doesn't make much sense to enable this
   when CONFIG_SECURITY is disabled.

 - Update the LSM and CREDENTIALS sections in MAINTAINERS with Rusty
   bits

   Add the Rust helper files to the associated LSM and CREDENTIALS
   entries int the MAINTAINERS file. We're trying to improve the
   communication between the two groups and making sure we're all aware
   of what is going on via cross-posting to the relevant lists is a good
   way to start.

* tag 'lsm-pr-20250926' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm:
  lsm: CONFIG_LSM can depend on CONFIG_SECURITY
  MAINTAINERS: add the associated Rust helper to the CREDENTIALS section
  MAINTAINERS: add the associated Rust helper to the LSM section
  rust,cred: update AlwaysRefCounted import to sync::aref
  security: use umax() to improve code
  lsm,selinux: Add LSM blob support for BPF objects
  lsm: use lsm_blob_alloc() in lsm_bdev_alloc()
This commit is contained in:
Linus Torvalds
2025-09-30 08:48:29 -07:00
8 changed files with 124 additions and 68 deletions

View File

@@ -6478,6 +6478,7 @@ S: Supported
T: git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
F: include/linux/cred.h
F: kernel/cred.c
F: rust/kernel/cred.rs
F: Documentation/security/credentials.rst
INTEL CRPS COMMON REDUNDANT PSU DRIVER
@@ -22824,6 +22825,7 @@ F: include/linux/security.h
F: include/uapi/linux/lsm.h
F: security/
F: tools/testing/selftests/lsm/
F: rust/kernel/security.rs
X: security/selinux/
K: \bsecurity_[a-z_0-9]\+\b

View File

@@ -116,6 +116,9 @@ struct lsm_blob_sizes {
int lbs_xattr_count; /* number of xattr slots in new_xattrs array */
int lbs_tun_dev;
int lbs_bdev;
int lbs_bpf_map;
int lbs_bpf_prog;
int lbs_bpf_token;
};
/*

View File

@@ -8,11 +8,7 @@
//!
//! Reference: <https://www.kernel.org/doc/html/latest/security/credentials.html>
use crate::{
bindings,
task::Kuid,
types::{AlwaysRefCounted, Opaque},
};
use crate::{bindings, sync::aref::AlwaysRefCounted, task::Kuid, types::Opaque};
/// Wraps the kernel's `struct cred`.
///

View File

@@ -269,6 +269,7 @@ endchoice
config LSM
string "Ordered list of enabled LSMs"
depends on SECURITY
default "landlock,lockdown,yama,loadpin,safesetid,smack,selinux,tomoyo,apparmor,ipe,bpf" if DEFAULT_SECURITY_SMACK
default "landlock,lockdown,yama,loadpin,safesetid,apparmor,selinux,smack,tomoyo,ipe,bpf" if DEFAULT_SECURITY_APPARMOR
default "landlock,lockdown,yama,loadpin,safesetid,tomoyo,ipe,bpf" if DEFAULT_SECURITY_TOMOYO

View File

@@ -3,6 +3,7 @@
#include <linux/mm.h>
#include <linux/security.h>
#include <linux/sysctl.h>
#include <linux/minmax.h>
/* amount of vm to protect from userspace access by both DAC and the LSM*/
unsigned long mmap_min_addr;
@@ -16,10 +17,7 @@ unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
static void update_mmap_min_addr(void)
{
#ifdef CONFIG_LSM_MMAP_MIN_ADDR
if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
mmap_min_addr = dac_mmap_min_addr;
else
mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
mmap_min_addr = umax(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR);
#else
mmap_min_addr = dac_mmap_min_addr;
#endif

View File

@@ -283,6 +283,9 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
lsm_set_blob_size(&needed->lbs_xattr_count,
&blob_sizes.lbs_xattr_count);
lsm_set_blob_size(&needed->lbs_bdev, &blob_sizes.lbs_bdev);
lsm_set_blob_size(&needed->lbs_bpf_map, &blob_sizes.lbs_bpf_map);
lsm_set_blob_size(&needed->lbs_bpf_prog, &blob_sizes.lbs_bpf_prog);
lsm_set_blob_size(&needed->lbs_bpf_token, &blob_sizes.lbs_bpf_token);
}
/* Prepare LSM for initialization. */
@@ -480,6 +483,9 @@ static void __init ordered_lsm_init(void)
init_debug("tun device blob size = %d\n", blob_sizes.lbs_tun_dev);
init_debug("xattr slots = %d\n", blob_sizes.lbs_xattr_count);
init_debug("bdev blob size = %d\n", blob_sizes.lbs_bdev);
init_debug("bpf map blob size = %d\n", blob_sizes.lbs_bpf_map);
init_debug("bpf prog blob size = %d\n", blob_sizes.lbs_bpf_prog);
init_debug("bpf token blob size = %d\n", blob_sizes.lbs_bpf_token);
/*
* Create any kmem_caches needed for blobs
@@ -823,18 +829,51 @@ static int lsm_msg_msg_alloc(struct msg_msg *mp)
*/
static int lsm_bdev_alloc(struct block_device *bdev)
{
if (blob_sizes.lbs_bdev == 0) {
bdev->bd_security = NULL;
return 0;
}
bdev->bd_security = kzalloc(blob_sizes.lbs_bdev, GFP_KERNEL);
if (!bdev->bd_security)
return -ENOMEM;
return 0;
return lsm_blob_alloc(&bdev->bd_security, blob_sizes.lbs_bdev,
GFP_KERNEL);
}
#ifdef CONFIG_BPF_SYSCALL
/**
* lsm_bpf_map_alloc - allocate a composite bpf_map blob
* @map: the bpf_map that needs a blob
*
* Allocate the bpf_map blob for all the modules
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
static int lsm_bpf_map_alloc(struct bpf_map *map)
{
return lsm_blob_alloc(&map->security, blob_sizes.lbs_bpf_map, GFP_KERNEL);
}
/**
* lsm_bpf_prog_alloc - allocate a composite bpf_prog blob
* @prog: the bpf_prog that needs a blob
*
* Allocate the bpf_prog blob for all the modules
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
static int lsm_bpf_prog_alloc(struct bpf_prog *prog)
{
return lsm_blob_alloc(&prog->aux->security, blob_sizes.lbs_bpf_prog, GFP_KERNEL);
}
/**
* lsm_bpf_token_alloc - allocate a composite bpf_token blob
* @token: the bpf_token that needs a blob
*
* Allocate the bpf_token blob for all the modules
*
* Returns 0, or -ENOMEM if memory can't be allocated.
*/
static int lsm_bpf_token_alloc(struct bpf_token *token)
{
return lsm_blob_alloc(&token->security, blob_sizes.lbs_bpf_token, GFP_KERNEL);
}
#endif /* CONFIG_BPF_SYSCALL */
/**
* lsm_early_task - during initialization allocate a composite task blob
* @task: the task that needs a blob
@@ -5728,7 +5767,16 @@ int security_bpf_prog(struct bpf_prog *prog)
int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
struct bpf_token *token, bool kernel)
{
return call_int_hook(bpf_map_create, map, attr, token, kernel);
int rc;
rc = lsm_bpf_map_alloc(map);
if (unlikely(rc))
return rc;
rc = call_int_hook(bpf_map_create, map, attr, token, kernel);
if (unlikely(rc))
security_bpf_map_free(map);
return rc;
}
/**
@@ -5747,7 +5795,16 @@ int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
struct bpf_token *token, bool kernel)
{
return call_int_hook(bpf_prog_load, prog, attr, token, kernel);
int rc;
rc = lsm_bpf_prog_alloc(prog);
if (unlikely(rc))
return rc;
rc = call_int_hook(bpf_prog_load, prog, attr, token, kernel);
if (unlikely(rc))
security_bpf_prog_free(prog);
return rc;
}
/**
@@ -5764,7 +5821,16 @@ int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
const struct path *path)
{
return call_int_hook(bpf_token_create, token, attr, path);
int rc;
rc = lsm_bpf_token_alloc(token);
if (unlikely(rc))
return rc;
rc = call_int_hook(bpf_token_create, token, attr, path);
if (unlikely(rc))
security_bpf_token_free(token);
return rc;
}
/**
@@ -5808,6 +5874,8 @@ int security_bpf_token_capable(const struct bpf_token *token, int cap)
void security_bpf_map_free(struct bpf_map *map)
{
call_void_hook(bpf_map_free, map);
kfree(map->security);
map->security = NULL;
}
/**
@@ -5819,6 +5887,8 @@ void security_bpf_map_free(struct bpf_map *map)
void security_bpf_prog_free(struct bpf_prog *prog)
{
call_void_hook(bpf_prog_free, prog);
kfree(prog->aux->security);
prog->aux->security = NULL;
}
/**
@@ -5830,6 +5900,8 @@ void security_bpf_prog_free(struct bpf_prog *prog)
void security_bpf_token_free(struct bpf_token *token)
{
call_void_hook(bpf_token_free, token);
kfree(token->security);
token->security = NULL;
}
#endif /* CONFIG_BPF_SYSCALL */

View File

@@ -7066,14 +7066,14 @@ static int bpf_fd_pass(const struct file *file, u32 sid)
if (file->f_op == &bpf_map_fops) {
map = file->private_data;
bpfsec = map->security;
bpfsec = selinux_bpf_map_security(map);
ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
bpf_map_fmode_to_av(file->f_mode), NULL);
if (ret)
return ret;
} else if (file->f_op == &bpf_prog_fops) {
prog = file->private_data;
bpfsec = prog->aux->security;
bpfsec = selinux_bpf_prog_security(prog);
ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
BPF__PROG_RUN, NULL);
if (ret)
@@ -7087,7 +7087,7 @@ static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
u32 sid = current_sid();
struct bpf_security_struct *bpfsec;
bpfsec = map->security;
bpfsec = selinux_bpf_map_security(map);
return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
bpf_map_fmode_to_av(fmode), NULL);
}
@@ -7097,7 +7097,7 @@ static int selinux_bpf_prog(struct bpf_prog *prog)
u32 sid = current_sid();
struct bpf_security_struct *bpfsec;
bpfsec = prog->aux->security;
bpfsec = selinux_bpf_prog_security(prog);
return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
BPF__PROG_RUN, NULL);
}
@@ -7107,69 +7107,33 @@ static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
{
struct bpf_security_struct *bpfsec;
bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
if (!bpfsec)
return -ENOMEM;
bpfsec = selinux_bpf_map_security(map);
bpfsec->sid = current_sid();
map->security = bpfsec;
return 0;
}
static void selinux_bpf_map_free(struct bpf_map *map)
{
struct bpf_security_struct *bpfsec = map->security;
map->security = NULL;
kfree(bpfsec);
}
static int selinux_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr,
struct bpf_token *token, bool kernel)
{
struct bpf_security_struct *bpfsec;
bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
if (!bpfsec)
return -ENOMEM;
bpfsec = selinux_bpf_prog_security(prog);
bpfsec->sid = current_sid();
prog->aux->security = bpfsec;
return 0;
}
static void selinux_bpf_prog_free(struct bpf_prog *prog)
{
struct bpf_security_struct *bpfsec = prog->aux->security;
prog->aux->security = NULL;
kfree(bpfsec);
}
static int selinux_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
const struct path *path)
{
struct bpf_security_struct *bpfsec;
bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
if (!bpfsec)
return -ENOMEM;
bpfsec = selinux_bpf_token_security(token);
bpfsec->sid = current_sid();
token->security = bpfsec;
return 0;
}
static void selinux_bpf_token_free(struct bpf_token *token)
{
struct bpf_security_struct *bpfsec = token->security;
token->security = NULL;
kfree(bpfsec);
}
#endif
struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
@@ -7187,6 +7151,9 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
.lbs_xattr_count = SELINUX_INODE_INIT_XATTRS,
.lbs_tun_dev = sizeof(struct tun_security_struct),
.lbs_ib = sizeof(struct ib_security_struct),
.lbs_bpf_map = sizeof(struct bpf_security_struct),
.lbs_bpf_prog = sizeof(struct bpf_security_struct),
.lbs_bpf_token = sizeof(struct bpf_security_struct),
};
#ifdef CONFIG_PERF_EVENTS
@@ -7540,9 +7507,6 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
LSM_HOOK_INIT(bpf, selinux_bpf),
LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
LSM_HOOK_INIT(bpf_map_free, selinux_bpf_map_free),
LSM_HOOK_INIT(bpf_prog_free, selinux_bpf_prog_free),
LSM_HOOK_INIT(bpf_token_free, selinux_bpf_token_free),
#endif
#ifdef CONFIG_PERF_EVENTS

View File

@@ -26,6 +26,7 @@
#include <linux/lsm_hooks.h>
#include <linux/msg.h>
#include <net/net_namespace.h>
#include <linux/bpf.h>
#include "flask.h"
#include "avc.h"
@@ -245,4 +246,23 @@ selinux_perf_event(void *perf_event)
return perf_event + selinux_blob_sizes.lbs_perf_event;
}
#ifdef CONFIG_BPF_SYSCALL
static inline struct bpf_security_struct *
selinux_bpf_map_security(struct bpf_map *map)
{
return map->security + selinux_blob_sizes.lbs_bpf_map;
}
static inline struct bpf_security_struct *
selinux_bpf_prog_security(struct bpf_prog *prog)
{
return prog->aux->security + selinux_blob_sizes.lbs_bpf_prog;
}
static inline struct bpf_security_struct *
selinux_bpf_token_security(struct bpf_token *token)
{
return token->security + selinux_blob_sizes.lbs_bpf_token;
}
#endif /* CONFIG_BPF_SYSCALL */
#endif /* _SELINUX_OBJSEC_H_ */