Re: [PATCH v5 3/3] AppArmor: add support for lsm_config_self_policy and lsm_config_system_policy
From: Mickaël Salaün <mic@digikod.net>
Date: 2025-08-20 14:21:40
Also in:
linux-security-module, lkml
On Wed, Jul 09, 2025 at 10:00:56AM +0200, Maxime Bélair wrote:
Enable users to manage AppArmor policies through the new hooks lsm_config_self_policy and lsm_config_system_policy. lsm_config_self_policy allows stacking existing policies in the kernel. This ensures that it can only further restrict the caller and can never be used to gain new privileges. lsm_config_system_policy allows loading or replacing AppArmor policies in any AppArmor namespace. Signed-off-by: Maxime Bélair <redacted> --- security/apparmor/apparmorfs.c | 31 ++++++++++ security/apparmor/include/apparmor.h | 4 ++ security/apparmor/include/apparmorfs.h | 3 + security/apparmor/lsm.c | 84 ++++++++++++++++++++++++++ 4 files changed, 122 insertions(+)
quoted hunk ↗ jump to hunk
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 9b6c2f157f83..0ce40290f44e 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c@@ -1275,6 +1275,86 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); } +/** + * apparmor_lsm_config_self_policy - Stack a profile + * @lsm_id: AppArmor ID (LSM_ID_APPARMOR). Unused here + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: buffer containing the user-provided name of the profile to stack + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: 0 on success, negative value on error + */ +static int apparmor_lsm_config_self_policy(u32 lsm_id, u32 op, void __user *buf, + size_t size, u32 flags) +{ + char *name; + long name_size; + int ret; +
+ if (op != LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + if (size == 0) + return -EINVAL; + if (size > AA_PROFILE_NAME_MAX_SIZE) + return -E2BIG; + + name = kmalloc(size, GFP_KERNEL); + if (!name) + return -ENOMEM;
This hunk should be part of the syscall code and shared amongst LSMs.
+
+
+ name_size = strncpy_from_user(name, buf, size);
+ if (name_size < 0) {
+ kfree(name);
+ return name_size;
+ }
+
+ ret = aa_change_profile(name, AA_CHANGE_STACK);
+
+ kfree(name);
+
+ return ret;
+}