[apparmor] AppArmor kernel audit locks up system
Paul Moore
paul at paul-moore.com
Mon Oct 9 17:51:22 UTC 2023
On Mon, Oct 9, 2023 at 1:41 PM John Johansen
<john.johansen at canonical.com> wrote:
> On 10/9/23 10:06, Paul Moore wrote:
> > I don't think anyone is objecting to resolving this, it's more a
> > matter of *how* we can resolve it.
>
> currently I am see four crazy/stupid paths forward, each with their own
> pain points.
>
>
> 1. lift the capable() and security_task_setrlimit() calls out of the lock.
>
> this might be possible, it should be fine for capable() but does open
> a potential race window for security_task_setrlimit() if the LSM hooks
> mediation looks at the tasks current resource value.
Ignoring the race for a moment, I worry that even if we solve it for
this particular case it could easily come back to bite us somewhere
else.
> 2. rework get_task_exe_file() to not need the task lock. That looks
> like a major under taking, and I don't currently see it as viable.
Agreed.
> 3. get the task lock switch to a recursive spin_lock. Another large
> piece of work that I don't currently see as viable.
Agreed.
> 4. caching a reference in the audit_context as paul has suggested.
I don't like this idea, but I'm struggling to come up with something
less awful. Below is a quick, untested patch to describe the concept
with code. It is worth noting that we don't take a mm_struct
reference in the io_uring entry point because I'm not sure filtering
on the executable file makes much sense there given the async nature
of io_uring, however I'm open to comments here (as well as pretty much
everything else in this pseudo-patch).
WARNING: this is a cut-n-paste so it's probably mangled.
diff --git a/kernel/audit.h b/kernel/audit.h
index a60d2840559e..eac470aaca4f 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -146,6 +146,8 @@ struct audit_context {
u32 target_sid;
char target_comm[TASK_COMM_LEN];
+ struct mm_struct *mm;
+
struct audit_tree_refs *trees, *first_trees;
struct list_head killed_trees;
int tree_count;
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 65075f1e4ac8..a619394530bd 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -526,8 +526,12 @@ int audit_exe_compare(struct task_struct *tsk, struct audit
_fsnotify_mark *mark)
struct file *exe_file;
unsigned long ino;
dev_t dev;
+ struct mm_struct *mm;
- exe_file = get_task_exe_file(tsk);
+ mm = tsk->audit_context->mm;
+ if (!mm)
+ return 0;
+ exe_file = get_mm_exe_file(mm);
if (!exe_file)
return 0;
ino = file_inode(exe_file)->i_ino;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 21d2fa815e78..edeff28a4bab 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1019,6 +1019,10 @@ static void audit_reset_context(struct audit_context *ctx
)
ctx->target_sessionid = 0;
ctx->target_sid = 0;
ctx->target_comm[0] = '\0';
+ if (ctx->mm) {
+ mmput(ctx->mm);
+ ctx->mm = NULL;
+ }
unroll_tree_refs(ctx, NULL, 0);
WARN_ON(!list_empty(&ctx->killed_trees));
audit_free_module(ctx);
@@ -2035,6 +2039,9 @@ void __audit_syscall_entry(int major, unsigned long a1, un
signed long a2,
return;
}
+ /* get mm as it requires task_lock() which may not be safe later */
+ context->mm = get_task_mm(current);
+
context->arch = syscall_get_arch(current);
context->major = major;
context->argv[0] = a1;
--
paul-moore.com
More information about the AppArmor
mailing list