[PATCH AUTOSEL 6.19-5.10] audit: add fchmodat2() to change attributes class

Sasha Levin <[email protected]>
Newsgroups org.kernel.vger.audit,dev.linux.lists.patches,org.kernel.vger.linux-arch,org.kernel.vger.stable
Message-ID <[email protected]>
From: Jeffrey Bencteux <[email protected]>

[ 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 <[email protected]>
Signed-off-by: Paul Moore <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.