Missing system calls in the Linux kernel audit subsystem classes (CVE-2025-71239, CVE-2026-23241)
A researcher found that the Linux kernel audit subsystem's syscall classes (used to implement auditd's -p r/w/x/a filesystem watch rules) were missing three relatively new syscalls: fchmodat2, getxattrat, and listxattrat. Because these syscalls weren't hooked into the audit_change_attr/read classes, calling them instead of their older counterparts (fchmodat, getxattr, listxattr) let an attacker change file permissions or read extended attributes (e.g., file capabilities, SELinux labels) without triggering any SYSCALL audit alert, enabling stealthy privilege changes and reconnaissance. The gaps were assigned CVE-2025-71239 and CVE-2026-23241, fixed in kernel v7.0 and backported to LTS branches 5.10 through 6.19.
What it is
Two CVEs — CVE-2025-71239 and CVE-2026-23241 — covering syscalls that were never added to the Linux kernel audit subsystem's classification headers. Auditd "filesystem rules" (watches, -w path -p perms -k key) translate the permission letters r/w/x/a into lists of syscalls hooked in kernel land, defined in per-class header files. Three newer syscalls were absent from the class they belong to: fchmodat2(), getxattrat(), and listxattrat(). A program calling them performs the audited operation without triggering the watch, i.e. a detection bypass.
How it works
Each audit class is a header of __NR_* entries — e.g. /include/asm-generic/audit_read.h lists __NR_listxattr, __NR_getxattr, etc., and /arch/x86/kernel/audit_64.c pulls it in via read_class[] and registers it in audit_classes_init(). A -p r watch fires a SYSCALL alert when any syscall in read_class touches the path (the author shows ls triggering it through lgetxattr/listxattr). fchmodat() was in audit_change_attr.h from the initial definition, but when fchmodat2() was added in kernel v6.6 it was not added to that class header — so an attribute change via fchmodat2() fires no -p a alert. The same omission applied to the *xattrat reads. Kernel syscall-addition docs explicitly note the audit subsystem is a special case that must be updated for analogous new syscalls, and advise a kernel-wide grep of the existing syscall.
Preconditions / Affected
- A system relying on auditd filesystem watch rules for detection (not syscall rules that already name the newer calls).
- Kernels carrying
fchmodat2()(added v6.6) /getxattrat()/listxattrat()but predating the fix. - An actor able to substitute the newer syscall for the classic one (e.g.
fchmodat2instead offchmodat/chmod) to change permissions or read xattrs unobserved.
What to do
The page states the syscalls have now been added upstream, so update to a patched kernel. To confirm your own kernel's exposure, check whether the class headers include the newer entries, and test empirically:
-w /tmp/test.txt -p r -k test_readausearch -k test_read | grep lsstrace ls -lh /tmp/test.txtA watch that fires for fchmodat/listxattr but not for fchmodat2/listxattrat against the same file confirms the gap.
Caveats
The excerpt cuts off mid-proof-of-concept, so the second (fchmodat2) test program and any getxattrat/listxattrat demonstrations aren't shown here. The bypass only concerns watch/class-based rules; rules written to match the specific syscall directly are unaffected.
Organisations named here
- fchmodat2
- getxattrat
- listxattrat
CVEs named here
- CVE-2025-71239
- CVE-2026-23241
Technologies named here
- auditd
- Linux kernel
- ausearch
- strace
- getfattr
- setfattr
- Linux kernel LTS
- setcap
Techniques named here
- Auditd filesystem rule bypass via missing syscalls
- Auditd read rule bypass via missing syscalls
Related in Blue Team & Detection
AI-Coded Malware | Analyzing Vibe-Coded AD Enumeration | Huntress
