NAS-143100 / 26.0.0-RC.1 / audit: do not follow a stale filename->aname back-pointer (by ixhamza) - #352
Merged
Conversation
…me->aname
__audit_getname() caches a back-pointer to the audit_names record in
filename->aname and __audit_inode() follows it. Nothing invalidates it.
io_uring calls getname() in ->prep() but issues the operation later, on
an io-wq worker or from task work, so the submitting syscall exits and
audit_free_names() frees the record while io_uring still holds the
filename. __audit_inode() then writes into freed memory:
BUG: KASAN: slab-use-after-free in __audit_inode+0x45e/0xa10
Read of size 8 by task iou-wrk-422/433
Look the record up by identity among the records the current context
owns instead. Every record on names_list holds a reference on its
filename, so a match cannot name a freed one. Clearing the back-pointer
in audit_free_names() would not be enough on its own: the freeing and
reading contexts are different tasks, so the store races the read, and
audit_free_names() hands the same preallocated_names[] slot back out at
the same address, so validating the pointer by address accepts a
recycled record.
Mainline fixed this differently, in commit 9fa3ec84587c ("allow
incomplete imports of filenames"), part of a series that reworks
getname_flags() and does not apply to this tree.
Signed-off-by: Ameer Hamza <ameer.hamza@truenas.com>
(cherry picked from commit c6e5cc0)
ixhamza
approved these changes
Sep 4, 2026
Author
Member
|
time 14:00 |
Author
|
This PR has been merged and conversations have been locked. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the panics seen on 6.18 during truenas_s3 testing. They all trace to one bug, a use-after-free in
__audit_inode()reached from io_uring path operations, analysed by @anodos325 from the pstore dumps. Reproducible on both our 6.18 and 6.12 trees, but scoped to 6.18 here since 6.12 has no io_uring callers that pass pathnames, Samba'svfs_io_uringonly submits fd-based data ops which take nostruct filename. One thing to call out, clearing->anamealone isn't enough. It covers the task-work path but notio-wq, where the worker can load the pointer before the submitter clears it and dereference it after, so the patch also validates the pointer in__audit_inode()before using it. One behaviour change too,io_uring_enter(2)no longer logs its own PATH record for these ops. That was the broken one anyway, it reported an inodeio_uring_enter(2)never looked up. The op is still audited on the URINGOP event and audit used to logname=(null)for these, now it logs the real path.This is a targeted fix rather than mainline's approach, and that's the reason for keeping it downstream only. Mainline fixed it in io_uring instead, so it never hands audit a filename from another context. Ours just stops audit following the stale pointer. I did try backporting mainline's, but it's one commit out of a series that rewrites
getname_flags(), 266 lines across 6 files includinglinux/fs.h. Since we update our kernel trees actively, that would drift us from LTS. Stable can't take mainline's either, it caps patches at 100 lines, and the series has noFixes:tag orCc: stableso the tooling never saw it. 27 moves to a 7.x kernel which already has the proper fix, so this carry has a natural end.Testing
Ran under KASAN with audit rules loaded, driving the affected opcodes over both the io-wq and task-work paths. 6.18.48 goes from 4879 reports to 0, and 0 with no rules loaded. Ordinary syscall audit records are unchanged, and an inode-keyed rule still matches the io_uring operations, checked against stock and patched kernels.
Original PR: #351