Skip to content

stdbuf: Search libstdbuf without /proc#11166

Open
oech3 wants to merge 1 commit intouutils:mainfrom
oech3:stdbuf-proc
Open

stdbuf: Search libstdbuf without /proc#11166
oech3 wants to merge 1 commit intouutils:mainfrom
oech3:stdbuf-proc

Conversation

@oech3
Copy link
Contributor

@oech3 oech3 commented Mar 1, 2026

Closes #11134

@oech3 oech3 force-pushed the stdbuf-proc branch 2 times, most recently from b34ac44 to e860b9d Compare March 1, 2026 09:30
@codspeed-hq
Copy link

codspeed-hq bot commented Mar 1, 2026

Merging this PR will not alter performance

✅ 298 untouched benchmarks
⏩ 48 skipped benchmarks1


Comparing oech3:stdbuf-proc (473f601) with main (f0c71b2)

Open in CodSpeed

Footnotes

  1. 48 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.

@github-actions
Copy link

github-actions bot commented Mar 1, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/misc/io-errors is no longer failing!
Congrats! The gnu test tests/tail/retry is no longer failing!
Note: The gnu test tests/basenc/bounded-memory is now being skipped but was previously passing.

@oech3 oech3 marked this pull request as ready for review March 1, 2026 09:51
@oech3
Copy link
Contributor Author

oech3 commented Mar 1, 2026

Test requires unshare. So I cannot add test.

@sylvestre sylvestre requested a review from Ecordonnier March 4, 2026 19:31
@Ecordonnier
Copy link
Collaborator

I agree to merge this, but in principle it's a workaround for a bug in the rust standard library in my opinion. The AIX implementation for instance does use argv[0] ( link ), while the linux implementation in the same file relies purely on /proc/self/exe ( link ).

The cleanest solution IMO would be to also fix the standard library. I have added a comment to rust-lang/rust#46090 (comment) , but maybe you're motivated to send a PR?

// use argv[0] to support masked /proc
if let Some(exe_dir) = std::env::args_os()
.next()
.and_then(|a| PathBuf::from(a).parent().map(std::path::Path::to_path_buf))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think this works if you call stdbuf as "stdbuf" and rely on PATH:

PathBuf::from("stdbuf").parent()  // Returns Some("")  (empty path!)

You need to use the logic from https://github.com/rust-lang/rust/blob/b90dc1e597db0bbc0cab0eccb39747b1a9d7e607/library/std/src/sys/pal/unix/os.rs#L122C9-L122C17 which checks if argv[0] contains a "/" character.

@oech3 oech3 force-pushed the stdbuf-proc branch 3 times, most recently from 08dd06d to 09a1eae Compare March 5, 2026 12:53
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

GNU testsuite comparison:

Congrats! The gnu test tests/misc/io-errors is no longer failing!
Note: The gnu test tests/basenc/bounded-memory is now being skipped but was previously passing.

@oech3 oech3 force-pushed the stdbuf-proc branch 3 times, most recently from 4766d1b to a63b468 Compare March 5, 2026 16:51
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

GNU testsuite comparison:

Skipping an intermittent issue tests/cut/bounded-memory (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/date/resolution (passes in this run but fails in the 'main' branch)

@oech3

This comment was marked as resolved.

@oech3 oech3 force-pushed the stdbuf-proc branch 2 times, most recently from 9843b27 to f8107e8 Compare March 6, 2026 09:09
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/tail/follow-name (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/pr/bounded-memory (passes in this run but fails in the 'main' branch)

@oech3 oech3 force-pushed the stdbuf-proc branch 2 times, most recently from b25c43c to 5017aaf Compare March 6, 2026 09:28
@github-actions
Copy link

github-actions bot commented Mar 6, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/pr/bounded-memory (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Note: The gnu test tests/seq/seq-epipe is now being skipped but was previously passing.
Congrats! The gnu test tests/tail/tail-n0f is now passing!

@Ecordonnier
Copy link
Collaborator

I don't really like the latest change:

  1. this adds the rustix crate as dependency to avoid using the unsafe function "libc::getauxval()". However a safe wrapper would be only a few lines of code, compared to adding the rustix crate, which adds a lot of complexity IMO:
#[cfg(any(target_os = "linux", target_os = "android"))]
mod auxv {
    use std::ffi::CStr;
    
    /// Safely retrieve the AT_EXECFN auxiliary vector value.
    /// Returns None if not available or null.
    pub fn execfn() -> Option<&'static CStr> {
        unsafe {
            let ptr = libc::getauxval(libc::AT_EXECFN) as *const libc::c_char;
            if ptr.is_null() {
                None
            } else {
                Some(CStr::from_ptr(ptr))
            }
        }
    }
}
  1. Adding rustix for linux and android is only a partial fix, because for instance cygwin also uses /proc/self/exe in the rust standard library implementation ( link ), so cygwin will still have the bug after this PR. Thus I think using argv[0] like you had initially done was better / simpler in this regard: one fix for all platforms

  2. Rustix uses the "raw linux" backend per default, and thus implements getauxval() by:

    • first trying to call prctl (PR_GET_AUXV) ( link ) , which is supported only on linux version > 6.4
    • then falling back to /proc/self/auxv ( link ), which will not work if /proc is not mounted

Because of this, using rustix does not fix the issue for linux kernel versions < 6.4

What about using argv[0] and just checking if there is a "/" in the path, like gnu coreutils does? This would be simpler.

@Ecordonnier
Copy link
Collaborator

I will try to get rust-lang/rust@cada230 merged in the rust standard library. This would be the best solution IMO.

@oech3
Copy link
Contributor Author

oech3 commented Mar 9, 2026

I'm fine to use argv[0] at here as GNU does.
But at upstream, std::env::current_exe, argv[0] is insecure and AT_EXECFN should have highest priority on available platforms. No?

@Ecordonnier
Copy link
Collaborator

Ecordonnier commented Mar 9, 2026

I'm fine to use argv[0] at here as GNU does. But at upstream, std::env::current_exe, argv[0] is insecure and AT_EXECFN should have highest priority on available platforms. No?

I'm not sure.

  • The code block which I'm changing is also executed for "exotic" platforms like cygwin, hurd, nuttx, emscripten, and those may not support AT_EXECFN. So it would require to have a different code path for those platforms.

  • Also the documentation of std::env::current_exe makes it clear that the result should not be relied upon for security, so the fact that argv[0] can be spoofed should not prevent the merge.

  • I was hoping that a change using argv[0] would be easier to upstream, because this is what the AIX implementation in the same file already does.

Maybe you can send a patch using AT_EXECFN in the rust stdlib as follow-up? I'd like to get the "easy to merge" patch merged first.

Edit: I've sent the PR: rust-lang/rust#153603

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.

stdbuf cannot use libstdbuf on the same directory if /proc is masked

2 participants