aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-24 09:22:21 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-24 09:22:21 -0700
commiteefe0b9dee5db64ec87707c8e44f31851f257389 (patch)
treecf1f706574c5139653803742813ed1f161c44852 /security
parentdd6c438c3e64a5ff0b5d7e78f7f9be547803ef1b (diff)
parent11b7df0952663f20ce72c9a22a3cf9278cf84db7 (diff)
downloadlinux-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.c36
-rw-r--r--security/apparmor/match.c2
-rw-r--r--security/apparmor/path.c8
-rw-r--r--security/apparmor/policy_unpack.c2
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)