1
2
3
4
5
6
7 package cgotest
8
9 import (
10 "fmt"
11 "internal/testenv"
12 "os"
13 "runtime"
14 "sort"
15 "strings"
16 "syscall"
17 "testing"
18 )
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 import "C"
64
65
66
67 func compareStatus(filter, expect string) error {
68 expected := filter + expect
69 pid := syscall.Getpid()
70 fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
71 if err != nil {
72 return fmt.Errorf("unable to find %d tasks: %v", pid, err)
73 }
74 expectedProc := fmt.Sprintf("Pid:\t%d", pid)
75 foundAThread := false
76 for _, f := range fs {
77 tf := fmt.Sprintf("/proc/%s/status", f.Name())
78 d, err := os.ReadFile(tf)
79 if err != nil {
80
81
82
83
84
85
86
87 continue
88 }
89 lines := strings.Split(string(d), "\n")
90 for _, line := range lines {
91
92 line = strings.TrimSpace(line)
93 if strings.HasPrefix(line, "Pid:\t") {
94
95
96
97
98
99
100
101
102
103 if line != expectedProc {
104 break
105 }
106
107
108
109 }
110 if strings.HasPrefix(line, filter) {
111 if line == expected {
112 foundAThread = true
113 break
114 }
115 if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") {
116
117
118 a := strings.Split(line[8:], " ")
119 sort.Strings(a)
120 got := strings.Join(a, " ")
121 if got == expected[8:] {
122 foundAThread = true
123 break
124 }
125
126 }
127 return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
128 }
129 }
130 }
131 if !foundAThread {
132 return fmt.Errorf("found no thread /proc/<TID>/status files for process %q", expectedProc)
133 }
134 return nil
135 }
136
137
138
139
140
141
142
143
144
145 func test1435(t *testing.T) {
146 if syscall.Getuid() != 0 {
147 t.Skip("skipping root only test")
148 }
149 if testing.Short() && testenv.Builder() != "" && os.Getenv("USER") == "swarming" {
150
151
152
153
154 t.Skip("skipping root only test on a non-root builder")
155 }
156 if runtime.GOOS == "linux" {
157 if _, err := os.Stat("/etc/alpine-release"); err == nil {
158 t.Skip("skipping failing test on alpine - go.dev/issue/19938")
159 }
160 }
161
162
163 const cts = 5
164 C.trial(cts)
165 defer C.cleanup()
166
167 vs := []struct {
168 call string
169 fn func() error
170 filter, expect string
171 }{
172 {call: "Setegid(1)", fn: func() error { return syscall.Setegid(1) }, filter: "Gid:", expect: "\t0\t1\t0\t1"},
173 {call: "Setegid(0)", fn: func() error { return syscall.Setegid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
174
175 {call: "Seteuid(1)", fn: func() error { return syscall.Seteuid(1) }, filter: "Uid:", expect: "\t0\t1\t0\t1"},
176 {call: "Setuid(0)", fn: func() error { return syscall.Setuid(0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"},
177
178 {call: "Setgid(1)", fn: func() error { return syscall.Setgid(1) }, filter: "Gid:", expect: "\t1\t1\t1\t1"},
179 {call: "Setgid(0)", fn: func() error { return syscall.Setgid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
180
181 {call: "Setgroups([]int{0,1,2,3})", fn: func() error { return syscall.Setgroups([]int{0, 1, 2, 3}) }, filter: "Groups:", expect: "\t0 1 2 3"},
182 {call: "Setgroups(nil)", fn: func() error { return syscall.Setgroups(nil) }, filter: "Groups:", expect: ""},
183 {call: "Setgroups([]int{0})", fn: func() error { return syscall.Setgroups([]int{0}) }, filter: "Groups:", expect: "\t0"},
184
185 {call: "Setregid(101,0)", fn: func() error { return syscall.Setregid(101, 0) }, filter: "Gid:", expect: "\t101\t0\t0\t0"},
186 {call: "Setregid(0,102)", fn: func() error { return syscall.Setregid(0, 102) }, filter: "Gid:", expect: "\t0\t102\t102\t102"},
187 {call: "Setregid(0,0)", fn: func() error { return syscall.Setregid(0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
188
189 {call: "Setreuid(1,0)", fn: func() error { return syscall.Setreuid(1, 0) }, filter: "Uid:", expect: "\t1\t0\t0\t0"},
190 {call: "Setreuid(0,2)", fn: func() error { return syscall.Setreuid(0, 2) }, filter: "Uid:", expect: "\t0\t2\t2\t2"},
191 {call: "Setreuid(0,0)", fn: func() error { return syscall.Setreuid(0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"},
192
193 {call: "Setresgid(101,0,102)", fn: func() error { return syscall.Setresgid(101, 0, 102) }, filter: "Gid:", expect: "\t101\t0\t102\t0"},
194 {call: "Setresgid(0,102,101)", fn: func() error { return syscall.Setresgid(0, 102, 101) }, filter: "Gid:", expect: "\t0\t102\t101\t102"},
195 {call: "Setresgid(0,0,0)", fn: func() error { return syscall.Setresgid(0, 0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
196
197 {call: "Setresuid(1,0,2)", fn: func() error { return syscall.Setresuid(1, 0, 2) }, filter: "Uid:", expect: "\t1\t0\t2\t0"},
198 {call: "Setresuid(0,2,1)", fn: func() error { return syscall.Setresuid(0, 2, 1) }, filter: "Uid:", expect: "\t0\t2\t1\t2"},
199 {call: "Setresuid(0,0,0)", fn: func() error { return syscall.Setresuid(0, 0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"},
200 }
201
202 for i, v := range vs {
203 if err := v.fn(); err != nil {
204 t.Errorf("[%d] %q failed: %v", i, v.call, err)
205 continue
206 }
207 if err := compareStatus(v.filter, v.expect); err != nil {
208 t.Errorf("[%d] %q comparison: %v", i, v.call, err)
209 }
210 }
211 }
212
View as plain text