devcgroup_inode_mknod and devcgroup_inode_permission hooks are called at place where already the corresponding lsm hooks security_inode_mknod and security_inode_permission are called to govern device access. Though introduce a small LSM which implements those two security hooks instead of the additional explicit devcgroup calls. The explicit API will be removed when corresponding subsystems will drop the direct call to devcgroup hooks. Signed-off-by: Michael Weiß <michael.weiss@xxxxxxxxxxxxxxxxxxx> --- init/Kconfig | 4 + security/Kconfig | 1 + security/Makefile | 2 +- security/device_cgroup/Kconfig | 7 ++ security/device_cgroup/Makefile | 4 + security/{ => device_cgroup}/device_cgroup.c | 0 security/device_cgroup/lsm.c | 82 ++++++++++++++++++++ 7 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 security/device_cgroup/Kconfig create mode 100644 security/device_cgroup/Makefile rename security/{ => device_cgroup}/device_cgroup.c (100%) create mode 100644 security/device_cgroup/lsm.c diff --git a/init/Kconfig b/init/Kconfig index 6d35728b94b2..5ed28dc821f3 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1111,6 +1111,8 @@ config PROC_PID_CPUSET config CGROUP_DEVICE bool "Device controller" + select SECURITY + select SECURITY_DEVICE_CGROUP help Provides a cgroup controller implementing whitelists for devices which a process in the cgroup can mknod or open. @@ -1136,6 +1138,8 @@ config CGROUP_BPF bool "Support for eBPF programs attached to cgroups" depends on BPF_SYSCALL select SOCK_CGROUP_DATA + select SECURITY + select SECURITY_DEVICE_CGROUP help Allow attaching eBPF programs to a cgroup using the bpf(2) syscall command BPF_PROG_ATTACH. diff --git a/security/Kconfig b/security/Kconfig index 52c9af08ad35..0a0e60fc50e1 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -194,6 +194,7 @@ source "security/yama/Kconfig" source "security/safesetid/Kconfig" source "security/lockdown/Kconfig" source "security/landlock/Kconfig" +source "security/device_cgroup/Kconfig" source "security/integrity/Kconfig" diff --git a/security/Makefile b/security/Makefile index 18121f8f85cd..7000cb8a69e8 100644 --- a/security/Makefile +++ b/security/Makefile @@ -21,7 +21,7 @@ obj-$(CONFIG_SECURITY_YAMA) += yama/ obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/ obj-$(CONFIG_SECURITY_SAFESETID) += safesetid/ obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown/ -obj-$(CONFIG_CGROUPS) += device_cgroup.o +obj-$(CONFIG_SECURITY_DEVICE_CGROUP) += device_cgroup/ obj-$(CONFIG_BPF_LSM) += bpf/ obj-$(CONFIG_SECURITY_LANDLOCK) += landlock/ diff --git a/security/device_cgroup/Kconfig b/security/device_cgroup/Kconfig new file mode 100644 index 000000000000..93934bda3b8e --- /dev/null +++ b/security/device_cgroup/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +config SECURITY_DEVICE_CGROUP + bool "Device Cgroup Support" + depends on SECURITY + help + Provides the necessary security framework integration + for cgroup device controller implementations. diff --git a/security/device_cgroup/Makefile b/security/device_cgroup/Makefile new file mode 100644 index 000000000000..c715b2b96388 --- /dev/null +++ b/security/device_cgroup/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_SECURITY_DEVICE_CGROUP) += devcgroup.o + +devcgroup-y := lsm.o device_cgroup.o diff --git a/security/device_cgroup.c b/security/device_cgroup/device_cgroup.c similarity index 100% rename from security/device_cgroup.c rename to security/device_cgroup/device_cgroup.c diff --git a/security/device_cgroup/lsm.c b/security/device_cgroup/lsm.c new file mode 100644 index 000000000000..ef30cff1f610 --- /dev/null +++ b/security/device_cgroup/lsm.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device cgroup security module + * + * This file contains device cgroup LSM hooks. + * + * Copyright (C) 2023 Fraunhofer AISEC. All rights reserved. + * Based on code copied from <file:include/linux/device_cgroups.h> (which has no copyright) + * + * Authors: Michael Weiß <michael.weiss@xxxxxxxxxxxxxxxxxxx> + */ + +#include <linux/bpf-cgroup.h> +#include <linux/device_cgroup.h> +#include <linux/lsm_hooks.h> + +static int devcg_inode_permission(struct inode *inode, int mask) +{ + short type, access = 0; + + if (likely(!inode->i_rdev)) + return 0; + + if (S_ISBLK(inode->i_mode)) + type = DEVCG_DEV_BLOCK; + else if (S_ISCHR(inode->i_mode)) + type = DEVCG_DEV_CHAR; + else + return 0; + + if (mask & MAY_WRITE) + access |= DEVCG_ACC_WRITE; + if (mask & MAY_READ) + access |= DEVCG_ACC_READ; + + return devcgroup_check_permission(type, imajor(inode), iminor(inode), + access); +} + +static int __devcg_inode_mknod(int mode, dev_t dev, short access) +{ + short type; + + if (!S_ISBLK(mode) && !S_ISCHR(mode)) + return 0; + + if (S_ISCHR(mode) && dev == WHITEOUT_DEV) + return 0; + + if (S_ISBLK(mode)) + type = DEVCG_DEV_BLOCK; + else + type = DEVCG_DEV_CHAR; + + return devcgroup_check_permission(type, MAJOR(dev), MINOR(dev), + access); +} + +static int devcg_inode_mknod(struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t dev) +{ + return __devcg_inode_mknod(mode, dev, DEVCG_ACC_MKNOD); +} + +static struct security_hook_list devcg_hooks[] __ro_after_init = { + LSM_HOOK_INIT(inode_permission, devcg_inode_permission), + LSM_HOOK_INIT(inode_mknod, devcg_inode_mknod), +}; + +static int __init devcgroup_init(void) +{ + security_add_hooks(devcg_hooks, ARRAY_SIZE(devcg_hooks), + "devcgroup"); + pr_info("device cgroup initialized\n"); + return 0; +} + +DEFINE_LSM(devcgroup) = { + .name = "devcgroup", + .order = LSM_ORDER_FIRST, + .init = devcgroup_init, +}; -- 2.30.2