mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
selinux/stable-7.0 PR 20260203
-----BEGIN PGP SIGNATURE----- iQJIBAABCgAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmmCup0UHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXOjcA//QpH/SmY+U5kdyQcu7ZDclcLJoJMM LFMeYEDmIOWh29K4fP7BqTH3c2qZMrEpcudHrkMWwO05Nae1L8Tusc2Gq91DpWTq JxCntZYEaamoh4KMrsXhC/43MoMCIr/aWgPwrSVwXD2/nqd12fWdnATDZCUuLZPa KcWKADEgjD4fCgIhQLNVo0jbLKw3Ulnmm0qo4MR+Lw2L/JfOIOJUYIwh9SEIQxwh xJfUFUUNKZE7TggBH5V2t5LHWQCJmUmFDKuRFlykr0owOej3Cz+0XEszFFffbrQ6 0Xspr0wMygpaNnM4DTRU/1nwRXINY9Z00fGpI1tDGR30IcEOv1Ub88mQIPnF0WvI E3XTCFjh0tQK5i6xH96yZzEK28wkEZ7MFSBui4UoKuaFdxwN25k61BG42+Q3bcSH zyRK7GOoii+iqCRDRTS+rAb2yOq2eWOP2h6mnIcviZtGqs8+t2/sVAE3Uv9GGMIb 2U7IDv5TljYbVXbmXBtBe7bw6N/rPI9RdQFz1vOV1cEkvljXCehfTVcKdcf8oC0M mW0wienlxbawXK/DuS5Sv287U2GehiUaT5JvyWbleZ4yVIo15uPgVSVhk5r4lECX GHEEOrvP/eNBVb7J7s++cZprNVOudC4I3kTUnacqTJKaJE3uNDQYdR8z9B/05/rB djI3gsNh+XjMYcU= =eiWJ -----END PGP SIGNATURE----- Merge tag 'selinux-pr-20260203' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux Pull selinux updates from Paul Moore: - Add support for SELinux based access control of BPF tokens We worked with the BPF devs to add the necessary LSM hooks when the BPF token code was first introduced, but it took us a bit longer to add the SELinux wiring and support. In order to preserve existing token-unaware SELinux policies, the new code is gated by the new "bpf_token_perms" policy capability. Additional details regarding the new permissions, and behaviors can be found in the associated commit. - Remove a BUG() from the SELinux capability code We now perform a similar check during compile time so we can safely remove the BUG() call. * tag 'selinux-pr-20260203' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: drop the BUG() in cred_has_capability() selinux: fix a capabilities parsing typo in selinux_bpf_token_capable() selinux: add support for BPF token access control selinux: move the selinux_blob_sizes struct
This commit is contained in:
commit
6252e917b9
6 changed files with 151 additions and 25 deletions
|
|
@ -737,6 +737,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|||
goto out;
|
||||
}
|
||||
|
||||
sbsec->creator_sid = current_sid();
|
||||
|
||||
if (strcmp(sb->s_type->name, "proc") == 0)
|
||||
sbsec->flags |= SE_SBPROC | SE_SBGENFS;
|
||||
|
||||
|
|
@ -908,6 +910,8 @@ static int selinux_cmp_sb_context(const struct super_block *oldsb,
|
|||
if (oldroot->sid != newroot->sid)
|
||||
goto mismatch;
|
||||
}
|
||||
if (old->creator_sid != new->creator_sid)
|
||||
goto mismatch;
|
||||
return 0;
|
||||
mismatch:
|
||||
pr_warn("SELinux: mount invalid. Same superblock, "
|
||||
|
|
@ -967,6 +971,7 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|||
newsbsec->sid = oldsbsec->sid;
|
||||
newsbsec->def_sid = oldsbsec->def_sid;
|
||||
newsbsec->behavior = oldsbsec->behavior;
|
||||
newsbsec->creator_sid = oldsbsec->creator_sid;
|
||||
|
||||
if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
|
||||
!(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
|
||||
|
|
@ -1654,7 +1659,6 @@ static int cred_has_capability(const struct cred *cred,
|
|||
break;
|
||||
default:
|
||||
pr_err("SELinux: out of range capability %d\n", cap);
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2586,6 +2590,7 @@ static int selinux_sb_alloc_security(struct super_block *sb)
|
|||
sbsec->sid = SECINITSID_UNLABELED;
|
||||
sbsec->def_sid = SECINITSID_FILE;
|
||||
sbsec->mntpoint_sid = SECINITSID_UNLABELED;
|
||||
sbsec->creator_sid = SECINITSID_UNLABELED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -7043,6 +7048,9 @@ static int selinux_bpf(int cmd, union bpf_attr *attr,
|
|||
u32 sid = current_sid();
|
||||
int ret;
|
||||
|
||||
if (selinux_policycap_bpf_token_perms())
|
||||
return 0;
|
||||
|
||||
switch (cmd) {
|
||||
case BPF_MAP_CREATE:
|
||||
ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
|
||||
|
|
@ -7124,60 +7132,144 @@ static int selinux_bpf_prog(struct bpf_prog *prog)
|
|||
BPF__PROG_RUN, NULL);
|
||||
}
|
||||
|
||||
static u32 selinux_bpffs_creator_sid(u32 fd)
|
||||
{
|
||||
struct path path;
|
||||
struct super_block *sb;
|
||||
struct superblock_security_struct *sbsec;
|
||||
|
||||
CLASS(fd, f)(fd);
|
||||
|
||||
if (fd_empty(f))
|
||||
return SECSID_NULL;
|
||||
|
||||
path = fd_file(f)->f_path;
|
||||
sb = path.dentry->d_sb;
|
||||
sbsec = selinux_superblock(sb);
|
||||
|
||||
return sbsec->creator_sid;
|
||||
}
|
||||
|
||||
static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr,
|
||||
struct bpf_token *token, bool kernel)
|
||||
{
|
||||
struct bpf_security_struct *bpfsec;
|
||||
u32 ssid;
|
||||
|
||||
bpfsec = selinux_bpf_map_security(map);
|
||||
bpfsec->sid = current_sid();
|
||||
|
||||
return 0;
|
||||
if (!token)
|
||||
ssid = bpfsec->sid;
|
||||
else
|
||||
ssid = selinux_bpffs_creator_sid(attr->map_token_fd);
|
||||
|
||||
return avc_has_perm(ssid, bpfsec->sid, SECCLASS_BPF, BPF__MAP_CREATE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
u32 ssid;
|
||||
|
||||
bpfsec = selinux_bpf_prog_security(prog);
|
||||
bpfsec->sid = current_sid();
|
||||
|
||||
return 0;
|
||||
if (!token)
|
||||
ssid = bpfsec->sid;
|
||||
else
|
||||
ssid = selinux_bpffs_creator_sid(attr->prog_token_fd);
|
||||
|
||||
return avc_has_perm(ssid, bpfsec->sid, SECCLASS_BPF, BPF__PROG_LOAD,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int selinux_bpf_token_create(struct bpf_token *token, union bpf_attr *attr,
|
||||
#define bpf_token_cmd(T, C) \
|
||||
((T)->allowed_cmds & (1ULL << (C)))
|
||||
|
||||
static int selinux_bpf_token_create(struct bpf_token *token,
|
||||
union bpf_attr *attr,
|
||||
const struct path *path)
|
||||
{
|
||||
struct bpf_security_struct *bpfsec;
|
||||
u32 sid = selinux_bpffs_creator_sid(attr->token_create.bpffs_fd);
|
||||
int err;
|
||||
|
||||
bpfsec = selinux_bpf_token_security(token);
|
||||
bpfsec->sid = current_sid();
|
||||
bpfsec->grantor_sid = sid;
|
||||
|
||||
bpfsec->perms = 0;
|
||||
/**
|
||||
* 'token->allowed_cmds' is a bit mask of allowed commands
|
||||
* Convert the BPF command enum to a bitmask representing its position
|
||||
* in the allowed_cmds bitmap.
|
||||
*/
|
||||
if (bpf_token_cmd(token, BPF_MAP_CREATE)) {
|
||||
err = avc_has_perm(bpfsec->sid, sid, SECCLASS_BPF,
|
||||
BPF__MAP_CREATE_AS, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
bpfsec->perms |= BPF__MAP_CREATE;
|
||||
}
|
||||
if (bpf_token_cmd(token, BPF_PROG_LOAD)) {
|
||||
err = avc_has_perm(bpfsec->sid, sid, SECCLASS_BPF,
|
||||
BPF__PROG_LOAD_AS, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
bpfsec->perms |= BPF__PROG_LOAD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
|
||||
.lbs_cred = sizeof(struct cred_security_struct),
|
||||
.lbs_task = sizeof(struct task_security_struct),
|
||||
.lbs_file = sizeof(struct file_security_struct),
|
||||
.lbs_inode = sizeof(struct inode_security_struct),
|
||||
.lbs_ipc = sizeof(struct ipc_security_struct),
|
||||
.lbs_key = sizeof(struct key_security_struct),
|
||||
.lbs_msg_msg = sizeof(struct msg_security_struct),
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
.lbs_perf_event = sizeof(struct perf_event_security_struct),
|
||||
static int selinux_bpf_token_cmd(const struct bpf_token *token,
|
||||
enum bpf_cmd cmd)
|
||||
{
|
||||
struct bpf_security_struct *bpfsec;
|
||||
|
||||
bpfsec = token->security;
|
||||
switch (cmd) {
|
||||
case BPF_MAP_CREATE:
|
||||
if (!(bpfsec->perms & BPF__MAP_CREATE))
|
||||
return -EACCES;
|
||||
break;
|
||||
case BPF_PROG_LOAD:
|
||||
if (!(bpfsec->perms & BPF__PROG_LOAD))
|
||||
return -EACCES;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int selinux_bpf_token_capable(const struct bpf_token *token, int cap)
|
||||
{
|
||||
u16 sclass;
|
||||
struct bpf_security_struct *bpfsec = token->security;
|
||||
bool initns = (token->userns == &init_user_ns);
|
||||
u32 av = CAP_TO_MASK(cap);
|
||||
|
||||
switch (CAP_TO_INDEX(cap)) {
|
||||
case 0:
|
||||
sclass = initns ? SECCLASS_CAPABILITY : SECCLASS_CAP_USERNS;
|
||||
break;
|
||||
case 1:
|
||||
sclass = initns ? SECCLASS_CAPABILITY2 : SECCLASS_CAP2_USERNS;
|
||||
break;
|
||||
default:
|
||||
pr_err("SELinux: out of range capability %d\n", cap);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return avc_has_perm(current_sid(), bpfsec->grantor_sid, sclass, av,
|
||||
NULL);
|
||||
}
|
||||
#endif
|
||||
.lbs_sock = sizeof(struct sk_security_struct),
|
||||
.lbs_superblock = sizeof(struct superblock_security_struct),
|
||||
.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
|
||||
static int selinux_perf_event_open(int type)
|
||||
|
|
@ -7297,6 +7389,27 @@ static const struct lsm_id selinux_lsmid = {
|
|||
.id = LSM_ID_SELINUX,
|
||||
};
|
||||
|
||||
struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
|
||||
.lbs_cred = sizeof(struct cred_security_struct),
|
||||
.lbs_task = sizeof(struct task_security_struct),
|
||||
.lbs_file = sizeof(struct file_security_struct),
|
||||
.lbs_inode = sizeof(struct inode_security_struct),
|
||||
.lbs_ipc = sizeof(struct ipc_security_struct),
|
||||
.lbs_key = sizeof(struct key_security_struct),
|
||||
.lbs_msg_msg = sizeof(struct msg_security_struct),
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
.lbs_perf_event = sizeof(struct perf_event_security_struct),
|
||||
#endif
|
||||
.lbs_sock = sizeof(struct sk_security_struct),
|
||||
.lbs_superblock = sizeof(struct superblock_security_struct),
|
||||
.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),
|
||||
};
|
||||
|
||||
/*
|
||||
* IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
|
||||
* 1. any hooks that don't belong to (2.) or (3.) below,
|
||||
|
|
@ -7590,6 +7703,8 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
|
|||
LSM_HOOK_INIT(bpf_map_create, selinux_bpf_map_create),
|
||||
LSM_HOOK_INIT(bpf_prog_load, selinux_bpf_prog_load),
|
||||
LSM_HOOK_INIT(bpf_token_create, selinux_bpf_token_create),
|
||||
LSM_HOOK_INIT(bpf_token_cmd, selinux_bpf_token_cmd),
|
||||
LSM_HOOK_INIT(bpf_token_capable, selinux_bpf_token_capable),
|
||||
#endif
|
||||
#ifdef CONFIG_PERF_EVENTS
|
||||
LSM_HOOK_INIT(perf_event_alloc, selinux_perf_event_alloc),
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ const struct security_class_mapping secclass_map[] = {
|
|||
{ "infiniband_endport", { "manage_subnet", NULL } },
|
||||
{ "bpf",
|
||||
{ "map_create", "map_read", "map_write", "prog_load", "prog_run",
|
||||
NULL } },
|
||||
"map_create_as", "prog_load_as", NULL } },
|
||||
{ "xdp_socket", { COMMON_SOCK_PERMS, NULL } },
|
||||
{ "mctp_socket", { COMMON_SOCK_PERMS, NULL } },
|
||||
{ "perf_event",
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ struct superblock_security_struct {
|
|||
u32 sid; /* SID of file system superblock */
|
||||
u32 def_sid; /* default SID for labeling */
|
||||
u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */
|
||||
u32 creator_sid; /* SID of privileged process */
|
||||
unsigned short behavior; /* labeling behavior */
|
||||
unsigned short flags; /* which mount options were specified */
|
||||
struct mutex lock;
|
||||
|
|
@ -169,6 +170,8 @@ struct pkey_security_struct {
|
|||
|
||||
struct bpf_security_struct {
|
||||
u32 sid; /* SID of bpf obj creator */
|
||||
u32 perms; /* permissions for allowed bpf token commands */
|
||||
u32 grantor_sid; /* SID of token grantor */
|
||||
};
|
||||
|
||||
struct perf_event_security_struct {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ enum {
|
|||
POLICYDB_CAP_GENFS_SECLABEL_WILDCARD,
|
||||
POLICYDB_CAP_FUNCTIONFS_SECLABEL,
|
||||
POLICYDB_CAP_MEMFD_CLASS,
|
||||
POLICYDB_CAP_BPF_TOKEN_PERMS,
|
||||
__POLICYDB_CAP_MAX
|
||||
};
|
||||
#define POLICYDB_CAP_MAX (__POLICYDB_CAP_MAX - 1)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const char *const selinux_policycap_names[__POLICYDB_CAP_MAX] = {
|
|||
"genfs_seclabel_wildcard",
|
||||
"functionfs_seclabel",
|
||||
"memfd_class",
|
||||
"bpf_token_perms",
|
||||
};
|
||||
/* clang-format on */
|
||||
|
||||
|
|
|
|||
|
|
@ -214,6 +214,12 @@ static inline bool selinux_policycap_memfd_class(void)
|
|||
return READ_ONCE(selinux_state.policycap[POLICYDB_CAP_MEMFD_CLASS]);
|
||||
}
|
||||
|
||||
static inline bool selinux_policycap_bpf_token_perms(void)
|
||||
{
|
||||
return READ_ONCE(
|
||||
selinux_state.policycap[POLICYDB_CAP_BPF_TOKEN_PERMS]);
|
||||
}
|
||||
|
||||
struct selinux_policy_convert_data;
|
||||
|
||||
struct selinux_load_state {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue