github.com/nibnait/go-learn@v0.0.0-20220227013611-dfa47ea6d2da/src/pkg/mod/golang.org/x/sys@v0.0.0-20210630005230-0f9fa26af87c/unix/syscall_freebsd_test.go (about) 1 // Copyright 2014 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 //go:build freebsd 6 // +build freebsd 7 8 package unix_test 9 10 import ( 11 "flag" 12 "fmt" 13 "io/ioutil" 14 "net" 15 "os" 16 "os/exec" 17 "path" 18 "path/filepath" 19 "runtime" 20 "testing" 21 22 "golang.org/x/sys/unix" 23 ) 24 25 func TestSysctlUint64(t *testing.T) { 26 _, err := unix.SysctlUint64("vm.swap_total") 27 if err != nil { 28 t.Fatal(err) 29 } 30 } 31 32 // FIXME: Infrastructure for launching tests in subprocesses stolen from openbsd_test.go - refactor? 33 // testCmd generates a proper command that, when executed, runs the test 34 // corresponding to the given key. 35 36 type testProc struct { 37 fn func() // should always exit instead of returning 38 arg func(t *testing.T) string // generate argument for test 39 cleanup func(arg string) error // for instance, delete coredumps from testing pledge 40 success bool // whether zero-exit means success or failure 41 } 42 43 var ( 44 testProcs = map[string]testProc{} 45 procName = "" 46 procArg = "" 47 ) 48 49 const ( 50 optName = "sys-unix-internal-procname" 51 optArg = "sys-unix-internal-arg" 52 ) 53 54 func init() { 55 flag.StringVar(&procName, optName, "", "internal use only") 56 flag.StringVar(&procArg, optArg, "", "internal use only") 57 58 } 59 60 func testCmd(procName string, procArg string) (*exec.Cmd, error) { 61 exe, err := filepath.Abs(os.Args[0]) 62 if err != nil { 63 return nil, err 64 } 65 cmd := exec.Command(exe, "-"+optName+"="+procName, "-"+optArg+"="+procArg) 66 cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr 67 return cmd, nil 68 } 69 70 // ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing 71 // a testProc with a key. 72 func ExitsCorrectly(t *testing.T, procName string) { 73 s := testProcs[procName] 74 arg := "-" 75 if s.arg != nil { 76 arg = s.arg(t) 77 } 78 c, err := testCmd(procName, arg) 79 defer func(arg string) { 80 if err := s.cleanup(arg); err != nil { 81 t.Fatalf("Failed to run cleanup for %s %s %#v", procName, err, err) 82 } 83 }(arg) 84 if err != nil { 85 t.Fatalf("Failed to construct command for %s", procName) 86 } 87 if (c.Run() == nil) != s.success { 88 result := "succeed" 89 if !s.success { 90 result = "fail" 91 } 92 t.Fatalf("Process did not %s when it was supposed to", result) 93 } 94 } 95 96 func TestMain(m *testing.M) { 97 flag.Parse() 98 if procName != "" { 99 t := testProcs[procName] 100 t.fn() 101 os.Stderr.WriteString("test function did not exit\n") 102 if t.success { 103 os.Exit(1) 104 } else { 105 os.Exit(0) 106 } 107 } 108 os.Exit(m.Run()) 109 } 110 111 // end of infrastructure 112 113 const testfile = "gocapmodetest" 114 const testfile2 = testfile + "2" 115 116 func CapEnterTest() { 117 _, err := os.OpenFile(path.Join(procArg, testfile), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 118 if err != nil { 119 panic(fmt.Sprintf("OpenFile: %s", err)) 120 } 121 122 err = unix.CapEnter() 123 if err != nil { 124 panic(fmt.Sprintf("CapEnter: %s", err)) 125 } 126 127 _, err = os.OpenFile(path.Join(procArg, testfile2), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 128 if err == nil { 129 panic("OpenFile works!") 130 } 131 if err.(*os.PathError).Err != unix.ECAPMODE { 132 panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err)) 133 } 134 os.Exit(0) 135 } 136 137 func makeTempDir(t *testing.T) string { 138 d, err := ioutil.TempDir("", "go_openat_test") 139 if err != nil { 140 t.Fatalf("TempDir failed: %s", err) 141 } 142 return d 143 } 144 145 func removeTempDir(arg string) error { 146 err := os.RemoveAll(arg) 147 if err != nil && err.(*os.PathError).Err == unix.ENOENT { 148 return nil 149 } 150 return err 151 } 152 153 func init() { 154 testProcs["cap_enter"] = testProc{ 155 CapEnterTest, 156 makeTempDir, 157 removeTempDir, 158 true, 159 } 160 } 161 162 func TestCapEnter(t *testing.T) { 163 if runtime.GOARCH != "amd64" { 164 t.Skipf("skipping test on %s", runtime.GOARCH) 165 } 166 ExitsCorrectly(t, "cap_enter") 167 } 168 169 func OpenatTest() { 170 f, err := os.Open(procArg) 171 if err != nil { 172 panic(err) 173 } 174 175 err = unix.CapEnter() 176 if err != nil { 177 panic(fmt.Sprintf("CapEnter: %s", err)) 178 } 179 180 fxx, err := unix.Openat(int(f.Fd()), "xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 181 if err != nil { 182 panic(err) 183 } 184 unix.Close(fxx) 185 186 // The right to open BASE/xx is not ambient 187 _, err = os.OpenFile(procArg+"/xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 188 if err == nil { 189 panic("OpenFile succeeded") 190 } 191 if err.(*os.PathError).Err != unix.ECAPMODE { 192 panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err)) 193 } 194 195 // Can't make a new directory either 196 err = os.Mkdir(procArg+"2", 0777) 197 if err == nil { 198 panic("MKdir succeeded") 199 } 200 if err.(*os.PathError).Err != unix.ECAPMODE { 201 panic(fmt.Sprintf("Mkdir failed wrong: %s %#v", err, err)) 202 } 203 204 // Remove all caps except read and lookup. 205 r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_LOOKUP}) 206 if err != nil { 207 panic(fmt.Sprintf("CapRightsInit failed: %s %#v", err, err)) 208 } 209 err = unix.CapRightsLimit(f.Fd(), r) 210 if err != nil { 211 panic(fmt.Sprintf("CapRightsLimit failed: %s %#v", err, err)) 212 } 213 214 // Check we can get the rights back again 215 r, err = unix.CapRightsGet(f.Fd()) 216 if err != nil { 217 panic(fmt.Sprintf("CapRightsGet failed: %s %#v", err, err)) 218 } 219 b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP}) 220 if err != nil { 221 panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err)) 222 } 223 if !b { 224 panic(fmt.Sprintf("Unexpected rights")) 225 } 226 b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP, unix.CAP_WRITE}) 227 if err != nil { 228 panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err)) 229 } 230 if b { 231 panic(fmt.Sprintf("Unexpected rights (2)")) 232 } 233 234 // Can no longer create a file 235 _, err = unix.Openat(int(f.Fd()), "xx2", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 236 if err == nil { 237 panic("Openat succeeded") 238 } 239 if err != unix.ENOTCAPABLE { 240 panic(fmt.Sprintf("OpenFileAt failed wrong: %s %#v", err, err)) 241 } 242 243 // But can read an existing one 244 _, err = unix.Openat(int(f.Fd()), "xx", os.O_RDONLY, 0666) 245 if err != nil { 246 panic(fmt.Sprintf("Openat failed: %s %#v", err, err)) 247 } 248 249 os.Exit(0) 250 } 251 252 func init() { 253 testProcs["openat"] = testProc{ 254 OpenatTest, 255 makeTempDir, 256 removeTempDir, 257 true, 258 } 259 } 260 261 func TestOpenat(t *testing.T) { 262 if runtime.GOARCH != "amd64" { 263 t.Skipf("skipping test on %s", runtime.GOARCH) 264 } 265 ExitsCorrectly(t, "openat") 266 } 267 268 func TestCapRightsSetAndClear(t *testing.T) { 269 r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT}) 270 if err != nil { 271 t.Fatalf("CapRightsInit failed: %s", err) 272 } 273 274 err = unix.CapRightsSet(r, []uint64{unix.CAP_EVENT, unix.CAP_LISTEN}) 275 if err != nil { 276 t.Fatalf("CapRightsSet failed: %s", err) 277 } 278 279 b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT, unix.CAP_EVENT, unix.CAP_LISTEN}) 280 if err != nil { 281 t.Fatalf("CapRightsIsSet failed: %s", err) 282 } 283 if !b { 284 t.Fatalf("Wrong rights set") 285 } 286 287 err = unix.CapRightsClear(r, []uint64{unix.CAP_READ, unix.CAP_PDWAIT}) 288 if err != nil { 289 t.Fatalf("CapRightsClear failed: %s", err) 290 } 291 292 b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_WRITE, unix.CAP_EVENT, unix.CAP_LISTEN}) 293 if err != nil { 294 t.Fatalf("CapRightsIsSet failed: %s", err) 295 } 296 if !b { 297 t.Fatalf("Wrong rights set") 298 } 299 } 300 301 func TestGetsockoptXucred(t *testing.T) { 302 fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) 303 if err != nil { 304 t.Fatalf("Socketpair: %v", err) 305 } 306 307 srvFile := os.NewFile(uintptr(fds[0]), "server") 308 cliFile := os.NewFile(uintptr(fds[1]), "client") 309 defer srvFile.Close() 310 defer cliFile.Close() 311 312 srv, err := net.FileConn(srvFile) 313 if err != nil { 314 t.Fatalf("FileConn: %v", err) 315 } 316 defer srv.Close() 317 318 cli, err := net.FileConn(cliFile) 319 if err != nil { 320 t.Fatalf("FileConn: %v", err) 321 } 322 defer cli.Close() 323 324 cred, err := unix.GetsockoptXucred(fds[1], unix.SOL_LOCAL, unix.LOCAL_PEERCRED) 325 if err == unix.ENOTCONN { 326 t.Skip("GetsockoptXucred not supported with Socketpair on FreeBSD 11 and earlier") 327 } else if err != nil { 328 t.Fatal(err) 329 } 330 t.Logf("got: %+v", cred) 331 if got, want := cred.Uid, os.Getuid(); int(got) != int(want) { 332 t.Errorf("uid = %v; want %v", got, want) 333 } 334 } 335 336 // stringsFromByteSlice converts a sequence of attributes to a []string. 337 // On FreeBSD, each entry consists of a single byte containing the length 338 // of the attribute name, followed by the attribute name. 339 // The name is _not_ NULL-terminated. 340 func stringsFromByteSlice(buf []byte) []string { 341 var result []string 342 i := 0 343 for i < len(buf) { 344 next := i + 1 + int(buf[i]) 345 result = append(result, string(buf[i+1:next])) 346 i = next 347 } 348 return result 349 }