-
Notifications
You must be signed in to change notification settings - Fork 18k
os/exec: Can't use os.Command (with ExtraFiles) that uses /proc/self/fd/<exe fd> as the executable #66654
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CC @bradfitz, @ianlancetaylor. |
That seems like a very unusual special case. The only way I see to fix it is to recognize the use of |
I agree; It's definitely unusual, although perhaps not unexpected in Linux.
or similar reasons for fexecve(3)
My use-case just happens to also incorporate inheriting IPC primitives with the parent and child that lead me to this issue.
I feared as such.
Understandable; one would hope the issue would be more readily presentable though. It had a non-ideal amount of digging needed to figure out it was occurring in golang source code and not the higher-level ForkExec wrappers. There's a non-zero possibility of someone using this pattern and invoking an unintended binary rather than getting various ERRNO (EPERM, ENXIO, etc) errors that I found. If not an in-place fix, would you folks be open to any (or all) of the below:
As I have workarounds to my specific situation, I won't go crazy, if nothing changes, but just figured I'd raise the awareness. Thanks for the quick look and response! |
Documentation would certainly be fine. |
Can't you also execute |
It wasn’t necessary to repro the issue, so I omitted this detail, but my use case also changes the UID/GID of the process which happens before the exec, so the child process won’t have the ability to read |
Go version
go 1.21.8 linux/amd64
Output of
go env
in your module/workspace:What did you do?
The following program attempts to Fork+Exec a binary (/usr/local/bin/play-sandbox) via an open file descriptor (FD) in the current process and have the child inherit additional FDs and print the usage information (-h / --help)
go playground link https://go.dev/play/p/MXQGzqeVJK0
What did you see happen?
What did you expect to see?
The problem can be circumvented by simply pushing the exe FD in the parent process to a FD integer high enough that it won't get clobbered by the file descriptors in cmd.ExtraFiles.
e.g
situation:
4 FDs are intended to be inherited by the child after exec [stdin(0), stdout(1), stderr(2), stdin_dup(4)] and the fd pointing to the exe is 3.
Problem:
exe(3) get's clobbered by stdin_dup (4) in the child before exec.
Workaround: By making the fd of exe, point to higher then
len(ProcAttr.Files)
(4 in this case), the exe isn't clobbered (and if CLO_EXEC is set, it'll also be closed in the exec'ed child. Which is my desired end-state)https://go.dev/play/p/gF5zi4g2fTq
I wasn't sure whether to mark this as a syscall issue or not; I originally ran in to this using libcap's cap.Launcher and was able to reproduce with the equivalent os/exec's Command setup. Both of them use syscall.ForkExec, which is where I believe the FD stomping occurs based on some strace + print statements.
I see in exec_linux.go that there's special handling to avoid stomping on needed FDs like pipes. Perhaps some special casing for /proc/self/fd/<fd> as argv[0] could be done too? Not sure, no expert here.
The text was updated successfully, but these errors were encountered: