Skip to content

fix(syswrap): return the client's auxv from prctl(PR_GET_AUXV) - #49

Merged
lvaroqui merged 1 commit into
masterfrom
cod-3810-valgrind-codspeed-leaks-the-host-auxv-through
Oct 12, 2026
Merged

lvaroqui merged 1 commit into
masterfrom
cod-3810-valgrind-codspeed-leaks-the-host-auxv-through

Conversation

@lvaroqui

@lvaroqui lvaroqui commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Under valgrind, prctl(PR_GET_AUXV) (Linux 6.4+) reached the kernel unchanged and returned the auxv the kernel saved when it exec'd the valgrind tool, not the program's. getauxval() and /proc/self/auxv already report the program's auxv, so the two disagreed.

AT_EXECFN came back as .../callgrind-amd64-linux, which breaks multicall binaries that pick their behavior from it. rust-coreutils 0.8.0, shipped with Ubuntu 26.04, failed every command under valgrind with coreutils: unknown program 'callgrind-amd64-linux'. Its 0.10.0 update no longer reads its name this way, but any program calling PR_GET_AUXV is affected, on any distro.

The prctl wrapper now answers PR_GET_AUXV itself and keeps the kernel's contract:

  • It returns a copy of the client's auxv taken at startup, where the fake /proc/self/auxv is created, like the kernel's copy saved at exec. Writing to, protecting or unmapping the original stack afterwards does not affect it.
  • It returns the kernel's own buffer size, asked with a zero-size call, and zero-pads after the auxv, so the return value matches native (448 bytes on amd64 here).
  • It copies at most the caller's size.
  • Nonzero arg4/arg5 fail with EINVAL, and a buffer the caller cannot write (unmapped or read-only) with EFAULT. Kernels without PR_GET_AUXV return their own EINVAL.

The wrapper completes the call itself, so it clears SfMayBlock: syswrap-main asserts that a call completed successfully in the pre-handler does not carry it.

callgrind/tests/prctl_get_auxv checks AT_EXECFN, that the whole vector equals the one on the stack and later writes to the stack copy do not show, that the size equals the kernel's (taken from a native run) with zero padding up to it, short buffers, EINVAL for arg4/arg5, and EFAULT for unmapped and read-only buffers. It passes natively, fails without this fix, and is built only when the system headers define PR_GET_AUXV (a new configure check) and skipped on kernels older than 6.4. Under memcheck the only report is the test's deliberate unmapped buffer, so the copied bytes are marked defined. Only amd64 was verified locally.

This was first stacked on the 3.27.1 merge (#48), which we're not merging; it now targets master and was verified on the 3.26 base.

Closes COD-3810

@lvaroqui
lvaroqui added this pull request to stack #50 October 9, 2026 11:59
@codspeed

codspeed Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 84 untouched benchmarks
⏩ 60 skipped benchmarks1


Comparing cod-3810-valgrind-codspeed-leaks-the-host-auxv-through (c838048) with master (47784c0)

Open in CodSpeed

Footnotes

  1. 60 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@lvaroqui
lvaroqui marked this pull request as ready for review October 9, 2026 12:24
@greptile-apps

greptile-apps Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the previous stack-access crash is fixed.

Summary

PR_GET_AUXV now returns a private copy of the client's startup vector rather than reading the original stack.

  • Later stack changes cannot change the returned vector.
  • The added test changes a stack value and checks that the saved vector stays unchanged.
  • The previous stack-access finding is fixed. No new actionable issues were found.

Diagram

sequenceDiagram
    participant Startup as Valgrind startup
    participant Saved as Private saved vector
    participant Client as Client program
    participant Wrapper as prctl wrapper
    participant Kernel as Linux kernel
    Startup->>Saved: Copy client's initial vector
    Client->>Wrapper: PR_GET_AUXV(buffer, size)
    Wrapper->>Kernel: Query supported operation and buffer size
    Kernel-->>Wrapper: Size or error
    Wrapper->>Saved: Read startup copy
    Wrapper-->>Client: Bounded copy, zero padding, full size
Loading

Reviews (3) · Last reviewed commit: "fix(syswrap): answer PR_GET_AUXV from a ..." · Reviewed by Greptile

Comment thread coregrind/m_syswrap/syswrap-linux.c Outdated
Comment thread callgrind/tests/prctl_get_auxv.vgtest Outdated
Comment thread callgrind/tests/prctl_get_auxv.c Outdated
@lvaroqui
lvaroqui force-pushed the cod-3810-valgrind-codspeed-leaks-the-host-auxv-through branch from 305a73e to 8df58f1 Compare October 9, 2026 12:45
Comment thread coregrind/m_syswrap/syswrap-linux.c Outdated
@lvaroqui
lvaroqui requested a review from not-matthias October 9, 2026 15:19

@not-matthias not-matthias left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job!

Comment thread callgrind/tests/prctl_get_auxv.c Outdated
@lvaroqui
lvaroqui force-pushed the cod-3810-valgrind-codspeed-leaks-the-host-auxv-through branch 4 times, most recently from bbd33da to 50083a6 Compare October 12, 2026 13:50
@lvaroqui
lvaroqui removed this pull request from stack #50 October 12, 2026 13:50
@lvaroqui
lvaroqui changed the base branch from cod-3818-bring-upstream-valgrind-3271-to-valgrind-codspeed to master October 12, 2026 13:50
The kernel answers PR_GET_AUXV (Linux 6.4+) with the auxv it saved when
it exec'd the Valgrind tool, so a program reading its auxv this way got
the tool's entries, including AT_EXECFN (e.g. .../callgrind-amd64-linux),
while getauxval() and /proc/self/auxv already report the client's.
Multicall binaries that pick their behavior from AT_EXECFN, such as
rust-coreutils 0.8.0 shipped with Ubuntu 26.04, failed with "unknown
program 'callgrind-amd64-linux'".

Handle PR_GET_AUXV in the prctl wrapper: copy the client auxv, zero-padded
to the size the kernel reports, into the caller's buffer and return that
size. Keep the kernel's EINVAL for nonzero arg4/arg5 and on kernels
without the option, and EFAULT for an unaddressable buffer.

Closes COD-3810
Co-Authored-By: Claude <noreply@anthropic.com>
@lvaroqui
lvaroqui force-pushed the cod-3810-valgrind-codspeed-leaks-the-host-auxv-through branch from 50083a6 to c838048 Compare October 12, 2026 13:57
@lvaroqui
lvaroqui merged commit 937a587 into master Oct 12, 2026
10 checks passed
@lvaroqui
lvaroqui deleted the cod-3810-valgrind-codspeed-leaks-the-host-auxv-through branch October 12, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants