diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-24 09:22:21 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-04-24 09:22:21 -0700 |
| commit | eefe0b9dee5db64ec87707c8e44f31851f257389 (patch) | |
| tree | cf1f706574c5139653803742813ed1f161c44852 /security | |
| parent | dd6c438c3e64a5ff0b5d7e78f7f9be547803ef1b (diff) | |
| parent | 11b7df0952663f20ce72c9a22a3cf9278cf84db7 (diff) | |
| download | linux-next-history-eefe0b9dee5db64ec87707c8e44f31851f257389.tar.gz | |
Merge tag 'apparmor-pr-2026-04-23' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen:
"Cleanups
- Use sysfs_emit in param_get_{audit,mode}
- Remove redundant if check in sk_peer_get_label
- Replace memcpy + NUL termination with kmemdup_nul in do_setattr
Bug Fixes:
- Fix aa_dfa_unpack's error handling in aa_setup_dfa_engine
- Fix string overrun due to missing termination
- Fix wrong dentry in RENAME_EXCHANGE uid check
- fix unpack_tags to properly return error in failure cases
- fix dfa size check
- return error on namespace mismatch in verify_header
- use target task's context in apparmor_getprocattr()"
* tag 'apparmor-pr-2026-04-23' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
apparmor/lsm: Fix aa_dfa_unpack's error handling in aa_setup_dfa_engine
apparmor: Fix string overrun due to missing termination
apparmor: Fix wrong dentry in RENAME_EXCHANGE uid check
apparmor: fix unpack_tags to properly return error in failure cases
apparmor: fix dfa size check
apparmor: Use sysfs_emit in param_get_{audit,mode}
apparmor: Remove redundant if check in sk_peer_get_label
apparmor: Replace memcpy + NUL termination with kmemdup_nul in do_setattr
apparmor: return error on namespace mismatch in verify_header
apparmor: use target task's context in apparmor_getprocattr()
Diffstat (limited to 'security')
| -rw-r--r-- | security/apparmor/lsm.c | 36 | ||||
| -rw-r--r-- | security/apparmor/match.c | 2 | ||||
| -rw-r--r-- | security/apparmor/path.c | 8 | ||||
| -rw-r--r-- | security/apparmor/policy_unpack.c | 2 |
4 files changed, 22 insertions, 26 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index c1d42fc72fdb4..3491e9f601943 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -17,6 +17,7 @@ #include <linux/ptrace.h> #include <linux/ctype.h> #include <linux/sysctl.h> +#include <linux/sysfs.h> #include <linux/audit.h> #include <linux/user_namespace.h> #include <linux/netfilter_ipv4.h> @@ -409,7 +410,7 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d struct path_cond cond_exchange = { .mode = d_backing_inode(new_dentry)->i_mode, }; - vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(old_dentry)); + vfsuid = i_uid_into_vfsuid(idmap, d_backing_inode(new_dentry)); cond_exchange.uid = vfsuid_into_kuid(vfsuid); error = aa_path_perm(OP_RENAME_SRC, current_cred(), @@ -822,25 +823,23 @@ static int apparmor_getprocattr(struct task_struct *task, const char *name, char **value) { int error = -ENOENT; - /* released below */ - const struct cred *cred = get_task_cred(task); - struct aa_task_ctx *ctx = task_ctx(current); struct aa_label *label = NULL; + rcu_read_lock(); if (strcmp(name, "current") == 0) - label = aa_get_newest_label(cred_label(cred)); - else if (strcmp(name, "prev") == 0 && ctx->previous) - label = aa_get_newest_label(ctx->previous); - else if (strcmp(name, "exec") == 0 && ctx->onexec) - label = aa_get_newest_label(ctx->onexec); + label = aa_get_newest_cred_label(__task_cred(task)); + else if (strcmp(name, "prev") == 0 && task_ctx(task)->previous) + label = aa_get_newest_label(task_ctx(task)->previous); + else if (strcmp(name, "exec") == 0 && task_ctx(task)->onexec) + label = aa_get_newest_label(task_ctx(task)->onexec); else error = -EINVAL; + rcu_read_unlock(); if (label) error = aa_getprocattr(label, value, true); aa_put_label(label); - put_cred(cred); return error; } @@ -858,12 +857,9 @@ static int do_setattr(u64 attr, void *value, size_t size) /* AppArmor requires that the buffer must be null terminated atm */ if (args[size - 1] != '\0') { - /* null terminate */ - largs = args = kmalloc(size + 1, GFP_KERNEL); + largs = args = kmemdup_nul(value, size, GFP_KERNEL); if (!args) return -ENOMEM; - memcpy(args, value, size); - args[size] = '\0'; } error = -EINVAL; @@ -1528,15 +1524,11 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) static struct aa_label *sk_peer_get_label(struct sock *sk) { struct aa_sk_ctx *ctx = aa_sock(sk); - struct aa_label *label = ERR_PTR(-ENOPROTOOPT); if (rcu_access_pointer(ctx->peer)) return aa_get_label_rcu(&ctx->peer); - if (sk->sk_family != PF_UNIX) - return ERR_PTR(-ENOPROTOOPT); - - return label; + return ERR_PTR(-ENOPROTOOPT); } /** @@ -2073,7 +2065,7 @@ static int param_get_audit(char *buffer, const struct kernel_param *kp) return -EINVAL; if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; - return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); + return sysfs_emit(buffer, "%s\n", audit_mode_names[aa_g_audit]); } static int param_set_audit(const char *val, const struct kernel_param *kp) @@ -2101,8 +2093,7 @@ static int param_get_mode(char *buffer, const struct kernel_param *kp) return -EINVAL; if (apparmor_initialized && !aa_current_policy_view_capable(NULL)) return -EPERM; - - return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]); + return sysfs_emit(buffer, "%s\n", aa_profile_mode_names[aa_g_profile_mode]); } static int param_set_mode(const char *val, const struct kernel_param *kp) @@ -2465,6 +2456,7 @@ static int __init aa_setup_dfa_engine(void) TO_ACCEPT2_FLAG(YYTD_DATA32)); if (IS_ERR(nulldfa)) { error = PTR_ERR(nulldfa); + nulldfa = NULL; goto fail; } nullpdb->dfa = aa_get_dfa(nulldfa); diff --git a/security/apparmor/match.c b/security/apparmor/match.c index e9fac67e5178c..3a2c6cf02b3c7 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -157,7 +157,7 @@ static int verify_dfa(struct aa_dfa *dfa) state_count = dfa->tables[YYTD_ID_BASE]->td_lolen; trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen; - if (state_count == 0) + if (state_count < 2) goto out; for (i = 0; i < state_count; i++) { if (DEFAULT_TABLE(dfa)[i] >= state_count) { diff --git a/security/apparmor/path.c b/security/apparmor/path.c index 65a0ca5cc1bdd..2494e81015384 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c @@ -164,14 +164,16 @@ static int d_namespace_path(const struct path *path, char *buf, char **name, } out: - /* Append "/" to directory paths, except for root "/" which - * already ends in a slash. + /* Append "/" to directory paths and reterminate string, except for + * root "/" which already ends in a slash. */ if (!error && isdir) { bool is_root = (*name)[0] == '/' && (*name)[1] == '\0'; - if (!is_root) + if (!is_root) { buf[aa_g_path_max - 2] = '/'; + buf[aa_g_path_max - 1] = '\0'; + } } return error; diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 076d3ff14da68..9f45d5513d2ca 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -879,6 +879,7 @@ static int unpack_tags(struct aa_ext *e, struct aa_tags_struct *tags, *info = "failed to unpack profile tag.sets"; goto fail; } + error = -EPROTO; if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; @@ -1465,6 +1466,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns) if (*ns && strcmp(*ns, name)) { audit_iface(NULL, NULL, NULL, "invalid ns change", e, error); + return error; } else if (!*ns) { *ns = kstrdup(name, GFP_KERNEL); if (!*ns) |
