diff options
| author | Paul Querna <paul@querna.org> | 2017-11-01 15:11:52 -0700 |
|---|---|---|
| committer | Alex Brainman <alex.brainman@gmail.com> | 2017-11-06 01:35:58 +0000 |
| commit | bb98331555a177f0e1256cebcfbc8a7b454bccd2 (patch) | |
| tree | 0d62f21310ba5e1a400307bf3446c68a5e1f049b /src/internal/syscall/windows/exec_windows_test.go | |
| parent | 989cc80167e0ec4e8c220f1aec308dbdf4b9b0e9 (diff) | |
| download | go-bb98331555a177f0e1256cebcfbc8a7b454bccd2.tar.xz | |
syscall: add Token to Windows SysProcAttr
Fixes #21105
Change-Id: Ia2dea9b82a356795f581ce75616198b46e97abb6
Reviewed-on: https://go-review.googlesource.com/75253
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Diffstat (limited to 'src/internal/syscall/windows/exec_windows_test.go')
| -rw-r--r-- | src/internal/syscall/windows/exec_windows_test.go | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/internal/syscall/windows/exec_windows_test.go b/src/internal/syscall/windows/exec_windows_test.go new file mode 100644 index 0000000000..b1edb4d6af --- /dev/null +++ b/src/internal/syscall/windows/exec_windows_test.go @@ -0,0 +1,153 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package windows_test + +import ( + "fmt" + "internal/syscall/windows" + "os" + "os/exec" + "syscall" + "testing" + "unsafe" +) + +func TestRunAtLowIntegrity(t *testing.T) { + if isWindowsXP(t) { + t.Skip("Windows XP does not support windows integrity levels") + } + + if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { + wil, err := getProcessIntegrityLevel() + if err != nil { + fmt.Fprintf(os.Stderr, "error: %s\n", err.Error()) + os.Exit(9) + return + } + fmt.Printf("%s", wil) + os.Exit(0) + return + } + + cmd := exec.Command(os.Args[0], "-test.run=TestRunAtLowIntegrity", "--") + cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} + + token, err := getIntegrityLevelToken(sidWilLow) + if err != nil { + t.Fatal(err) + } + defer syscall.CloseHandle(token) + + cmd.SysProcAttr = &syscall.SysProcAttr{ + Token: token, + } + + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatal(err) + } + + if string(out) != sidWilLow { + t.Fatalf("Child process did not run as low integrity level: %s", string(out)) + } +} + +func isWindowsXP(t *testing.T) bool { + v, err := syscall.GetVersion() + if err != nil { + t.Fatalf("GetVersion failed: %v", err) + } + major := byte(v) + return major < 6 +} + +const ( + sidWilLow = `S-1-16-4096` +) + +func getProcessIntegrityLevel() (string, error) { + procToken, err := syscall.OpenCurrentProcessToken() + if err != nil { + return "", err + } + defer procToken.Close() + + p, err := tokenGetInfo(procToken, syscall.TokenIntegrityLevel, 64) + if err != nil { + return "", err + } + + tml := (*windows.TOKEN_MANDATORY_LABEL)(p) + + sid := (*syscall.SID)(unsafe.Pointer(tml.Label.Sid)) + + return sid.String() +} + +func tokenGetInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) { + n := uint32(initSize) + for { + b := make([]byte, n) + e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) + if e == nil { + return unsafe.Pointer(&b[0]), nil + } + if e != syscall.ERROR_INSUFFICIENT_BUFFER { + return nil, e + } + if n <= uint32(len(b)) { + return nil, e + } + } +} + +func getIntegrityLevelToken(wns string) (syscall.Handle, error) { + var token syscall.Handle + var procToken syscall.Token + + proc, err := syscall.GetCurrentProcess() + if err != nil { + return 0, err + } + defer syscall.CloseHandle(proc) + + err = syscall.OpenProcessToken(proc, + syscall.TOKEN_DUPLICATE| + syscall.TOKEN_ADJUST_DEFAULT| + syscall.TOKEN_QUERY| + syscall.TOKEN_ASSIGN_PRIMARY, + &procToken) + if err != nil { + return 0, err + } + defer procToken.Close() + + sid, err := syscall.StringToSid(wns) + if err != nil { + return 0, err + } + + tml := &windows.TOKEN_MANDATORY_LABEL{} + tml.Label.Attributes = windows.SE_GROUP_INTEGRITY + tml.Label.Sid = sid + + err = windows.DuplicateTokenEx(syscall.Handle(procToken), 0, nil, windows.SecurityImpersonation, + windows.TokenPrimary, &token) + if err != nil { + return 0, err + } + + err = windows.SetTokenInformation(token, + syscall.TokenIntegrityLevel, + uintptr(unsafe.Pointer(tml)), + tml.Size()) + if err != nil { + syscall.CloseHandle(token) + return 0, err + } + return token, nil +} |
