From 8d34e16f7f2b51f880957f2caadaae731ee28867 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Maxime=20B=C3=A9lair?= Date: Mon, 21 Jul 2025 16:46:44 +0200 Subject: [PATCH] apparmor: userns: Add support for execpath in userns MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This new field allows reliable identification of the binary that triggered a denial since the existing field (comm) only gives the name of the binary, not its path. Thus comm doesn't work for binaries outside of $PATH or works unreliably when two binaries have the same name. Additionally comm can be modified by a program, for example, comm="(tor)" or comm=4143504920506F6C6C6572 (= ACPI Poller). Signed-off-by: Maxime Bélair Signed-off-by: John Johansen --- security/apparmor/task.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/security/apparmor/task.c b/security/apparmor/task.c index c9bc9cc69475..0db0e81b4600 100644 --- a/security/apparmor/task.c +++ b/security/apparmor/task.c @@ -15,6 +15,7 @@ #include #include +#include "include/path.h" #include "include/audit.h" #include "include/cred.h" #include "include/policy.h" @@ -300,16 +301,47 @@ int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer, xrequest, &sa)); } +static const char *get_current_exe_path(char *buffer, int buffer_size) +{ + struct file *exe_file; + struct path p; + const char *path_str; + + exe_file = get_task_exe_file(current); + if (!exe_file) + return ERR_PTR(-ENOENT); + p = exe_file->f_path; + path_get(&p); + + if (aa_path_name(&p, FLAG_VIEW_SUBNS, buffer, &path_str, NULL, NULL)) + return ERR_PTR(-ENOMEM); + + fput(exe_file); + path_put(&p); + + return path_str; +} + /* call back to audit ptrace fields */ static void audit_ns_cb(struct audit_buffer *ab, void *va) { struct apparmor_audit_data *ad = aad_of_va(va); + char *buffer; + const char *path; if (ad->request & AA_USERNS_CREATE) audit_log_format(ab, " requested=\"userns_create\""); if (ad->denied & AA_USERNS_CREATE) audit_log_format(ab, " denied=\"userns_create\""); + + buffer = aa_get_buffer(false); + if (!buffer) + return; // OOM + path = get_current_exe_path(buffer, aa_g_path_max); + if (!IS_ERR(path)) + audit_log_format(ab, " execpath=\"%s\"", path); + aa_put_buffer(buffer); } int aa_profile_ns_perm(struct aa_profile *profile, -- 2.47.3