audit_ctl_owner_current() reads the lock owner without taking the lock and KCSAN complains about it. Only the current task can store itself as owner, so the check can't give a wrong answer. Mark the accesses with READ_ONCE() and WRITE_ONCE().
Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=39b8fea0641107a1ccee Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Babanpreet Singh <[email protected]> --- Paul, you looked at this race in 2022 and asked whether READ_ONCE() was worth it and what it would cost: https://lore.kernel.org/all/CAHC9VhTXNPWBDRoPcz-Jw=f+nnaehxbh-ysc56cud-zbubo...@mail.gmail.com/ Compile tested only (gcc and the KCSAN instrumentation diff); I could not reproduce the race in QEMU. kernel/audit.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 631d6d4a23cfd..f8c43ac6d5b82 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -247,7 +247,7 @@ int auditd_test_task(struct task_struct *task) void audit_ctl_lock(void) { mutex_lock(&audit_cmd_mutex.lock); - audit_cmd_mutex.owner = current; + WRITE_ONCE(audit_cmd_mutex.owner, current); } /** @@ -255,7 +255,7 @@ void audit_ctl_lock(void) */ void audit_ctl_unlock(void) { - audit_cmd_mutex.owner = NULL; + WRITE_ONCE(audit_cmd_mutex.owner, NULL); mutex_unlock(&audit_cmd_mutex.lock); } @@ -268,7 +268,12 @@ void audit_ctl_unlock(void) */ static bool audit_ctl_owner_current(void) { - return (current == audit_cmd_mutex.owner); + /* + * Lockless read: the owner can only equal current if current set + * it, so another task changing the owner concurrently can never + * make this return the wrong answer. + */ + return (current == READ_ONCE(audit_cmd_mutex.owner)); } /** base-commit: a8bdcf944504980635c2069b4a4cfcf677b09bbb -- 2.43.0

