[PATCH AUTOSEL 7.0-6.18] um: fix address-of CMSG_DATA() rvalue in stub

Sasha Levin <[email protected]>
Newsgroups gmane.linux.uml.devel,gmane.linux.kernel.stable,gmane.linux.kernel
Message-ID <[email protected]>
From: "Marcel W. Wysocki" <[email protected]>

[ Upstream commit 4076f7329832074196e050def49d22265fce2021 ]

The UML stub takes the address of CMSG_DATA(fd_msg):

    fd_map = (void *)&CMSG_DATA(fd_msg);

CMSG_DATA() is specified by POSIX to return unsigned char *.  Taking
its address is semantically wrong -- the intent is to get a pointer
to the control message data, which is exactly what CMSG_DATA()
already returns.

This happens to compile with glibc because glibc's primary
CMSG_DATA definition accesses a flexible array member:

    #define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data)

An array lvalue can have its address taken, and &array yields the
same address as array.  However, glibc also has an alternative
definition that uses pointer arithmetic (returning an rvalue), and
musl's definition always uses pointer arithmetic:

    /* musl */
    #define CMSG_DATA(cmsg) \
        ((unsigned char *)(((struct cmsghdr *)(cmsg)) + 1))

Taking the address of an rvalue is a hard error in C, so the
current code fails to compile with musl libc.

Remove the erroneous & operator.  The resulting code is correct
regardless of the CMSG_DATA implementation -- it simply assigns the
data pointer, which is what the subsequent code (fd_map[--num_fds])
expects.

No functional change with glibc; fixes the build with musl.

Signed-off-by: Marcel W. Wysocki <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

LLM Generated explanations, may be completely bogus:

Now I have enough information to provide a thorough analysis.

## Phase 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Parse the Subject Line
Record: [arch/um] [fix] Fixes address-of operator applied to CMSG_DATA()
macro which is an rvalue under musl libc, breaking UML build with musl.

### Step 1.2: Parse All Commit Message Tags
Record:
- `Signed-off-by: Marcel W. Wysocki <[email protected]>` (author)
- `Link:
  https://patch.msgid.link/[email protected]`
  (lore link)
- `Signed-off-by: Johannes Berg <[email protected]>` (UML
  maintainer applied)
- No `Fixes:` tag, no `Reported-by:`, no `Reviewed-by:`, no explicit
  `Cc: stable` (expected)

### Step 1.3: Analyze the Commit Body
Record: The commit explains in depth:
- Bug: UML stub does `fd_map = (void *)&CMSG_DATA(fd_msg);`
- Root cause: POSIX specifies `CMSG_DATA()` returns `unsigned char *`;
  the `&` operator applied to an rvalue is a hard C error
- Why it compiles with glibc: glibc's primary macro accesses a flexible
  array member (lvalue)
- Why it fails with musl: musl always uses pointer arithmetic (rvalue)
- Fix: Remove the `&` operator - result is correct for any `CMSG_DATA()`
  implementation
- Impact: "No functional change with glibc; fixes the build with musl."

### Step 1.4: Detect Hidden Bug Fixes
Record: Not hidden - this is explicitly stated as a build fix. It also
has semantic merit (even under glibc's primary definition,
`&array_member` followed by a void* cast is nonsensical - you get the
array address, same as without `&`).

## Phase 2: DIFF ANALYSIS

### Step 2.1: Inventory the Changes
Record: 1 file changed, 1 insertion, 1 deletion. Single character
removal (`&`) in `arch/um/kernel/skas/stub.c` inside
`stub_signal_interrupt()`. Classification: minimal surgical fix.

### Step 2.2: Code Flow Change
Record:
- Before: `fd_map = (void *)&CMSG_DATA(fd_msg);` - takes address of
  expression returned by `CMSG_DATA()`
- After: `fd_map = (void *)CMSG_DATA(fd_msg);` - uses the pointer
  returned by `CMSG_DATA()` directly
- With glibc's primary macro (flexible array): `&array` == `array`, so
  result is identical
- With musl (or glibc alternative): before = build error; after = works
- Path: normal path (FD handling during stub signal interrupt)

### Step 2.3: Identify the Bug Mechanism
Record: Build fix / portability issue (category h - hardware workarounds
is not a match; this is a build fix category). The existing code uses a
macro in a way that violates POSIX's return-type contract and fails on
conforming implementations.

### Step 2.4: Fix Quality
Record: Fix is trivially correct. Since `CMSG_DATA()` already returns
`unsigned char *`, casting that to `(void *)` is exactly what's needed.
Zero regression risk on glibc - the resulting pointer value is
identical.

## Phase 3: GIT HISTORY INVESTIGATION

### Step 3.1: Blame the Changed Lines
Record: The buggy line was introduced in commit `e92e2552858142b` ("um:
pass FD for memory operations when needed", June 2, 2025), which landed
in v6.16.

### Step 3.2: Follow the Fixes: Tag
Record: No Fixes: tag, but git blame identifies `e92e2552858142b` as the
introducing commit. That commit is in v6.16 and all subsequent stable
trees (6.16.y, 6.17.y, 6.18.y, 6.19.y).

### Step 3.3: Check File History
Record: `git log v6.16..v7.0 -- arch/um/kernel/skas/stub.c` returns
empty - no intervening changes between v6.16 and v7.0 in this file. This
means the fix will apply cleanly to every stable tree from 6.16.y
onward.

### Step 3.4: Author's Other Commits
Record: Author Marcel W. Wysocki has 2 commits in linux-next, both musl
compatibility fixes for UML. First-time contributor in this area.
Maintainer Johannes Berg (UML maintainer) applied the patch.

### Step 3.5: Dependent/Prerequisite Commits
Record: Standalone fix. Part of a 2-patch musl series, but patch 2/2
(struct sigcontext redefinition) is independent - they don't depend on
each other.

## Phase 4: MAILING LIST RESEARCH

### Step 4.1: Original Patch Discussion
Record: Found via `b4 dig`: https://lore.kernel.org/all/20260215142803.1
[email protected]/
- Series: v1 only (no revisions)
- No reviewer comments captured in the mbox thread (only the 2 patches
  themselves)
- Patch applied as-is by Johannes Berg

### Step 4.2: Who Reviewed
Record: Originally addressed to UML maintainers Richard Weinberger,
Anton Ivanov, Johannes Berg, [email protected], linux-
[email protected]. Applied by Johannes Berg (subsystem maintainer).

### Step 4.3: Bug Report
Record: No syzbot, no external bug report. Bug is self-evident: UML
simply doesn't build under musl.

### Step 4.4: Related Patches
Record: Part of a 2-patch series for musl compatibility; patch 2/2 is an
independent header conflict fix. Prior historical patch series exist
(e.g., `5e1121cd43d4d` "um: Some fixes to build UML with musl" from
2020).

### Step 4.5: Stable Mailing List History
Record: Not separately discussed in stable context. No NAKs or stable
nominations captured.

## Phase 5: CODE SEMANTIC ANALYSIS

### Step 5.1: Key Functions
Record: `stub_signal_interrupt()` in `arch/um/kernel/skas/stub.c`.

### Step 5.2: Callers
Record: `stub_signal_interrupt` is the signal handler installed by UML
for the userspace stub process (SECCOMP-based). It's invoked via signal
delivery - not directly called by normal C code. Entry is from the
SECCOMP trap handler in the userspace stub.

### Step 5.3: Callees
Record: Uses `stub_syscall3(__NR_recvmsg, ...)`, `CMSG_DATA()`,
`syscall_handler(fd_map)`, `stub_syscall2(__NR_close, ...)`.

### Step 5.4: Call Chain / Reachability
Record: This is core UML stub code - runs in every UML process when
handling signals/syscalls. For glibc: change produces the same runtime
behavior. For musl: fixes the build so it runs at all.

### Step 5.5: Similar Patterns
Record: Prior musl compatibility patches exist (e.g., `5e1121cd43d4d`).
This is a continuation of making UML buildable under non-glibc C
libraries.

## Phase 6: STABLE TREE ANALYSIS

### Step 6.1: Buggy Code in Stable?
Record: Verified via `git grep` on tags - `fd_map = (void
*)&CMSG_DATA(fd_msg);` is present verbatim in v6.16, v6.17, v6.18,
v6.19. Introduced in v6.16 via commit `e92e2552858142b`.

### Step 6.2: Backport Complications
Record: No churn in the file between v6.16 and v7.0 (the diff is against
identical context). Fix applies cleanly to all affected stable trees
with zero modification required.

### Step 6.3: Related Fixes in Stable
Record: None - this is the first fix for this specific issue.

## Phase 7: SUBSYSTEM CONTEXT

### Step 7.1: Subsystem Criticality
Record: arch/um (User-Mode Linux). Niche but real users (CI testing,
isolation, security research). Criticality for affected users: CORE (UML
doesn't build at all with musl).

### Step 7.2: Subsystem Activity
Record: Active - UML gets regular updates, with musl support being
periodically improved (2020 series, 2026 series).

## Phase 8: IMPACT AND RISK ASSESSMENT

### Step 8.1: Who Is Affected
Record: UML users on musl-based distributions (Alpine Linux, Void Linux
musl variant, embedded systems). Anyone attempting to build UML with a
non-glibc libc. Glibc users: unaffected.

### Step 8.2: Trigger Conditions
Record: Trigger = attempting to build arch/um with musl libc. 100% of
musl build attempts fail at this line in v6.16+.

### Step 8.3: Failure Mode Severity
Record: Build failure → UML cannot be built at all on affected
configurations. Severity: HIGH for affected users (blocker), NONE for
glibc users.

### Step 8.4: Risk-Benefit Ratio
Record:
- BENEFIT: Enables UML build for musl libc users. Build fix category,
  explicitly allowed.
- RISK: Near-zero. With glibc's primary definition, `&array == array`,
  so the cast to `(void *)` produces the identical pointer value. No
  runtime change.
- Ratio: Clearly favorable.

## Phase 9: FINAL SYNTHESIS

### Step 9.1: Evidence Compilation
FOR backport:
- One-character build fix with zero runtime impact for glibc users
- Falls under explicit "BUILD FIXES" stable exception category
- Buggy code exists in all active stable trees (6.16.y through 6.19.y)
- Applied cleanly (no file churn since introduction)
- Applied by subsystem maintainer
- The semantic argument is also correct: taking `&` of `CMSG_DATA()`'s
  return is wrong per POSIX

AGAINST backport:
- No explicit `Cc: stable` (expected, not disqualifying)
- No `Fixes:` tag (expected, not disqualifying)
- Niche subsystem (UML + musl) - but still real users

### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? YES - trivial one-char removal,
   semantically correct
2. Fixes a real bug? YES - build failure
3. Important issue? YES - build fix (explicit stable exception category)
4. Small and contained? YES - 1 line
5. No new features or APIs? YES
6. Apply to stable trees? YES - clean apply to all affected trees

### Step 9.3: Exception Category
Record: BUILD FIX - explicitly allowed in stable per guidelines: "Fixes
for compilation errors or warnings... These are critical for users who
need to build the kernel."

### Step 9.4: Decision
YES - classic build fix with:
- Trivial, obviously correct change (1 char)
- Zero regression risk for glibc users (unchanged pointer value)
- Enables musl libc builds which are currently broken
- Buggy code in v6.16.y through v6.19.y
- Clean apply to all affected stable trees

## Verification

- [Phase 1] Parsed commit message: author Marcel W. Wysocki, applied by
  Johannes Berg (UML maintainer), lore Link present, no Fixes:/Reported-
  by:/stable tags (expected for review pipeline)
- [Phase 2] Diff analysis: 1 file, +1/-1, removes `&` from `fd_map =
  (void *)&CMSG_DATA(fd_msg);` in `stub_signal_interrupt()`
- [Phase 3] `git log --oneline -- arch/um/kernel/skas/stub.c`: buggy
  line introduced in commit `e92e2552858142b` ("um: pass FD for memory
  operations when needed")
- [Phase 3] `git tag --contains e92e2552858142b`: confirmed present in
  v6.16 through v7.0 (all active stable trees)
- [Phase 3] `git log v6.16..v7.0 -- arch/um/kernel/skas/stub.c`: empty -
  no intervening changes, clean apply guaranteed
- [Phase 3] `git log --author="Marcel W. Wysocki"`: 2 commits total,
  both musl compatibility fixes for UML
- [Phase 4] `b4 dig -c 4076f73298320`: found at https://lore.kernel.org/
  all/[email protected]/
- [Phase 4] `b4 dig -a`: only v1 exists, no revisions
- [Phase 4] `b4 dig -w`: addressed to UML maintainers (Richard
  Weinberger, Anton Ivanov, Johannes Berg) and linux-um/linux-kernel
  lists
- [Phase 4] `b4 dig -m /tmp/thread.mbox`: mbox contains the 2 patches of
  the series; no reviewer replies present
- [Phase 6] `git grep -n "fd_map = (void \*)&CMSG_DATA" v6.16 v6.17
  v6.18 v6.19 -- arch/um/kernel/skas/stub.c`: buggy code confirmed
  present in all four stable release tags at line 149
- [Phase 6] Same line count (149) in all versions confirms no contextual
  drift, fix applies cleanly
- [Phase 8] Failure mode: compilation error when building UML with musl
  libc - blocks build entirely
- UNVERIFIED: Exact range of glibc versions that use the alternative
  (rvalue) `CMSG_DATA` definition - commit message asserts both
  definitions exist but did not verify personally; however this does not
  affect the decision (the fix is correct in either case).

**YES**

 arch/um/kernel/skas/stub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/um/kernel/skas/stub.c b/arch/um/kernel/skas/stub.c
index 67cab46a602cf..e09216a20cb57 100644
--- a/arch/um/kernel/skas/stub.c
+++ b/arch/um/kernel/skas/stub.c
@@ -146,7 +146,7 @@ stub_signal_interrupt(int sig, siginfo_t *info, void *p)
 		/* Receive the FDs */
 		num_fds = 0;
 		fd_msg = msghdr.msg_control;
-		fd_map = (void *)&CMSG_DATA(fd_msg);
+		fd_map = (void *)CMSG_DATA(fd_msg);
 		if (res == iov.iov_len && msghdr.msg_controllen > sizeof(struct cmsghdr))
 			num_fds = (fd_msg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
 
-- 
2.53.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.