Skip to content

Prevent mutating the global environment pointer in CommandExt::exec and opt to use execve and resolve path manually - #157144

Open
asder8215 wants to merge 8 commits into
rust-lang:mainfrom
asder8215:commandext_exec_bug_fix
Open

asder8215 wants to merge 8 commits into
rust-lang:mainfrom
asder8215:commandext_exec_bug_fix

Conversation

@asder8215

@asder8215 asder8215 commented May 30, 2026 •

Copy link
Copy Markdown
Contributor

View all comments

This PR fixes the bug described in #156951 where CommandExt::exec mutating the global environment pointer could cause correctness issue with concurrent exec calls (also this function holds an environment read lock, so it shouldn't cause any writes to the global environment pointer anyways). We do everything within CommandExt::exec via execve than execvp, which means we have to resolve the path manually.

I took reference to what was done in an archived (Feb 2026) upstream mirror of glibc's execvp and execvpe. I also took reference to #55359 on how they implemented the concerned portion of CommandExt::exec with execve. There's also this OpenBSD libc implementation of execvpe that I saw, but I didn't deeply take a look at this one and saw how it differ.

Other than that, I'm unsure how to handle the error ETIMEOUT/TimedOut as glibc breaks parsing through the PATH environment variable value and returns the error while #55359 continues parsing.

Let me know if you also want me to put some of execve code in a helper function or refactor it in other ways.

From @joboet comment in #157144 (comment), this table contain platform behavior on the default fallback path with execvp and whether it invokes shell or not on ENOEXEC.

Target process_spawnp execvp fallback PATH fallback is PATH_DEFPATH posix_spawnp calls shell on ENOEXEC execvp calls shell on ENOEXEC
linux-glibc link link CS_PATH = /bin:/usr/bin (same as confstr(_CS_PATH), but different from _PATH_DEFPATH = /usr/bin:/bin) no, guaranteed to include confstr(_CS_PATH) before glibc 2.15 (below our minimum) yes
macos link link _PATH_DEFPATH = /usr/bin:/bin (notably, this is different from confstr(_CS_PATH) = sysctl(..) = /usr/bin:/bin:/usr/sbin:/sbin) guaranteed by documentation yes yes
linux-musl link link /usr/local/bin:/bin:/usr/bin = _PATH_DEFPATH (not equal to confstr(_CS_PATH) = /bin:/usr/bin yes forwards to __execvpe no
freebsd link link _PATH_DEFPATH = /sbin:/bin:/usr/sbin:/usr/bin: (not equal to confstr(_CS_PATH) = _PATH_STDPATH = /usr/bin:/bin:/usr/sbin:/sbin) guaranteed by documentation forwards to execvpe yes
openbsd link link _PATH_DEFPATH = /usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin (currently equal to confstr(_CS_PATH) = _PATH_STDPATH) guaranteed by documentation forwards to execvpe yes
netbsd link link _PATH_DEFPATH = /usr/bin:/bin:/usr/pkg/bin:/usr/local/bin (not equal to confstr(_CS_PATH = sysctl(..) = _PATH_STDPATH = /usr/bin:/bin:/usr/sbin:/sbin:/usr/pkg/bin:/usr/pkg/sbin:/usr/local/bin:/usr/local/sbin) guaranteed by documentation no yes

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels May 30, 2026
@rustbot

rustbot commented May 30, 2026

Copy link
Copy Markdown
Collaborator

r? @joboet

rustbot has assigned @joboet.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 8 candidates
  • Random selection from Mark-Simulacrum, joboet

@rust-log-analyzer

This comment has been minimized.

@joboet joboet 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.

I highly recommend having a look at the POSIX specification – GNU/Linux mostly follows that, but the specification sometimes leaves some things unspecified and we should be careful not to break those.

Also, this is currently unsound, we cannot perform any memory allocation in do_exec, since it's called after fork for the standard spawn path. You probably need to preallocate some memory when creating the Command (or when setting certain parameters).

View changes since this review

Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
None => c"/bin:/usr/bin".to_bytes_with_nul(),
}
}
None => parent_path.as_bytes_with_nul(),

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.

I recommend moving the environment variable lookup here so that it's only performed when actually needed.

Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 30, 2026
@rustbot

rustbot commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot rustbot added the O-unix Operating system: Unix-like label May 31, 2026
@asder8215
asder8215 requested a review from joboet May 31, 2026 05:02
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 31, 2026
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/pal/unix/conf.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/common.rs Outdated
Comment thread library/std/src/sys/process/unix/common.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 6, 2026
@asder8215
asder8215 requested a review from joboet June 8, 2026 08:36
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 8, 2026
Comment thread library/std/src/sys/process/unix/common/cstring_array.rs Outdated
@rust-log-analyzer

This comment has been minimized.

@asder8215
asder8215 force-pushed the commandext_exec_bug_fix branch from 213bb02 to 8319b09 Compare June 8, 2026 09:23
@rust-log-analyzer

This comment has been minimized.

Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/pal/unix/conf.rs Outdated
Comment thread library/std/src/sys/pal/unix/conf.rs Outdated
assert_failed(index, len);
}

self.ptrs.insert(index, item.into_raw());

@joboet joboet Jun 8, 2026 •

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.

This leaks the string if insert panics (see #155748, I made this mistake before).

View changes since the review

Comment thread library/std/src/sys/process/unix/common.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 8, 2026
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
@asder8215
asder8215 requested a review from joboet June 9, 2026 22:31
@rust-rfcbot rust-rfcbot added to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Sep 25, 2026
@rust-rfcbot

Copy link
Copy Markdown
Collaborator

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

@joboet

joboet commented Sep 25, 2026

Copy link
Copy Markdown
Member

I wanted to ask earlier if we have to wait for libc to be bumped up to use it within stdlib? Or is it possible to bump up libc here and start using _PATH_BSHELL/_PATH_DEFPATH?

You don't have to wait, you can do it here. I'd suggest putting it into a separate commit, just so you could drop it easily if another PR with a bump gets merged in the meantime.

@asder8215

Copy link
Copy Markdown
Contributor Author

You don't have to wait, you can do it here. I'd suggest putting it into a separate commit, just so you could drop it easily if another PR with a bump gets merged in the meantime.

I'm not sure if I could bump up libc here in the rust repo. Looking at the latest libc crate, it's at version 0.2.189 since July 21, 2026, which doesn't have the _PATH_DEFPATH and _PATH_BSHELL constants.

@tgross35 how does release schedule work for libc?

…nd opt to use execve and resolve path manually
…confstr_as_cstring added to get a CString value returned by confstr, added CStringArray::from_ptr, added default_path and shell_argv fields to unix Command, and refactored do_exec code
…om a single passthrough in envp, match on errno values directly instead of ErrorKind, fix shell_argv CStringArray value.
…remove confstr_as_cstr, remove unnecessary shell_argv field/funtions + unused functions from CStringArray, use slice::split to delimit on colons
…cumentation for returning an error from execve
@joboet

joboet commented Oct 20, 2026

Copy link
Copy Markdown
Member

The relevant libc version is now released and already used by std.

@joboet joboet added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 20, 2026
@asder8215

asder8215 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Yep, I saw. I was actually working on it before the notif I received for the with_native_path refactoring.

I have to check a couple of other platforms that wasn't listed earlier to see how execvp works.

  • DragonFlyBSD: uses _PATH_DEFPATH invokes shell via _PATH_BSHELL
  • Android: uses _PATH_DEFPATH and invokes shell via _PATH_BSHELL.
  • uClibc, which seems to use ":/bin:/usr/bin" different from its _PATH_DEFPATH value of "/usr/bin:/bin". I know the comment above that value says it tried to mirror glibc, which leans on confstr(_CS_PATH), so I'm wondering if that's the same on uClibc?
  • emscripten, which uses musl, so same as you mentioned earlier.
  • Haiku: It looks like it doesn't use _PATH_DEFPATH (sets errno to B_BAD_VALUE when path is null), but from lines 89-90, it seems to use _PATH_BSHELL (values are the same) on ENOEXEC error
  • Cygwin: Does not have a default fallback path or handles ENOEXEC
  • Hurd: I couldn't understand Hurd's exec implementation that well, so I might need help parsing through what they're doing here.
  • [Redox]: This one has a _PATH_BSHELL constant, but I mean this is all I found from their exec.c file (pretty barebones, though the value it does pass for the first argument of execv is _PATH_BSHELL). There's also this exec.rs, but I'm unsure if that's the right area we're supposed to look for exec implementation.
  • nuttx/NTO/QNX: This one doesn't have _PATH_DEFPATH or _PATH_BSHELL constant (couldn't find a include/paths.h file); I don't think we have to do anything special for these platforms?
  • Solaris/AIX: Also, doesn't have _PATH_DEFPATH/_PATH_BSHELL and I believe it's closed source? Can't tell if they have a default fallback path or handle ENOEXEC.

Do we know what we want to do for certain platforms like Solaris/AIX? I think those platforms are closed-source, so I couldn't find info about _PATH_DEFPATH/_PATH_BSHELL. I know Solaris is listed as tier 2 with host tools, so being able to build the standard library is supposed to be guaranteed.

Also, if possible, could you put that table of default path/ENOEXEC behavior in the PR description? 🙏 (Nvm, I realized there was a copy markdown option, so copying it to the PR description).

@asder8215
asder8215 force-pushed the commandext_exec_bug_fix branch from 71e457f to 0289d85 Compare October 21, 2026 17:36
@rustbot

rustbot commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@asder8215
asder8215 force-pushed the commandext_exec_bug_fix branch from 0289d85 to 4c2289e Compare October 21, 2026 18:03
@rust-log-analyzer

This comment has been minimized.

@asder8215
asder8215 force-pushed the commandext_exec_bug_fix branch from 4c2289e to 78a1404 Compare October 21, 2026 18:12
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
Comment thread library/std/src/sys/process/unix/unix.rs Outdated
all(target_os = "linux", target_env = "gnu") => {
confstr(libc::_CS_PATH, None).unwrap_or(OsString::new())
}
any(

@asder8215 asder8215 Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@joboet see my comment earlier #157144 (comment)

Unresolved question here is should we just directly use ":/bin:/usr/bin" for uclibc's execvp default fallback path? This is different from its _PATH_DEFPATH value which is "/usr/bin:/bin"

View changes since the review

@rust-log-analyzer

This comment has been minimized.

…H on Apple, Android, OpenBSD, FreeBSD, and DragonflyBSD as the default fallback path when the PATH environment variable was not found from maybe_envp/environ(); furthermore, added support for invoking the shell when execve returns an ENOEXEC error on Android, all Linux platforms (except musl), OpenBSD, NetBSD (for exec, but not posix_spawn), Apple, DragonFlyBSD, and Haiku.
@asder8215
asder8215 force-pushed the commandext_exec_bug_fix branch from 78a1404 to 4359483 Compare October 21, 2026 18:39
@asder8215

Copy link
Copy Markdown
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 21, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. O-unix Operating system: Unix-like S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. to-announce Announce this issue on triage meeting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants