1
2
3
4
5
6
7 package unix_test
8
9 import (
10 "flag"
11 "fmt"
12 "net"
13 "os"
14 "os/exec"
15 "path/filepath"
16 "runtime"
17 "testing"
18
19 "golang.org/x/sys/unix"
20 )
21
22 func TestSysctlUint64(t *testing.T) {
23 _, err := unix.SysctlUint64("vm.swap_total")
24 if err != nil {
25 t.Fatal(err)
26 }
27 }
28
29
30
31
32
33 type testProc struct {
34 fn func()
35 success bool
36 }
37
38 var (
39 testProcs = map[string]testProc{}
40 procName = ""
41 procArg = ""
42 )
43
44 const (
45 optName = "sys-unix-internal-procname"
46 optArg = "sys-unix-internal-arg"
47 )
48
49 func init() {
50 flag.StringVar(&procName, optName, "", "internal use only")
51 flag.StringVar(&procArg, optArg, "", "internal use only")
52
53 }
54
55 func testCmd(procName string, procArg string) (*exec.Cmd, error) {
56 exe, err := filepath.Abs(os.Args[0])
57 if err != nil {
58 return nil, err
59 }
60 cmd := exec.Command(exe, "-"+optName+"="+procName, "-"+optArg+"="+procArg)
61 cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
62 return cmd, nil
63 }
64
65
66
67 func ExitsCorrectly(t *testing.T, procName string) {
68 s := testProcs[procName]
69 c, err := testCmd(procName, t.TempDir())
70 if err != nil {
71 t.Fatalf("Failed to construct command for %s", procName)
72 }
73 if (c.Run() == nil) != s.success {
74 result := "succeed"
75 if !s.success {
76 result = "fail"
77 }
78 t.Fatalf("Process did not %s when it was supposed to", result)
79 }
80 }
81
82 func TestMain(m *testing.M) {
83 flag.Parse()
84 if procName != "" {
85 t := testProcs[procName]
86 t.fn()
87 os.Stderr.WriteString("test function did not exit\n")
88 if t.success {
89 os.Exit(1)
90 } else {
91 os.Exit(0)
92 }
93 }
94 os.Exit(m.Run())
95 }
96
97
98
99 const testfile = "gocapmodetest"
100 const testfile2 = testfile + "2"
101
102 func CapEnterTest() {
103 _, err := os.OpenFile(filepath.Join(procArg, testfile), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
104 if err != nil {
105 panic(fmt.Sprintf("OpenFile: %s", err))
106 }
107
108 err = unix.CapEnter()
109 if err != nil {
110 panic(fmt.Sprintf("CapEnter: %s", err))
111 }
112
113 _, err = os.OpenFile(filepath.Join(procArg, testfile2), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
114 if err == nil {
115 panic("OpenFile works!")
116 }
117 if err.(*os.PathError).Err != unix.ECAPMODE {
118 panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err))
119 }
120 os.Exit(0)
121 }
122
123 func init() {
124 testProcs["cap_enter"] = testProc{
125 CapEnterTest,
126 true,
127 }
128 }
129
130 func TestCapEnter(t *testing.T) {
131 if runtime.GOARCH != "amd64" {
132 t.Skipf("skipping test on %s", runtime.GOARCH)
133 }
134 ExitsCorrectly(t, "cap_enter")
135 }
136
137 func OpenatTest() {
138 f, err := os.Open(procArg)
139 if err != nil {
140 panic(err)
141 }
142
143 err = unix.CapEnter()
144 if err != nil {
145 panic(fmt.Sprintf("CapEnter: %s", err))
146 }
147
148 fxx, err := unix.Openat(int(f.Fd()), "xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
149 if err != nil {
150 panic(err)
151 }
152 unix.Close(fxx)
153
154
155 _, err = os.OpenFile(procArg+"/xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
156 if err == nil {
157 panic("OpenFile succeeded")
158 }
159 if err.(*os.PathError).Err != unix.ECAPMODE {
160 panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err))
161 }
162
163
164 err = os.Mkdir(procArg+"2", 0777)
165 if err == nil {
166 panic("MKdir succeeded")
167 }
168 if err.(*os.PathError).Err != unix.ECAPMODE {
169 panic(fmt.Sprintf("Mkdir failed wrong: %s %#v", err, err))
170 }
171
172
173 r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_LOOKUP})
174 if err != nil {
175 panic(fmt.Sprintf("CapRightsInit failed: %s %#v", err, err))
176 }
177 err = unix.CapRightsLimit(f.Fd(), r)
178 if err != nil {
179 panic(fmt.Sprintf("CapRightsLimit failed: %s %#v", err, err))
180 }
181
182
183 r, err = unix.CapRightsGet(f.Fd())
184 if err != nil {
185 panic(fmt.Sprintf("CapRightsGet failed: %s %#v", err, err))
186 }
187 b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP})
188 if err != nil {
189 panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err))
190 }
191 if !b {
192 panic("Unexpected rights")
193 }
194 b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP, unix.CAP_WRITE})
195 if err != nil {
196 panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err))
197 }
198 if b {
199 panic("Unexpected rights (2)")
200 }
201
202
203 _, err = unix.Openat(int(f.Fd()), "xx2", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
204 if err == nil {
205 panic("Openat succeeded")
206 }
207 if err != unix.ENOTCAPABLE {
208 panic(fmt.Sprintf("OpenFileAt failed wrong: %s %#v", err, err))
209 }
210
211
212 _, err = unix.Openat(int(f.Fd()), "xx", os.O_RDONLY, 0666)
213 if err != nil {
214 panic(fmt.Sprintf("Openat failed: %s %#v", err, err))
215 }
216
217 os.Exit(0)
218 }
219
220 func init() {
221 testProcs["openat"] = testProc{
222 OpenatTest,
223 true,
224 }
225 }
226
227 func TestOpenat(t *testing.T) {
228 if runtime.GOARCH != "amd64" {
229 t.Skipf("skipping test on %s", runtime.GOARCH)
230 }
231 ExitsCorrectly(t, "openat")
232 }
233
234 func TestCapRightsSetAndClear(t *testing.T) {
235 r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT})
236 if err != nil {
237 t.Fatalf("CapRightsInit failed: %s", err)
238 }
239
240 err = unix.CapRightsSet(r, []uint64{unix.CAP_EVENT, unix.CAP_LISTEN})
241 if err != nil {
242 t.Fatalf("CapRightsSet failed: %s", err)
243 }
244
245 b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT, unix.CAP_EVENT, unix.CAP_LISTEN})
246 if err != nil {
247 t.Fatalf("CapRightsIsSet failed: %s", err)
248 }
249 if !b {
250 t.Fatalf("Wrong rights set")
251 }
252
253 err = unix.CapRightsClear(r, []uint64{unix.CAP_READ, unix.CAP_PDWAIT})
254 if err != nil {
255 t.Fatalf("CapRightsClear failed: %s", err)
256 }
257
258 b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_WRITE, unix.CAP_EVENT, unix.CAP_LISTEN})
259 if err != nil {
260 t.Fatalf("CapRightsIsSet failed: %s", err)
261 }
262 if !b {
263 t.Fatalf("Wrong rights set")
264 }
265 }
266
267 func TestGetsockoptXucred(t *testing.T) {
268 fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
269 if err != nil {
270 t.Fatalf("Socketpair: %v", err)
271 }
272
273 srvFile := os.NewFile(uintptr(fds[0]), "server")
274 cliFile := os.NewFile(uintptr(fds[1]), "client")
275 defer srvFile.Close()
276 defer cliFile.Close()
277
278 srv, err := net.FileConn(srvFile)
279 if err != nil {
280 t.Fatalf("FileConn: %v", err)
281 }
282 defer srv.Close()
283
284 cli, err := net.FileConn(cliFile)
285 if err != nil {
286 t.Fatalf("FileConn: %v", err)
287 }
288 defer cli.Close()
289
290 cred, err := unix.GetsockoptXucred(fds[1], unix.SOL_LOCAL, unix.LOCAL_PEERCRED)
291 if err == unix.ENOTCONN {
292 t.Skip("GetsockoptXucred not supported with Socketpair on FreeBSD 11 and earlier")
293 } else if err != nil {
294 t.Fatal(err)
295 }
296 t.Logf("got: %+v", cred)
297 if got, want := cred.Uid, os.Getuid(); int(got) != int(want) {
298 t.Errorf("uid = %v; want %v", got, want)
299 }
300 }
301
302
303
304
305
306 func stringsFromByteSlice(buf []byte) []string {
307 var result []string
308 i := 0
309 for i < len(buf) {
310 next := i + 1 + int(buf[i])
311 result = append(result, string(buf[i+1:next]))
312 i = next
313 }
314 return result
315 }
316
View as plain text