From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Jeffrey Bencteux <jeff@bencteux.fr>,
Paul Moore <paul@paul-moore.com>, Sasha Levin <sashal@kernel.org>,
eparis@redhat.com, audit@vger.kernel.org,
linux-arch@vger.kernel.org
Subject: [PATCH AUTOSEL 6.19-5.10] audit: add fchmodat2() to change attributes class
Date: Tue, 10 Feb 2026 18:30:51 -0500 [thread overview]
Message-ID: <20260210233123.2905307-6-sashal@kernel.org> (raw)
In-Reply-To: <20260210233123.2905307-1-sashal@kernel.org>
From: Jeffrey Bencteux <jeff@bencteux.fr>
[ Upstream commit 4f493a6079b588cf1f04ce5ed6cdad45ab0d53dc ]
fchmodat2(), introduced in version 6.6 is currently not in the change
attribute class of audit. Calling fchmodat2() to change a file
attribute in the same fashion than chmod() or fchmodat() will bypass
audit rules such as:
-w /tmp/test -p rwa -k test_rwa
The current patch adds fchmodat2() to the change attributes class.
Signed-off-by: Jeffrey Bencteux <jeff@bencteux.fr>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have a complete picture. Let me write up the full analysis.
---
## Detailed Analysis
### 1. COMMIT MESSAGE ANALYSIS
The commit message is clear and explicit about the bug:
- **Problem**: `fchmodat2()`, introduced in kernel v6.6, was never added
to the audit subsystem's "change attributes" (chattr) class. This
means that any process calling `fchmodat2()` to change a file's
permissions **completely bypasses audit rules** that monitor attribute
changes (the `-p a` permission in audit rules, e.g., `-w /tmp/test -p
rwa -k test_rwa`).
- **Impact**: This is a **security audit bypass**. Users who deploy
audit rules to track attribute changes on sensitive files (a standard
security and compliance practice) will miss `fchmodat2()` calls
entirely. An attacker or any process using `fchmodat2()` instead of
`chmod()`/`fchmodat()` can change file permissions without triggering
any audit record.
- **Author**: Jeffrey Bencteux, signed off by Paul Moore (the audit
subsystem maintainer), which is a strong indicator of correctness.
### 2. CODE CHANGE ANALYSIS
The patch is **3 lines** in a single file:
```c
#ifdef __NR_fchmodat2
__NR_fchmodat2,
#endif
```
Added to `include/asm-generic/audit_change_attr.h`, right after the
existing `__NR_fchmodat` entry. This is the header file that is
`#include`d by the `chattr_class[]` arrays across all architectures
(x86, sparc, s390, powerpc, parisc, alpha, and generic lib/audit.c +
compat_audit.c). These arrays define which syscall numbers are in the
"change attributes" audit class.
The mechanism is straightforward:
- The `audit_match_perm()` function in `kernel/auditsc.c` (line 167-169)
checks if a syscall number (`ctx->major`) matches `AUDIT_CLASS_CHATTR`
when the audit rule has `AUDIT_PERM_ATTR` set.
- Without `fchmodat2` in the `chattr_class[]` array,
`audit_match_class(AUDIT_CLASS_CHATTR, __NR_fchmodat2)` returns 0, so
the rule never fires for `fchmodat2()`.
Critically, `fchmodat2()` (defined in `fs/open.c` line 704-708) calls
the same `do_fchmodat()` function as `fchmodat()` (line 710-714). They
are functionally identical for attribute changes - the only difference
is `fchmodat2` adds a `flags` parameter. So there's no question that
`fchmodat2` belongs in the chattr class.
### 3. CLASSIFICATION
This is a **security bug fix** — specifically, an audit bypass. It is
NOT a new feature. The `fchmodat2` syscall already exists; this merely
ensures the audit subsystem correctly classifies it alongside the
equivalent `fchmodat` syscall.
This fits squarely into the category of fixes that are critical for
stable:
- Environments running Linux audit (virtually all enterprise
deployments, compliance-regulated systems) are silently missing
attribute change events
- This is a **compliance gap** (PCI-DSS, HIPAA, SOX, FedRAMP all require
file integrity monitoring via audit)
- The `#ifdef __NR_fchmodat2` guard ensures it compiles safely on older
architectures where the syscall might not be defined
### 4. SCOPE AND RISK ASSESSMENT
- **Size**: 3 lines added, 1 file changed — the smallest possible change
- **Risk**: Near zero. The change only adds a syscall number to an
existing list. The `#ifdef` guard protects against the case where
`__NR_fchmodat2` is not defined. There is no behavioral change to any
existing code path.
- **Could this break anything?**: No. Adding a new entry to the
chattr_class array only means that `fchmodat2` syscalls will now
correctly trigger audit rules with attribute-change permissions.
There's no way this causes a regression — at worst, users would see
additional (correct) audit records they were previously missing.
### 5. USER IMPACT
- **Who is affected**: Every single system running Linux audit with
attribute-change monitoring rules on kernels 6.6+. This includes
enterprise distributions (RHEL, SLES, Ubuntu), compliance-critical
infrastructure, and security-sensitive deployments.
- **Severity**: HIGH — this is a silent security audit bypass. Users
believe they are monitoring attribute changes, but `fchmodat2()` slips
through undetected.
- **Real-world trigger**: glibc and other C libraries may route
`chmod()`-like calls through `fchmodat2()` if available. The commit
message explicitly gives an example of the audit rule being bypassed.
### 6. DEPENDENCY CHECK
- **fchmodat2 syscall exists in v6.6**: Confirmed — `__NR_fchmodat2` is
defined as syscall 452 in `include/uapi/asm-generic/unistd.h` since
v6.6.
- **Clean application to v6.6**: Confirmed — the context lines
(`__NR_fchownat`, `__NR_fchmodat`, `#endif`, `#ifdef __NR_chown32`)
are identical in v6.6's version of the file.
- **No other dependencies**: The patch is completely self-contained. It
doesn't depend on any other commit. The `setxattrat`/`removexattrat`
additions from commit 6140be90ec70c are in different positions in the
file and don't affect the context.
- **Applicable to**: 6.6.y, 6.1.y (if fchmodat2 was backported there —
it wasn't since fchmodat2 was introduced in 6.6), and all stable trees
≥6.6.
### 7. STABILITY INDICATORS
- Signed off by Paul Moore, the audit subsystem maintainer
- The pattern is well-established — the same file has entries for every
attribute-changing syscall, each guarded by `#ifdef __NR_*`
- The commit is in the `security-next` tree, in the pipeline for
mainline
### 8. COMPARISON WITH PRECEDENT
The same file has been modified before for identical reasons:
- `262fd3aad6110` ("audit: Modify a set of system calls in audit class
definitions") — added syscalls to audit classes
- `af2951325bd6c` ("audit: make link()/linkat() match 'attribute change'
predicate") — added `link`/`linkat` to the same class
- `6140be90ec70c` ("fs/xattr: add *at family syscalls") — added
`setxattrat`/`removexattrat` to the same header
All of these follow the exact same pattern of adding a syscall number to
an audit class list.
### Summary
This is a textbook stable backport candidate:
1. **Obviously correct**: It adds 3 lines that are structurally
identical to the existing `fchmodat` entry, guarded by `#ifdef`
2. **Fixes a real bug**: Silent audit bypass of attribute changes via
`fchmodat2()`
3. **Security impact**: Allows processes to bypass audit monitoring —
this is a security-relevant gap
4. **Small and contained**: 3 lines, 1 file, no behavioral side effects
5. **No new features**: Just ensures existing audit infrastructure
correctly covers an existing syscall
6. **Applies cleanly to stable**: Context matches v6.6 exactly; no
dependencies
7. **Signed off by subsystem maintainer**: Paul Moore (audit maintainer)
The fix addresses a security audit bypass that has existed since v6.6
(when `fchmodat2` was introduced) — roughly 2+ years of every stable
kernel silently failing to audit attribute changes made via
`fchmodat2()`. This is particularly critical for enterprise and
compliance-regulated environments.
**YES**
include/asm-generic/audit_change_attr.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h
index cc840537885fb..ddd90bbe40dfc 100644
--- a/include/asm-generic/audit_change_attr.h
+++ b/include/asm-generic/audit_change_attr.h
@@ -26,6 +26,9 @@ __NR_fremovexattr,
__NR_fchownat,
__NR_fchmodat,
#endif
+#ifdef __NR_fchmodat2
+__NR_fchmodat2,
+#endif
#ifdef __NR_chown32
__NR_chown32,
__NR_fchown32,
--
2.51.0
next prev parent reply other threads:[~2026-02-10 23:31 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-10 23:30 [PATCH AUTOSEL 6.19-6.12] i3c: mipi-i3c-hci: Reset RING_OPERATION1 fields during init Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-5.15] gfs2: fiemap page fault fix Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.18] dlm: fix recovery pending middle conversion Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.6] smb: client: prevent races in ->query_interfaces() Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.12] i3c: mipi-i3c-hci: Ensure proper bus clean-up Sasha Levin
2026-02-11 7:56 ` Adrian Hunter
2026-02-10 23:30 ` Sasha Levin [this message]
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.12] btrfs: fallback to buffered IO if the data profile has duplication Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19] btrfs: don't BUG() on unexpected delayed ref type in run_one_delayed_ref() Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.12] i3c: mipi-i3c-hci-pci: Add System Suspend support Sasha Levin
2026-02-11 7:57 ` Adrian Hunter
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.18] hfsplus: fix volume corruption issue for generic/480 Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.18] kselftest/kublk: include message in _Static_assert for C11 compatibility Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.12] dlm: validate length in dlm_search_rsb_tree Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.18] i3c: mipi-i3c-hci: Stop reading Extended Capabilities if capability ID is 0 Sasha Levin
2026-02-10 23:30 ` [PATCH AUTOSEL 6.19-6.1] fs/buffer: add alert in try_to_free_buffers() for folios without buffers Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-5.15] i3c: master: svc: Initialize 'dev' to NULL in svc_i3c_master_ibi_isr() Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-6.12] statmount: permission check should return EPERM Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-5.10] audit: add missing syscalls to read class Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-5.10] hfsplus: pretend special inodes as regular files Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-5.10] hfsplus: fix volume corruption issue for generic/498 Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-6.18] netfs: when subreq is marked for retry, do not check if it faced an error Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19] hfs: Replace BUG_ON with error handling for CNID count checks Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-6.1] smb: client: add proper locking around ses->iface_last_update Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-6.6] btrfs: handle user interrupt properly in btrfs_trim_fs() Sasha Levin
2026-02-10 23:31 ` [PATCH AUTOSEL 6.19-5.10] minix: Add required sanity checking to minix_check_superblock() Sasha Levin
2026-02-11 7:56 ` [PATCH AUTOSEL 6.19-6.12] i3c: mipi-i3c-hci: Reset RING_OPERATION1 fields during init Adrian Hunter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260210233123.2905307-6-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=audit@vger.kernel.org \
--cc=eparis@redhat.com \
--cc=jeff@bencteux.fr \
--cc=linux-arch@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=paul@paul-moore.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox