don't call os.NewFile on unknown FDs

os.NewFile was called on file descriptors 3, 4, and 5 during every init,
in case this process happened to be running inside panicwrap. If the
runtime has already chosen one of these file descriptors to use
internally, starting polling on them can cause the runtime to crash.

Initialize the file descriptors lazily, only if we know that they belong
to us, after Wrapped is checked.
This commit is contained in:
James Bardin 2020-04-04 15:46:19 -04:00
parent 60e407a59b
commit cd65b28da0
2 changed files with 23 additions and 24 deletions

View File

@ -10,34 +10,31 @@ import (
// Stdin returns the true stdin of the process.
func Stdin() *os.File {
stdin := os.Stdin
if panicwrap.Wrapped(nil) {
stdin = wrappedStdin
}
stdin, _, _ := fds()
return stdin
}
// Stdout returns the true stdout of the process.
func Stdout() *os.File {
stdout := os.Stdout
if panicwrap.Wrapped(nil) {
stdout = wrappedStdout
}
_, stdout, _ := fds()
return stdout
}
// Stderr returns the true stderr of the process.
func Stderr() *os.File {
stderr := os.Stderr
if panicwrap.Wrapped(nil) {
stderr = wrappedStderr
}
_, _, stderr := fds()
return stderr
}
func fds() (stdin, stdout, stderr *os.File) {
stdin, stdout, stderr = os.Stdin, os.Stdout, os.Stderr
if panicwrap.Wrapped(nil) {
initPlatform()
stdin, stdout, stderr = wrappedStdin, wrappedStdout, wrappedStderr
}
return
}
// These are the wrapped standard streams. These are setup by the
// platform specific code in initPlatform.
var (
@ -45,8 +42,3 @@ var (
wrappedStdout *os.File
wrappedStderr *os.File
)
func init() {
// Initialize the platform-specific code
initPlatform()
}

View File

@ -4,11 +4,18 @@ package wrappedstreams
import (
"os"
"sync"
)
var initOnce sync.Once
func initPlatform() {
// These must be initialized lazily, once it's been determined that this is
// a wrapped process.
initOnce.Do(func() {
// The standard streams are passed in via extra file descriptors.
wrappedStdin = os.NewFile(uintptr(3), "stdin")
wrappedStdout = os.NewFile(uintptr(4), "stdout")
wrappedStderr = os.NewFile(uintptr(5), "stderr")
})
}