-
Notifications
You must be signed in to change notification settings - Fork 18k
syscall: ForkExec with Ptrace flag causes runtime to be traced #21428
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
@bjames2011 there was a presentation at Gophercon by Liz Rice @lizrice at https://medium.com/@lizrice/strace-in-60-lines-of-go-b4b76e3ecd64 "Strace in 60 lines of Go", that might help you. |
It's true that there are various optional system calls that may be executed after the For what it's worth, it's unusually to call What fix do you suggest? To simply move the |
Thanks; for some reason, I'd completely failed to find anything like this when Googling. The code in that presentation is very similar to what I ended up with - albeit using
Hence my intro text "This is somewhat of a philosophical question about the design decisions made in the Go runtime, rather than a bug, per-se." It is somewhat counter-intuitive, when tracing a process, to see completely unrelated system calls not executed by the process. From a user point-of-view, what the runtime does in order to set up the new process is completely unrelated to the process itself (and simply a side-effect of the fact that we're writing Go). After all, the only way to know which syscalls were executed by the subprocess - rather than the Go runtime - is to track the syscall type and ignore all syscalls until the
That's exactly what I was implying with my C example. ;-) Unless there was a conscious design decision made to include the Go runtime calls in the trace (and I can't see any logical reason why this would make sense), I would very much suggest moving the If you need further justification, it would also be a moral victory (as you will have converted one more C programmer to using Go, as - at present - I've rewritten my program in C). |
Thanks for the shout-out @odeke-em :-) Just reading the source quickly there, the Ptrace flag is checked as soon as the Clone syscall creates the child process. So yes, it's tracing the syscalls that the Go runtime calls before the execve, but they are executed by the child process - so I think it's right that they are included in the trace. If the ptrace wasn't started until just before the execve, I think we'd just lose the ability to trace those syscalls, wouldn't we? |
Yes, they are executed by the child process, but not by the program that the user specified in the call to
Yes, but all the syscalls executed before the A few points here:
I can't think of a use-case where the user of this API would want to trace the runtime implicitly like this; the only time it would make sense to trace those runtime syscalls would be from an external process (i.e. a debugger attaching to the parent Go process) and in that case, the suggested change would not cause any syscalls to be lost. Overall, I'd say that the current behaviour falls into the realm of "exposing the implementation" and the suggested change should be considered. |
Also, the "missing syscalls" argument has a hole in it as there are other syscalls between the ...
// Fork succeeded, now in child.
// Wait for User ID/Group ID mappings to be written.
if sys.UidMappings != nil || sys.GidMappings != nil {
if _, _, err1 = RawSyscall(SYS_CLOSE, uintptr(p[1]), 0, 0); err1 != 0 {
goto childerror
}
r1, _, err1 = RawSyscall(SYS_READ, uintptr(p[0]), uintptr(unsafe.Pointer(&err2)), unsafe.Sizeof(err2))
if err1 != 0 {
goto childerror
}
if r1 != unsafe.Sizeof(err2) {
err1 = EINVAL
goto childerror
}
if err2 != 0 {
err1 = err2
goto childerror
}
}
// Enable tracing if requested.
if sys.Ptrace {
_, _, err1 = RawSyscall(SYS_PTRACE, uintptr(PTRACE_TRACEME), 0, 0)
if err1 != 0 {
goto childerror
}
}
... |
fwiw I agree with you that the call to SYS_PTRACE is either too early or too late (and without checking the history, I'd bet that that the UID/GID mappings section was added more recently.) @ianlancetaylor pretty sure that os.StartProcess() ends up calling syscall.ForkExec() anyway, so would result in the same behaviour |
I have no opinion on the right fix. Does somebody want to send in a change? |
I can send a patch to move the ptrace call before execve |
Change https://golang.org/cl/55811 mentions this issue: |
@jessfraz Thanks. Does anybody who cares about this issue object to https://golang.org/cl/55811? |
don't know how qualified I am to say this, but lgtm! |
@lizrice I don't know if you are interested, but if you can log into Gerrit with a gmail account, it'd be awesome to have you there as a reviewer and you can put your approvals or disapprovals on there, and then in merges, yours will be there on the record as a Go reviewer! |
The review looks good to me. Thanks to everyone on the quick responses so far. |
Same thing for you too @bjames2011 as I had mentioned in #21428 (comment) :) |
:) appreciate it and definitely review more \o/
…On Aug 15, 2017 5:28 PM, "Liz Rice" ***@***.***> wrote:
Thanks @odeke-em <https://github.com/odeke-em> - I added myself as a
reviewer on there. Exciting, my first Go review is a LGTM on a @jessfraz
<https://github.com/jessfraz> change :-)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#21428 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABYNbBhNw3sG-u-Vv4tvb6_4s3jkF9DGks5sYg1vgaJpZM4O1r4m>
.
|
Environment
Issue
This is somewhat of a philosophical question about the design decisions made in the Go runtime, rather than a bug, per-se.
I've been trying to implement a simple strace-like program in Golang, using
syscall.ForkExec
with the Ptrace flag enabled - my expectation of this flag is that it enables tracing syscalls of the child process after the fork has occurred, something like the following (as I would write, if implementing the same program in C):However it doesn't seem like the above is possible in Go due to the fact that the Ptrace flag is checked too early in https://golang.org/src/syscall/exec_linux.go (
forkAndExecInChild()
) and a number of (Go runtime) syscalls are performed between enabling tracing and the actual exec call.Here's a cut-down version of the code I'm using:
Question
Why was this design decision made and what is the intended usage of the Ptrace flag? Is it the intended behaviour to trace the Go runtime in the child process before the exec? If so, that's a bit counter-intuitive to the user.
Even better, is there a code example demonstrating the intended usage of the Ptrace flag and how one might implement strace using Go?
The text was updated successfully, but these errors were encountered: