Commit fb9fc886 authored by Hector Chu's avatar Hector Chu Committed by Alex Brainman

windows: syscall: Make ForkExec acquire the ForkLock

so that spawned processes avoid inheriting pipes.

Implement CloseOnExec.
Make file and pipe handles inheritable.

R=rsc, brainman, vincent.vanackere
CC=golang-dev
https://golang.org/cl/4126047
parent 68b40fbb
...@@ -107,7 +107,7 @@ func escapeAddQuotes(s string) string { ...@@ -107,7 +107,7 @@ func escapeAddQuotes(s string) string {
func CloseOnExec(fd int) { func CloseOnExec(fd int) {
return SetHandleInformation(int32(fd), HANDLE_FLAG_INHERIT, 0)
} }
func SetNonblock(fd int, nonblocking bool) (errno int) { func SetNonblock(fd int, nonblocking bool) (errno int) {
...@@ -144,6 +144,12 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri ...@@ -144,6 +144,12 @@ func forkExec(argv0 string, argv []string, envv []string, traceme bool, dir stri
startupInfo.StdOutput = 0 startupInfo.StdOutput = 0
startupInfo.StdErr = 0 startupInfo.StdErr = 0
// Acquire the fork lock so that no other threads
// create new fds that are not yet close-on-exec
// before we fork.
ForkLock.Lock()
defer ForkLock.Unlock()
var currentProc, _ = GetCurrentProcess() var currentProc, _ = GetCurrentProcess()
if len(fd) > 0 && fd[0] > 0 { if len(fd) > 0 && fd[0] > 0 {
if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok { if ok, err := DuplicateHandle(currentProc, int32(fd[0]), currentProc, &startupInfo.StdInput, 0, true, DUPLICATE_SAME_ACCESS); !ok {
......
...@@ -111,7 +111,7 @@ func NewCallback(fn interface{}) uintptr ...@@ -111,7 +111,7 @@ func NewCallback(fn interface{}) uintptr
//sys GetVersion() (ver uint32, errno int) //sys GetVersion() (ver uint32, errno int)
//sys FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) = FormatMessageW //sys FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, errno int) = FormatMessageW
//sys ExitProcess(exitcode uint32) //sys ExitProcess(exitcode uint32)
//sys CreateFile(name *uint16, access uint32, mode uint32, sa *byte, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) [failretval==-1] = CreateFileW //sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) [failretval==-1] = CreateFileW
//sys ReadFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int) //sys ReadFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int)
//sys WriteFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int) //sys WriteFile(handle int32, buf []byte, done *uint32, overlapped *Overlapped) (ok bool, errno int)
//sys SetFilePointer(handle int32, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) [failretval==0xffffffff] //sys SetFilePointer(handle int32, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, errno int) [failretval==0xffffffff]
...@@ -123,7 +123,7 @@ func NewCallback(fn interface{}) uintptr ...@@ -123,7 +123,7 @@ func NewCallback(fn interface{}) uintptr
//sys GetFileInformationByHandle(handle int32, data *ByHandleFileInformation) (ok bool, errno int) //sys GetFileInformationByHandle(handle int32, data *ByHandleFileInformation) (ok bool, errno int)
//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, errno int) = GetCurrentDirectoryW //sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, errno int) = GetCurrentDirectoryW
//sys SetCurrentDirectory(path *uint16) (ok bool, errno int) = SetCurrentDirectoryW //sys SetCurrentDirectory(path *uint16) (ok bool, errno int) = SetCurrentDirectoryW
//sys CreateDirectory(path *uint16, sa *byte) (ok bool, errno int) = CreateDirectoryW //sys CreateDirectory(path *uint16, sa *SecurityAttributes) (ok bool, errno int) = CreateDirectoryW
//sys RemoveDirectory(path *uint16) (ok bool, errno int) = RemoveDirectoryW //sys RemoveDirectory(path *uint16) (ok bool, errno int) = RemoveDirectoryW
//sys DeleteFile(path *uint16) (ok bool, errno int) = DeleteFileW //sys DeleteFile(path *uint16) (ok bool, errno int) = DeleteFileW
//sys MoveFile(from *uint16, to *uint16) (ok bool, errno int) = MoveFileW //sys MoveFile(from *uint16, to *uint16) (ok bool, errno int) = MoveFileW
...@@ -141,7 +141,7 @@ func NewCallback(fn interface{}) uintptr ...@@ -141,7 +141,7 @@ func NewCallback(fn interface{}) uintptr
//sys DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (ok bool, errno int) //sys DuplicateHandle(hSourceProcessHandle int32, hSourceHandle int32, hTargetProcessHandle int32, lpTargetHandle *int32, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (ok bool, errno int)
//sys WaitForSingleObject(handle int32, waitMilliseconds uint32) (event uint32, errno int) [failretval==0xffffffff] //sys WaitForSingleObject(handle int32, waitMilliseconds uint32) (event uint32, errno int) [failretval==0xffffffff]
//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) = GetTempPathW //sys GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) = GetTempPathW
//sys CreatePipe(readhandle *uint32, writehandle *uint32, lpsa *byte, size uint32) (ok bool, errno int) //sys CreatePipe(readhandle *uint32, writehandle *uint32, sa *SecurityAttributes, size uint32) (ok bool, errno int)
//sys GetFileType(filehandle uint32) (n uint32, errno int) //sys GetFileType(filehandle uint32) (n uint32, errno int)
//sys CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW //sys CryptAcquireContext(provhandle *uint32, container *uint16, provider *uint16, provtype uint32, flags uint32) (ok bool, errno int) = advapi32.CryptAcquireContextW
//sys CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext //sys CryptReleaseContext(provhandle uint32, flags uint32) (ok bool, errno int) = advapi32.CryptReleaseContext
...@@ -157,6 +157,7 @@ func NewCallback(fn interface{}) uintptr ...@@ -157,6 +157,7 @@ func NewCallback(fn interface{}) uintptr
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW //sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) [failretval==nil] = shell32.CommandLineToArgvW //sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, errno int) [failretval==nil] = shell32.CommandLineToArgvW
//sys LocalFree(hmem uint32) (handle uint32, errno int) [failretval!=0] //sys LocalFree(hmem uint32) (handle uint32, errno int) [failretval!=0]
//sys SetHandleInformation(handle int32, mask uint32, flags uint32) (ok bool, errno int)
// syscall interface implementation for other packages // syscall interface implementation for other packages
...@@ -181,6 +182,13 @@ func Errstr(errno int) string { ...@@ -181,6 +182,13 @@ func Errstr(errno int) string {
func Exit(code int) { ExitProcess(uint32(code)) } func Exit(code int) { ExitProcess(uint32(code)) }
func makeInheritSa() *SecurityAttributes {
var sa SecurityAttributes
sa.Length = uint32(unsafe.Sizeof(sa))
sa.InheritHandle = 1
return &sa
}
func Open(path string, mode int, perm uint32) (fd int, errno int) { func Open(path string, mode int, perm uint32) (fd int, errno int) {
if len(path) == 0 { if len(path) == 0 {
return -1, ERROR_FILE_NOT_FOUND return -1, ERROR_FILE_NOT_FOUND
...@@ -202,6 +210,10 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) { ...@@ -202,6 +210,10 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) {
access |= FILE_APPEND_DATA access |= FILE_APPEND_DATA
} }
sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE) sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
var sa *SecurityAttributes
if mode&O_CLOEXEC == 0 {
sa = makeInheritSa()
}
var createmode uint32 var createmode uint32
switch { switch {
case mode&O_CREAT != 0: case mode&O_CREAT != 0:
...@@ -215,7 +227,7 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) { ...@@ -215,7 +227,7 @@ func Open(path string, mode int, perm uint32) (fd int, errno int) {
default: default:
createmode = OPEN_EXISTING createmode = OPEN_EXISTING
} }
h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, nil, createmode, FILE_ATTRIBUTE_NORMAL, 0) h, e := CreateFile(StringToUTF16Ptr(path), access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
return int(h), int(e) return int(h), int(e)
} }
...@@ -439,7 +451,7 @@ func Pipe(p []int) (errno int) { ...@@ -439,7 +451,7 @@ func Pipe(p []int) (errno int) {
return EINVAL return EINVAL
} }
var r, w uint32 var r, w uint32
if ok, errno := CreatePipe(&r, &w, nil, 0); !ok { if ok, errno := CreatePipe(&r, &w, makeInheritSa(), 0); !ok {
return errno return errno
} }
p[0] = int(r) p[0] = int(r)
......
...@@ -66,6 +66,7 @@ var ( ...@@ -66,6 +66,7 @@ var (
procGetCommandLineW = getSysProcAddr(modkernel32, "GetCommandLineW") procGetCommandLineW = getSysProcAddr(modkernel32, "GetCommandLineW")
procCommandLineToArgvW = getSysProcAddr(modshell32, "CommandLineToArgvW") procCommandLineToArgvW = getSysProcAddr(modshell32, "CommandLineToArgvW")
procLocalFree = getSysProcAddr(modkernel32, "LocalFree") procLocalFree = getSysProcAddr(modkernel32, "LocalFree")
procSetHandleInformation = getSysProcAddr(modkernel32, "SetHandleInformation")
procWSAStartup = getSysProcAddr(modwsock32, "WSAStartup") procWSAStartup = getSysProcAddr(modwsock32, "WSAStartup")
procWSACleanup = getSysProcAddr(modwsock32, "WSACleanup") procWSACleanup = getSysProcAddr(modwsock32, "WSACleanup")
procsocket = getSysProcAddr(modwsock32, "socket") procsocket = getSysProcAddr(modwsock32, "socket")
...@@ -180,7 +181,7 @@ func ExitProcess(exitcode uint32) { ...@@ -180,7 +181,7 @@ func ExitProcess(exitcode uint32) {
return return
} }
func CreateFile(name *uint16, access uint32, mode uint32, sa *byte, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) { func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle int32, errno int) {
r0, _, e1 := Syscall9(procCreateFileW, 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) r0, _, e1 := Syscall9(procCreateFileW, 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
handle = int32(r0) handle = int32(r0)
if handle == -1 { if handle == -1 {
...@@ -368,7 +369,7 @@ func SetCurrentDirectory(path *uint16) (ok bool, errno int) { ...@@ -368,7 +369,7 @@ func SetCurrentDirectory(path *uint16) (ok bool, errno int) {
return return
} }
func CreateDirectory(path *uint16, sa *byte) (ok bool, errno int) { func CreateDirectory(path *uint16, sa *SecurityAttributes) (ok bool, errno int) {
r0, _, e1 := Syscall(procCreateDirectoryW, 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) r0, _, e1 := Syscall(procCreateDirectoryW, 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0)
ok = bool(r0 != 0) ok = bool(r0 != 0)
if !ok { if !ok {
...@@ -630,8 +631,8 @@ func GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) { ...@@ -630,8 +631,8 @@ func GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) {
return return
} }
func CreatePipe(readhandle *uint32, writehandle *uint32, lpsa *byte, size uint32) (ok bool, errno int) { func CreatePipe(readhandle *uint32, writehandle *uint32, sa *SecurityAttributes, size uint32) (ok bool, errno int) {
r0, _, e1 := Syscall6(procCreatePipe, 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(lpsa)), uintptr(size), 0, 0) r0, _, e1 := Syscall6(procCreatePipe, 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0)
ok = bool(r0 != 0) ok = bool(r0 != 0)
if !ok { if !ok {
if e1 != 0 { if e1 != 0 {
...@@ -861,6 +862,21 @@ func LocalFree(hmem uint32) (handle uint32, errno int) { ...@@ -861,6 +862,21 @@ func LocalFree(hmem uint32) (handle uint32, errno int) {
return return
} }
func SetHandleInformation(handle int32, mask uint32, flags uint32) (ok bool, errno int) {
r0, _, e1 := Syscall(procSetHandleInformation, 3, uintptr(handle), uintptr(mask), uintptr(flags))
ok = bool(r0 != 0)
if !ok {
if e1 != 0 {
errno = int(e1)
} else {
errno = EINVAL
}
} else {
errno = 0
}
return
}
func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) { func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
r0, _, _ := Syscall(procWSAStartup, 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) r0, _, _ := Syscall(procWSAStartup, 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
sockerrno = int(r0) sockerrno = int(r0)
......
...@@ -74,6 +74,7 @@ const ( ...@@ -74,6 +74,7 @@ const (
OPEN_ALWAYS = 4 OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5 TRUNCATE_EXISTING = 5
HANDLE_FLAG_INHERIT = 0x00000001
STARTF_USESTDHANDLES = 0x00000100 STARTF_USESTDHANDLES = 0x00000100
DUPLICATE_CLOSE_SOURCE = 0x00000001 DUPLICATE_CLOSE_SOURCE = 0x00000001
DUPLICATE_SAME_ACCESS = 0x00000002 DUPLICATE_SAME_ACCESS = 0x00000002
...@@ -172,6 +173,12 @@ func NsecToTimeval(nsec int64) (tv Timeval) { ...@@ -172,6 +173,12 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
return return
} }
type SecurityAttributes struct {
Length uint32
SecurityDescriptor uintptr
InheritHandle uint32
}
type Overlapped struct { type Overlapped struct {
Internal uint32 Internal uint32
InternalHigh uint32 InternalHigh uint32
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment