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