github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/internal/syscall/windows/exec_windows_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build windows 6 7 package windows_test 8 9 import ( 10 "fmt" 11 "internal/syscall/windows" 12 "os" 13 "os/exec" 14 "syscall" 15 "testing" 16 "unsafe" 17 ) 18 19 func TestRunAtLowIntegrity(t *testing.T) { 20 if isWindowsXP(t) { 21 t.Skip("Windows XP does not support windows integrity levels") 22 } 23 24 if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" { 25 wil, err := getProcessIntegrityLevel() 26 if err != nil { 27 fmt.Fprintf(os.Stderr, "error: %s\n", err.Error()) 28 os.Exit(9) 29 return 30 } 31 fmt.Printf("%s", wil) 32 os.Exit(0) 33 return 34 } 35 36 cmd := exec.Command(os.Args[0], "-test.run=TestRunAtLowIntegrity", "--") 37 cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"} 38 39 token, err := getIntegrityLevelToken(sidWilLow) 40 if err != nil { 41 t.Fatal(err) 42 } 43 defer token.Close() 44 45 cmd.SysProcAttr = &syscall.SysProcAttr{ 46 Token: token, 47 } 48 49 out, err := cmd.CombinedOutput() 50 if err != nil { 51 t.Fatal(err) 52 } 53 54 if string(out) != sidWilLow { 55 t.Fatalf("Child process did not run as low integrity level: %s", string(out)) 56 } 57 } 58 59 func isWindowsXP(t *testing.T) bool { 60 v, err := syscall.GetVersion() 61 if err != nil { 62 t.Fatalf("GetVersion failed: %v", err) 63 } 64 major := byte(v) 65 return major < 6 66 } 67 68 const ( 69 sidWilLow = `S-1-16-4096` 70 ) 71 72 func getProcessIntegrityLevel() (string, error) { 73 procToken, err := syscall.OpenCurrentProcessToken() 74 if err != nil { 75 return "", err 76 } 77 defer procToken.Close() 78 79 p, err := tokenGetInfo(procToken, syscall.TokenIntegrityLevel, 64) 80 if err != nil { 81 return "", err 82 } 83 84 tml := (*windows.TOKEN_MANDATORY_LABEL)(p) 85 86 sid := (*syscall.SID)(unsafe.Pointer(tml.Label.Sid)) 87 88 return sid.String() 89 } 90 91 func tokenGetInfo(t syscall.Token, class uint32, initSize int) (unsafe.Pointer, error) { 92 n := uint32(initSize) 93 for { 94 b := make([]byte, n) 95 e := syscall.GetTokenInformation(t, class, &b[0], uint32(len(b)), &n) 96 if e == nil { 97 return unsafe.Pointer(&b[0]), nil 98 } 99 if e != syscall.ERROR_INSUFFICIENT_BUFFER { 100 return nil, e 101 } 102 if n <= uint32(len(b)) { 103 return nil, e 104 } 105 } 106 } 107 108 func getIntegrityLevelToken(wns string) (syscall.Token, error) { 109 var procToken, token syscall.Token 110 111 proc, err := syscall.GetCurrentProcess() 112 if err != nil { 113 return 0, err 114 } 115 defer syscall.CloseHandle(proc) 116 117 err = syscall.OpenProcessToken(proc, 118 syscall.TOKEN_DUPLICATE| 119 syscall.TOKEN_ADJUST_DEFAULT| 120 syscall.TOKEN_QUERY| 121 syscall.TOKEN_ASSIGN_PRIMARY, 122 &procToken) 123 if err != nil { 124 return 0, err 125 } 126 defer procToken.Close() 127 128 sid, err := syscall.StringToSid(wns) 129 if err != nil { 130 return 0, err 131 } 132 133 tml := &windows.TOKEN_MANDATORY_LABEL{} 134 tml.Label.Attributes = windows.SE_GROUP_INTEGRITY 135 tml.Label.Sid = sid 136 137 err = windows.DuplicateTokenEx(procToken, 0, nil, windows.SecurityImpersonation, 138 windows.TokenPrimary, &token) 139 if err != nil { 140 return 0, err 141 } 142 143 err = windows.SetTokenInformation(token, 144 syscall.TokenIntegrityLevel, 145 uintptr(unsafe.Pointer(tml)), 146 tml.Size()) 147 if err != nil { 148 token.Close() 149 return 0, err 150 } 151 return token, nil 152 }