github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/integration-cli/docker_cli_run_unix_test.go (about) 1 // +build !windows 2 3 package main 4 5 import ( 6 "bufio" 7 "context" 8 "encoding/json" 9 "fmt" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "regexp" 15 "strconv" 16 "strings" 17 "syscall" 18 "time" 19 20 "github.com/docker/docker/client" 21 "github.com/docker/docker/integration-cli/checker" 22 "github.com/docker/docker/integration-cli/cli" 23 "github.com/docker/docker/integration-cli/cli/build" 24 "github.com/docker/docker/pkg/homedir" 25 "github.com/docker/docker/pkg/mount" 26 "github.com/docker/docker/pkg/parsers" 27 "github.com/docker/docker/pkg/sysinfo" 28 "github.com/go-check/check" 29 "github.com/gotestyourself/gotestyourself/icmd" 30 "github.com/kr/pty" 31 ) 32 33 // #6509 34 func (s *DockerSuite) TestRunRedirectStdout(c *check.C) { 35 checkRedirect := func(command string) { 36 _, tty, err := pty.Open() 37 c.Assert(err, checker.IsNil, check.Commentf("Could not open pty")) 38 cmd := exec.Command("sh", "-c", command) 39 cmd.Stdin = tty 40 cmd.Stdout = tty 41 cmd.Stderr = tty 42 c.Assert(cmd.Start(), checker.IsNil) 43 ch := make(chan error) 44 go func() { 45 ch <- cmd.Wait() 46 close(ch) 47 }() 48 49 select { 50 case <-time.After(10 * time.Second): 51 c.Fatal("command timeout") 52 case err := <-ch: 53 c.Assert(err, checker.IsNil, check.Commentf("wait err")) 54 } 55 } 56 57 checkRedirect(dockerBinary + " run -i busybox cat /etc/passwd | grep -q root") 58 checkRedirect(dockerBinary + " run busybox cat /etc/passwd | grep -q root") 59 } 60 61 // Test recursive bind mount works by default 62 func (s *DockerSuite) TestRunWithVolumesIsRecursive(c *check.C) { 63 // /tmp gets permission denied 64 testRequires(c, NotUserNamespace, SameHostDaemon) 65 tmpDir, err := ioutil.TempDir("", "docker_recursive_mount_test") 66 c.Assert(err, checker.IsNil) 67 68 defer os.RemoveAll(tmpDir) 69 70 // Create a temporary tmpfs mount. 71 tmpfsDir := filepath.Join(tmpDir, "tmpfs") 72 c.Assert(os.MkdirAll(tmpfsDir, 0777), checker.IsNil, check.Commentf("failed to mkdir at %s", tmpfsDir)) 73 c.Assert(mount.Mount("tmpfs", tmpfsDir, "tmpfs", ""), checker.IsNil, check.Commentf("failed to create a tmpfs mount at %s", tmpfsDir)) 74 75 f, err := ioutil.TempFile(tmpfsDir, "touch-me") 76 c.Assert(err, checker.IsNil) 77 defer f.Close() 78 79 out, _ := dockerCmd(c, "run", "--name", "test-data", "--volume", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox:latest", "ls", "/tmp/tmpfs") 80 c.Assert(out, checker.Contains, filepath.Base(f.Name()), check.Commentf("Recursive bind mount test failed. Expected file not found")) 81 } 82 83 func (s *DockerSuite) TestRunDeviceDirectory(c *check.C) { 84 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm) 85 if _, err := os.Stat("/dev/snd"); err != nil { 86 c.Skip("Host does not have /dev/snd") 87 } 88 89 out, _ := dockerCmd(c, "run", "--device", "/dev/snd:/dev/snd", "busybox", "sh", "-c", "ls /dev/snd/") 90 c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "timer", check.Commentf("expected output /dev/snd/timer")) 91 92 out, _ = dockerCmd(c, "run", "--device", "/dev/snd:/dev/othersnd", "busybox", "sh", "-c", "ls /dev/othersnd/") 93 c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "seq", check.Commentf("expected output /dev/othersnd/seq")) 94 } 95 96 // TestRunAttachDetach checks attaching and detaching with the default escape sequence. 97 func (s *DockerSuite) TestRunAttachDetach(c *check.C) { 98 name := "attach-detach" 99 100 dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") 101 102 cmd := exec.Command(dockerBinary, "attach", name) 103 stdout, err := cmd.StdoutPipe() 104 c.Assert(err, checker.IsNil) 105 cpty, tty, err := pty.Open() 106 c.Assert(err, checker.IsNil) 107 defer cpty.Close() 108 cmd.Stdin = tty 109 c.Assert(cmd.Start(), checker.IsNil) 110 c.Assert(waitRun(name), check.IsNil) 111 112 _, err = cpty.Write([]byte("hello\n")) 113 c.Assert(err, checker.IsNil) 114 115 out, err := bufio.NewReader(stdout).ReadString('\n') 116 c.Assert(err, checker.IsNil) 117 c.Assert(strings.TrimSpace(out), checker.Equals, "hello") 118 119 // escape sequence 120 _, err = cpty.Write([]byte{16}) 121 c.Assert(err, checker.IsNil) 122 time.Sleep(100 * time.Millisecond) 123 _, err = cpty.Write([]byte{17}) 124 c.Assert(err, checker.IsNil) 125 126 ch := make(chan struct{}) 127 go func() { 128 cmd.Wait() 129 ch <- struct{}{} 130 }() 131 132 select { 133 case <-ch: 134 case <-time.After(10 * time.Second): 135 c.Fatal("timed out waiting for container to exit") 136 } 137 138 running := inspectField(c, name, "State.Running") 139 c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running")) 140 141 out, _ = dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c), "-f", "container="+name) 142 // attach and detach event should be monitored 143 c.Assert(out, checker.Contains, "attach") 144 c.Assert(out, checker.Contains, "detach") 145 } 146 147 // TestRunAttachDetachFromFlag checks attaching and detaching with the escape sequence specified via flags. 148 func (s *DockerSuite) TestRunAttachDetachFromFlag(c *check.C) { 149 name := "attach-detach" 150 keyCtrlA := []byte{1} 151 keyA := []byte{97} 152 153 dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") 154 155 cmd := exec.Command(dockerBinary, "attach", "--detach-keys=ctrl-a,a", name) 156 stdout, err := cmd.StdoutPipe() 157 if err != nil { 158 c.Fatal(err) 159 } 160 cpty, tty, err := pty.Open() 161 if err != nil { 162 c.Fatal(err) 163 } 164 defer cpty.Close() 165 cmd.Stdin = tty 166 if err := cmd.Start(); err != nil { 167 c.Fatal(err) 168 } 169 c.Assert(waitRun(name), check.IsNil) 170 171 if _, err := cpty.Write([]byte("hello\n")); err != nil { 172 c.Fatal(err) 173 } 174 175 out, err := bufio.NewReader(stdout).ReadString('\n') 176 if err != nil { 177 c.Fatal(err) 178 } 179 if strings.TrimSpace(out) != "hello" { 180 c.Fatalf("expected 'hello', got %q", out) 181 } 182 183 // escape sequence 184 if _, err := cpty.Write(keyCtrlA); err != nil { 185 c.Fatal(err) 186 } 187 time.Sleep(100 * time.Millisecond) 188 if _, err := cpty.Write(keyA); err != nil { 189 c.Fatal(err) 190 } 191 192 ch := make(chan struct{}) 193 go func() { 194 cmd.Wait() 195 ch <- struct{}{} 196 }() 197 198 select { 199 case <-ch: 200 case <-time.After(10 * time.Second): 201 c.Fatal("timed out waiting for container to exit") 202 } 203 204 running := inspectField(c, name, "State.Running") 205 c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running")) 206 } 207 208 // TestRunAttachDetachFromInvalidFlag checks attaching and detaching with the escape sequence specified via flags. 209 func (s *DockerSuite) TestRunAttachDetachFromInvalidFlag(c *check.C) { 210 name := "attach-detach" 211 dockerCmd(c, "run", "--name", name, "-itd", "busybox", "top") 212 c.Assert(waitRun(name), check.IsNil) 213 214 // specify an invalid detach key, container will ignore it and use default 215 cmd := exec.Command(dockerBinary, "attach", "--detach-keys=ctrl-A,a", name) 216 stdout, err := cmd.StdoutPipe() 217 if err != nil { 218 c.Fatal(err) 219 } 220 cpty, tty, err := pty.Open() 221 if err != nil { 222 c.Fatal(err) 223 } 224 defer cpty.Close() 225 cmd.Stdin = tty 226 if err := cmd.Start(); err != nil { 227 c.Fatal(err) 228 } 229 go cmd.Wait() 230 231 bufReader := bufio.NewReader(stdout) 232 out, err := bufReader.ReadString('\n') 233 if err != nil { 234 c.Fatal(err) 235 } 236 // it should print a warning to indicate the detach key flag is invalid 237 errStr := "Invalid detach keys (ctrl-A,a) provided" 238 c.Assert(strings.TrimSpace(out), checker.Equals, errStr) 239 } 240 241 // TestRunAttachDetachFromConfig checks attaching and detaching with the escape sequence specified via config file. 242 func (s *DockerSuite) TestRunAttachDetachFromConfig(c *check.C) { 243 keyCtrlA := []byte{1} 244 keyA := []byte{97} 245 246 // Setup config 247 homeKey := homedir.Key() 248 homeVal := homedir.Get() 249 tmpDir, err := ioutil.TempDir("", "fake-home") 250 c.Assert(err, checker.IsNil) 251 defer os.RemoveAll(tmpDir) 252 253 dotDocker := filepath.Join(tmpDir, ".docker") 254 os.Mkdir(dotDocker, 0600) 255 tmpCfg := filepath.Join(dotDocker, "config.json") 256 257 defer func() { os.Setenv(homeKey, homeVal) }() 258 os.Setenv(homeKey, tmpDir) 259 260 data := `{ 261 "detachKeys": "ctrl-a,a" 262 }` 263 264 err = ioutil.WriteFile(tmpCfg, []byte(data), 0600) 265 c.Assert(err, checker.IsNil) 266 267 // Then do the work 268 name := "attach-detach" 269 dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") 270 271 cmd := exec.Command(dockerBinary, "attach", name) 272 stdout, err := cmd.StdoutPipe() 273 if err != nil { 274 c.Fatal(err) 275 } 276 cpty, tty, err := pty.Open() 277 if err != nil { 278 c.Fatal(err) 279 } 280 defer cpty.Close() 281 cmd.Stdin = tty 282 if err := cmd.Start(); err != nil { 283 c.Fatal(err) 284 } 285 c.Assert(waitRun(name), check.IsNil) 286 287 if _, err := cpty.Write([]byte("hello\n")); err != nil { 288 c.Fatal(err) 289 } 290 291 out, err := bufio.NewReader(stdout).ReadString('\n') 292 if err != nil { 293 c.Fatal(err) 294 } 295 if strings.TrimSpace(out) != "hello" { 296 c.Fatalf("expected 'hello', got %q", out) 297 } 298 299 // escape sequence 300 if _, err := cpty.Write(keyCtrlA); err != nil { 301 c.Fatal(err) 302 } 303 time.Sleep(100 * time.Millisecond) 304 if _, err := cpty.Write(keyA); err != nil { 305 c.Fatal(err) 306 } 307 308 ch := make(chan struct{}) 309 go func() { 310 cmd.Wait() 311 ch <- struct{}{} 312 }() 313 314 select { 315 case <-ch: 316 case <-time.After(10 * time.Second): 317 c.Fatal("timed out waiting for container to exit") 318 } 319 320 running := inspectField(c, name, "State.Running") 321 c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running")) 322 } 323 324 // TestRunAttachDetachKeysOverrideConfig checks attaching and detaching with the detach flags, making sure it overrides config file 325 func (s *DockerSuite) TestRunAttachDetachKeysOverrideConfig(c *check.C) { 326 keyCtrlA := []byte{1} 327 keyA := []byte{97} 328 329 // Setup config 330 homeKey := homedir.Key() 331 homeVal := homedir.Get() 332 tmpDir, err := ioutil.TempDir("", "fake-home") 333 c.Assert(err, checker.IsNil) 334 defer os.RemoveAll(tmpDir) 335 336 dotDocker := filepath.Join(tmpDir, ".docker") 337 os.Mkdir(dotDocker, 0600) 338 tmpCfg := filepath.Join(dotDocker, "config.json") 339 340 defer func() { os.Setenv(homeKey, homeVal) }() 341 os.Setenv(homeKey, tmpDir) 342 343 data := `{ 344 "detachKeys": "ctrl-e,e" 345 }` 346 347 err = ioutil.WriteFile(tmpCfg, []byte(data), 0600) 348 c.Assert(err, checker.IsNil) 349 350 // Then do the work 351 name := "attach-detach" 352 dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") 353 354 cmd := exec.Command(dockerBinary, "attach", "--detach-keys=ctrl-a,a", name) 355 stdout, err := cmd.StdoutPipe() 356 if err != nil { 357 c.Fatal(err) 358 } 359 cpty, tty, err := pty.Open() 360 if err != nil { 361 c.Fatal(err) 362 } 363 defer cpty.Close() 364 cmd.Stdin = tty 365 if err := cmd.Start(); err != nil { 366 c.Fatal(err) 367 } 368 c.Assert(waitRun(name), check.IsNil) 369 370 if _, err := cpty.Write([]byte("hello\n")); err != nil { 371 c.Fatal(err) 372 } 373 374 out, err := bufio.NewReader(stdout).ReadString('\n') 375 if err != nil { 376 c.Fatal(err) 377 } 378 if strings.TrimSpace(out) != "hello" { 379 c.Fatalf("expected 'hello', got %q", out) 380 } 381 382 // escape sequence 383 if _, err := cpty.Write(keyCtrlA); err != nil { 384 c.Fatal(err) 385 } 386 time.Sleep(100 * time.Millisecond) 387 if _, err := cpty.Write(keyA); err != nil { 388 c.Fatal(err) 389 } 390 391 ch := make(chan struct{}) 392 go func() { 393 cmd.Wait() 394 ch <- struct{}{} 395 }() 396 397 select { 398 case <-ch: 399 case <-time.After(10 * time.Second): 400 c.Fatal("timed out waiting for container to exit") 401 } 402 403 running := inspectField(c, name, "State.Running") 404 c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running")) 405 } 406 407 func (s *DockerSuite) TestRunAttachInvalidDetachKeySequencePreserved(c *check.C) { 408 name := "attach-detach" 409 keyA := []byte{97} 410 keyB := []byte{98} 411 412 dockerCmd(c, "run", "--name", name, "-itd", "busybox", "cat") 413 414 cmd := exec.Command(dockerBinary, "attach", "--detach-keys=a,b,c", name) 415 stdout, err := cmd.StdoutPipe() 416 if err != nil { 417 c.Fatal(err) 418 } 419 cpty, tty, err := pty.Open() 420 if err != nil { 421 c.Fatal(err) 422 } 423 defer cpty.Close() 424 cmd.Stdin = tty 425 if err := cmd.Start(); err != nil { 426 c.Fatal(err) 427 } 428 go cmd.Wait() 429 c.Assert(waitRun(name), check.IsNil) 430 431 // Invalid escape sequence aba, should print aba in output 432 if _, err := cpty.Write(keyA); err != nil { 433 c.Fatal(err) 434 } 435 time.Sleep(100 * time.Millisecond) 436 if _, err := cpty.Write(keyB); err != nil { 437 c.Fatal(err) 438 } 439 time.Sleep(100 * time.Millisecond) 440 if _, err := cpty.Write(keyA); err != nil { 441 c.Fatal(err) 442 } 443 time.Sleep(100 * time.Millisecond) 444 if _, err := cpty.Write([]byte("\n")); err != nil { 445 c.Fatal(err) 446 } 447 448 out, err := bufio.NewReader(stdout).ReadString('\n') 449 if err != nil { 450 c.Fatal(err) 451 } 452 if strings.TrimSpace(out) != "aba" { 453 c.Fatalf("expected 'aba', got %q", out) 454 } 455 } 456 457 // "test" should be printed 458 func (s *DockerSuite) TestRunWithCPUQuota(c *check.C) { 459 testRequires(c, cpuCfsQuota) 460 461 file := "/sys/fs/cgroup/cpu/cpu.cfs_quota_us" 462 out, _ := dockerCmd(c, "run", "--cpu-quota", "8000", "--name", "test", "busybox", "cat", file) 463 c.Assert(strings.TrimSpace(out), checker.Equals, "8000") 464 465 out = inspectField(c, "test", "HostConfig.CpuQuota") 466 c.Assert(out, checker.Equals, "8000", check.Commentf("setting the CPU CFS quota failed")) 467 } 468 469 func (s *DockerSuite) TestRunWithCpuPeriod(c *check.C) { 470 testRequires(c, cpuCfsPeriod) 471 472 file := "/sys/fs/cgroup/cpu/cpu.cfs_period_us" 473 out, _ := dockerCmd(c, "run", "--cpu-period", "50000", "--name", "test", "busybox", "cat", file) 474 c.Assert(strings.TrimSpace(out), checker.Equals, "50000") 475 476 out, _ = dockerCmd(c, "run", "--cpu-period", "0", "busybox", "cat", file) 477 c.Assert(strings.TrimSpace(out), checker.Equals, "100000") 478 479 out = inspectField(c, "test", "HostConfig.CpuPeriod") 480 c.Assert(out, checker.Equals, "50000", check.Commentf("setting the CPU CFS period failed")) 481 } 482 483 func (s *DockerSuite) TestRunWithInvalidCpuPeriod(c *check.C) { 484 testRequires(c, cpuCfsPeriod) 485 out, _, err := dockerCmdWithError("run", "--cpu-period", "900", "busybox", "true") 486 c.Assert(err, check.NotNil) 487 expected := "CPU cfs period can not be less than 1ms (i.e. 1000) or larger than 1s (i.e. 1000000)" 488 c.Assert(out, checker.Contains, expected) 489 490 out, _, err = dockerCmdWithError("run", "--cpu-period", "2000000", "busybox", "true") 491 c.Assert(err, check.NotNil) 492 c.Assert(out, checker.Contains, expected) 493 494 out, _, err = dockerCmdWithError("run", "--cpu-period", "-3", "busybox", "true") 495 c.Assert(err, check.NotNil) 496 c.Assert(out, checker.Contains, expected) 497 } 498 499 func (s *DockerSuite) TestRunWithKernelMemory(c *check.C) { 500 testRequires(c, kernelMemorySupport) 501 502 file := "/sys/fs/cgroup/memory/memory.kmem.limit_in_bytes" 503 cli.DockerCmd(c, "run", "--kernel-memory", "50M", "--name", "test1", "busybox", "cat", file).Assert(c, icmd.Expected{ 504 Out: "52428800", 505 }) 506 507 cli.InspectCmd(c, "test1", cli.Format(".HostConfig.KernelMemory")).Assert(c, icmd.Expected{ 508 Out: "52428800", 509 }) 510 } 511 512 func (s *DockerSuite) TestRunWithInvalidKernelMemory(c *check.C) { 513 testRequires(c, kernelMemorySupport) 514 515 out, _, err := dockerCmdWithError("run", "--kernel-memory", "2M", "busybox", "true") 516 c.Assert(err, check.NotNil) 517 expected := "Minimum kernel memory limit allowed is 4MB" 518 c.Assert(out, checker.Contains, expected) 519 520 out, _, err = dockerCmdWithError("run", "--kernel-memory", "-16m", "--name", "test2", "busybox", "echo", "test") 521 c.Assert(err, check.NotNil) 522 expected = "invalid size" 523 c.Assert(out, checker.Contains, expected) 524 } 525 526 func (s *DockerSuite) TestRunWithCPUShares(c *check.C) { 527 testRequires(c, cpuShare) 528 529 file := "/sys/fs/cgroup/cpu/cpu.shares" 530 out, _ := dockerCmd(c, "run", "--cpu-shares", "1000", "--name", "test", "busybox", "cat", file) 531 c.Assert(strings.TrimSpace(out), checker.Equals, "1000") 532 533 out = inspectField(c, "test", "HostConfig.CPUShares") 534 c.Assert(out, check.Equals, "1000") 535 } 536 537 // "test" should be printed 538 func (s *DockerSuite) TestRunEchoStdoutWithCPUSharesAndMemoryLimit(c *check.C) { 539 testRequires(c, cpuShare) 540 testRequires(c, memoryLimitSupport) 541 cli.DockerCmd(c, "run", "--cpu-shares", "1000", "-m", "32m", "busybox", "echo", "test").Assert(c, icmd.Expected{ 542 Out: "test\n", 543 }) 544 } 545 546 func (s *DockerSuite) TestRunWithCpusetCpus(c *check.C) { 547 testRequires(c, cgroupCpuset) 548 549 file := "/sys/fs/cgroup/cpuset/cpuset.cpus" 550 out, _ := dockerCmd(c, "run", "--cpuset-cpus", "0", "--name", "test", "busybox", "cat", file) 551 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 552 553 out = inspectField(c, "test", "HostConfig.CpusetCpus") 554 c.Assert(out, check.Equals, "0") 555 } 556 557 func (s *DockerSuite) TestRunWithCpusetMems(c *check.C) { 558 testRequires(c, cgroupCpuset) 559 560 file := "/sys/fs/cgroup/cpuset/cpuset.mems" 561 out, _ := dockerCmd(c, "run", "--cpuset-mems", "0", "--name", "test", "busybox", "cat", file) 562 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 563 564 out = inspectField(c, "test", "HostConfig.CpusetMems") 565 c.Assert(out, check.Equals, "0") 566 } 567 568 func (s *DockerSuite) TestRunWithBlkioWeight(c *check.C) { 569 testRequires(c, blkioWeight) 570 571 file := "/sys/fs/cgroup/blkio/blkio.weight" 572 out, _ := dockerCmd(c, "run", "--blkio-weight", "300", "--name", "test", "busybox", "cat", file) 573 c.Assert(strings.TrimSpace(out), checker.Equals, "300") 574 575 out = inspectField(c, "test", "HostConfig.BlkioWeight") 576 c.Assert(out, check.Equals, "300") 577 } 578 579 func (s *DockerSuite) TestRunWithInvalidBlkioWeight(c *check.C) { 580 testRequires(c, blkioWeight) 581 out, _, err := dockerCmdWithError("run", "--blkio-weight", "5", "busybox", "true") 582 c.Assert(err, check.NotNil, check.Commentf(out)) 583 expected := "Range of blkio weight is from 10 to 1000" 584 c.Assert(out, checker.Contains, expected) 585 } 586 587 func (s *DockerSuite) TestRunWithInvalidPathforBlkioWeightDevice(c *check.C) { 588 testRequires(c, blkioWeight) 589 out, _, err := dockerCmdWithError("run", "--blkio-weight-device", "/dev/sdX:100", "busybox", "true") 590 c.Assert(err, check.NotNil, check.Commentf(out)) 591 } 592 593 func (s *DockerSuite) TestRunWithInvalidPathforBlkioDeviceReadBps(c *check.C) { 594 testRequires(c, blkioWeight) 595 out, _, err := dockerCmdWithError("run", "--device-read-bps", "/dev/sdX:500", "busybox", "true") 596 c.Assert(err, check.NotNil, check.Commentf(out)) 597 } 598 599 func (s *DockerSuite) TestRunWithInvalidPathforBlkioDeviceWriteBps(c *check.C) { 600 testRequires(c, blkioWeight) 601 out, _, err := dockerCmdWithError("run", "--device-write-bps", "/dev/sdX:500", "busybox", "true") 602 c.Assert(err, check.NotNil, check.Commentf(out)) 603 } 604 605 func (s *DockerSuite) TestRunWithInvalidPathforBlkioDeviceReadIOps(c *check.C) { 606 testRequires(c, blkioWeight) 607 out, _, err := dockerCmdWithError("run", "--device-read-iops", "/dev/sdX:500", "busybox", "true") 608 c.Assert(err, check.NotNil, check.Commentf(out)) 609 } 610 611 func (s *DockerSuite) TestRunWithInvalidPathforBlkioDeviceWriteIOps(c *check.C) { 612 testRequires(c, blkioWeight) 613 out, _, err := dockerCmdWithError("run", "--device-write-iops", "/dev/sdX:500", "busybox", "true") 614 c.Assert(err, check.NotNil, check.Commentf(out)) 615 } 616 617 func (s *DockerSuite) TestRunOOMExitCode(c *check.C) { 618 testRequires(c, memoryLimitSupport, swapMemorySupport) 619 errChan := make(chan error) 620 go func() { 621 defer close(errChan) 622 out, exitCode, _ := dockerCmdWithError("run", "-m", "4MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done") 623 if expected := 137; exitCode != expected { 624 errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) 625 } 626 }() 627 628 select { 629 case err := <-errChan: 630 c.Assert(err, check.IsNil) 631 case <-time.After(600 * time.Second): 632 c.Fatal("Timeout waiting for container to die on OOM") 633 } 634 } 635 636 func (s *DockerSuite) TestRunWithMemoryLimit(c *check.C) { 637 testRequires(c, memoryLimitSupport) 638 639 file := "/sys/fs/cgroup/memory/memory.limit_in_bytes" 640 cli.DockerCmd(c, "run", "-m", "32M", "--name", "test", "busybox", "cat", file).Assert(c, icmd.Expected{ 641 Out: "33554432", 642 }) 643 cli.InspectCmd(c, "test", cli.Format(".HostConfig.Memory")).Assert(c, icmd.Expected{ 644 Out: "33554432", 645 }) 646 } 647 648 // TestRunWithoutMemoryswapLimit sets memory limit and disables swap 649 // memory limit, this means the processes in the container can use 650 // 16M memory and as much swap memory as they need (if the host 651 // supports swap memory). 652 func (s *DockerSuite) TestRunWithoutMemoryswapLimit(c *check.C) { 653 testRequires(c, DaemonIsLinux) 654 testRequires(c, memoryLimitSupport) 655 testRequires(c, swapMemorySupport) 656 dockerCmd(c, "run", "-m", "32m", "--memory-swap", "-1", "busybox", "true") 657 } 658 659 func (s *DockerSuite) TestRunWithSwappiness(c *check.C) { 660 testRequires(c, memorySwappinessSupport) 661 file := "/sys/fs/cgroup/memory/memory.swappiness" 662 out, _ := dockerCmd(c, "run", "--memory-swappiness", "0", "--name", "test", "busybox", "cat", file) 663 c.Assert(strings.TrimSpace(out), checker.Equals, "0") 664 665 out = inspectField(c, "test", "HostConfig.MemorySwappiness") 666 c.Assert(out, check.Equals, "0") 667 } 668 669 func (s *DockerSuite) TestRunWithSwappinessInvalid(c *check.C) { 670 testRequires(c, memorySwappinessSupport) 671 out, _, err := dockerCmdWithError("run", "--memory-swappiness", "101", "busybox", "true") 672 c.Assert(err, check.NotNil) 673 expected := "Valid memory swappiness range is 0-100" 674 c.Assert(out, checker.Contains, expected, check.Commentf("Expected output to contain %q, not %q", out, expected)) 675 676 out, _, err = dockerCmdWithError("run", "--memory-swappiness", "-10", "busybox", "true") 677 c.Assert(err, check.NotNil) 678 c.Assert(out, checker.Contains, expected, check.Commentf("Expected output to contain %q, not %q", out, expected)) 679 } 680 681 func (s *DockerSuite) TestRunWithMemoryReservation(c *check.C) { 682 testRequires(c, SameHostDaemon, memoryReservationSupport) 683 684 file := "/sys/fs/cgroup/memory/memory.soft_limit_in_bytes" 685 out, _ := dockerCmd(c, "run", "--memory-reservation", "200M", "--name", "test", "busybox", "cat", file) 686 c.Assert(strings.TrimSpace(out), checker.Equals, "209715200") 687 688 out = inspectField(c, "test", "HostConfig.MemoryReservation") 689 c.Assert(out, check.Equals, "209715200") 690 } 691 692 func (s *DockerSuite) TestRunWithMemoryReservationInvalid(c *check.C) { 693 testRequires(c, memoryLimitSupport) 694 testRequires(c, SameHostDaemon, memoryReservationSupport) 695 out, _, err := dockerCmdWithError("run", "-m", "500M", "--memory-reservation", "800M", "busybox", "true") 696 c.Assert(err, check.NotNil) 697 expected := "Minimum memory limit can not be less than memory reservation limit" 698 c.Assert(strings.TrimSpace(out), checker.Contains, expected, check.Commentf("run container should fail with invalid memory reservation")) 699 700 out, _, err = dockerCmdWithError("run", "--memory-reservation", "1k", "busybox", "true") 701 c.Assert(err, check.NotNil) 702 expected = "Minimum memory reservation allowed is 4MB" 703 c.Assert(strings.TrimSpace(out), checker.Contains, expected, check.Commentf("run container should fail with invalid memory reservation")) 704 } 705 706 func (s *DockerSuite) TestStopContainerSignal(c *check.C) { 707 out, _ := dockerCmd(c, "run", "--stop-signal", "SIGUSR1", "-d", "busybox", "/bin/sh", "-c", `trap 'echo "exit trapped"; exit 0' USR1; while true; do sleep 1; done`) 708 containerID := strings.TrimSpace(out) 709 710 c.Assert(waitRun(containerID), checker.IsNil) 711 712 dockerCmd(c, "stop", containerID) 713 out, _ = dockerCmd(c, "logs", containerID) 714 715 c.Assert(out, checker.Contains, "exit trapped", check.Commentf("Expected `exit trapped` in the log")) 716 } 717 718 func (s *DockerSuite) TestRunSwapLessThanMemoryLimit(c *check.C) { 719 testRequires(c, memoryLimitSupport) 720 testRequires(c, swapMemorySupport) 721 out, _, err := dockerCmdWithError("run", "-m", "16m", "--memory-swap", "15m", "busybox", "echo", "test") 722 expected := "Minimum memoryswap limit should be larger than memory limit" 723 c.Assert(err, check.NotNil) 724 725 c.Assert(out, checker.Contains, expected) 726 } 727 728 func (s *DockerSuite) TestRunInvalidCpusetCpusFlagValue(c *check.C) { 729 testRequires(c, cgroupCpuset, SameHostDaemon) 730 731 sysInfo := sysinfo.New(true) 732 cpus, err := parsers.ParseUintList(sysInfo.Cpus) 733 c.Assert(err, check.IsNil) 734 var invalid int 735 for i := 0; i <= len(cpus)+1; i++ { 736 if !cpus[i] { 737 invalid = i 738 break 739 } 740 } 741 out, _, err := dockerCmdWithError("run", "--cpuset-cpus", strconv.Itoa(invalid), "busybox", "true") 742 c.Assert(err, check.NotNil) 743 expected := fmt.Sprintf("Error response from daemon: Requested CPUs are not available - requested %s, available: %s", strconv.Itoa(invalid), sysInfo.Cpus) 744 c.Assert(out, checker.Contains, expected) 745 } 746 747 func (s *DockerSuite) TestRunInvalidCpusetMemsFlagValue(c *check.C) { 748 testRequires(c, cgroupCpuset) 749 750 sysInfo := sysinfo.New(true) 751 mems, err := parsers.ParseUintList(sysInfo.Mems) 752 c.Assert(err, check.IsNil) 753 var invalid int 754 for i := 0; i <= len(mems)+1; i++ { 755 if !mems[i] { 756 invalid = i 757 break 758 } 759 } 760 out, _, err := dockerCmdWithError("run", "--cpuset-mems", strconv.Itoa(invalid), "busybox", "true") 761 c.Assert(err, check.NotNil) 762 expected := fmt.Sprintf("Error response from daemon: Requested memory nodes are not available - requested %s, available: %s", strconv.Itoa(invalid), sysInfo.Mems) 763 c.Assert(out, checker.Contains, expected) 764 } 765 766 func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) { 767 testRequires(c, cpuShare, DaemonIsLinux) 768 out, _, err := dockerCmdWithError("run", "--cpu-shares", "1", "busybox", "echo", "test") 769 c.Assert(err, check.NotNil, check.Commentf(out)) 770 expected := "The minimum allowed cpu-shares is 2" 771 c.Assert(out, checker.Contains, expected) 772 773 out, _, err = dockerCmdWithError("run", "--cpu-shares", "-1", "busybox", "echo", "test") 774 c.Assert(err, check.NotNil, check.Commentf(out)) 775 expected = "shares: invalid argument" 776 c.Assert(out, checker.Contains, expected) 777 778 out, _, err = dockerCmdWithError("run", "--cpu-shares", "99999999", "busybox", "echo", "test") 779 c.Assert(err, check.NotNil, check.Commentf(out)) 780 expected = "The maximum allowed cpu-shares is" 781 c.Assert(out, checker.Contains, expected) 782 } 783 784 func (s *DockerSuite) TestRunWithDefaultShmSize(c *check.C) { 785 testRequires(c, DaemonIsLinux) 786 787 name := "shm-default" 788 out, _ := dockerCmd(c, "run", "--name", name, "busybox", "mount") 789 shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`) 790 if !shmRegex.MatchString(out) { 791 c.Fatalf("Expected shm of 64MB in mount command, got %v", out) 792 } 793 shmSize := inspectField(c, name, "HostConfig.ShmSize") 794 c.Assert(shmSize, check.Equals, "67108864") 795 } 796 797 func (s *DockerSuite) TestRunWithShmSize(c *check.C) { 798 testRequires(c, DaemonIsLinux) 799 800 name := "shm" 801 out, _ := dockerCmd(c, "run", "--name", name, "--shm-size=1G", "busybox", "mount") 802 shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`) 803 if !shmRegex.MatchString(out) { 804 c.Fatalf("Expected shm of 1GB in mount command, got %v", out) 805 } 806 shmSize := inspectField(c, name, "HostConfig.ShmSize") 807 c.Assert(shmSize, check.Equals, "1073741824") 808 } 809 810 func (s *DockerSuite) TestRunTmpfsMountsEnsureOrdered(c *check.C) { 811 tmpFile, err := ioutil.TempFile("", "test") 812 c.Assert(err, check.IsNil) 813 defer tmpFile.Close() 814 out, _ := dockerCmd(c, "run", "--tmpfs", "/run", "-v", tmpFile.Name()+":/run/test", "busybox", "ls", "/run") 815 c.Assert(out, checker.Contains, "test") 816 } 817 818 func (s *DockerSuite) TestRunTmpfsMounts(c *check.C) { 819 // TODO Windows (Post TP5): This test cannot run on a Windows daemon as 820 // Windows does not support tmpfs mounts. 821 testRequires(c, DaemonIsLinux) 822 if out, _, err := dockerCmdWithError("run", "--tmpfs", "/run", "busybox", "touch", "/run/somefile"); err != nil { 823 c.Fatalf("/run directory not mounted on tmpfs %q %s", err, out) 824 } 825 if out, _, err := dockerCmdWithError("run", "--tmpfs", "/run:noexec", "busybox", "touch", "/run/somefile"); err != nil { 826 c.Fatalf("/run directory not mounted on tmpfs %q %s", err, out) 827 } 828 if out, _, err := dockerCmdWithError("run", "--tmpfs", "/run:noexec,nosuid,rw,size=5k,mode=700", "busybox", "touch", "/run/somefile"); err != nil { 829 c.Fatalf("/run failed to mount on tmpfs with valid options %q %s", err, out) 830 } 831 if _, _, err := dockerCmdWithError("run", "--tmpfs", "/run:foobar", "busybox", "touch", "/run/somefile"); err == nil { 832 c.Fatalf("/run mounted on tmpfs when it should have vailed within invalid mount option") 833 } 834 if _, _, err := dockerCmdWithError("run", "--tmpfs", "/run", "-v", "/run:/run", "busybox", "touch", "/run/somefile"); err == nil { 835 c.Fatalf("Should have generated an error saying Duplicate mount points") 836 } 837 } 838 839 func (s *DockerSuite) TestRunTmpfsMountsOverrideImageVolumes(c *check.C) { 840 name := "img-with-volumes" 841 buildImageSuccessfully(c, name, build.WithDockerfile(` 842 FROM busybox 843 VOLUME /run 844 RUN touch /run/stuff 845 `)) 846 out, _ := dockerCmd(c, "run", "--tmpfs", "/run", name, "ls", "/run") 847 c.Assert(out, checker.Not(checker.Contains), "stuff") 848 } 849 850 // Test case for #22420 851 func (s *DockerSuite) TestRunTmpfsMountsWithOptions(c *check.C) { 852 testRequires(c, DaemonIsLinux) 853 854 expectedOptions := []string{"rw", "nosuid", "nodev", "noexec", "relatime"} 855 out, _ := dockerCmd(c, "run", "--tmpfs", "/tmp", "busybox", "sh", "-c", "mount | grep 'tmpfs on /tmp'") 856 for _, option := range expectedOptions { 857 c.Assert(out, checker.Contains, option) 858 } 859 c.Assert(out, checker.Not(checker.Contains), "size=") 860 861 expectedOptions = []string{"rw", "nosuid", "nodev", "noexec", "relatime"} 862 out, _ = dockerCmd(c, "run", "--tmpfs", "/tmp:rw", "busybox", "sh", "-c", "mount | grep 'tmpfs on /tmp'") 863 for _, option := range expectedOptions { 864 c.Assert(out, checker.Contains, option) 865 } 866 c.Assert(out, checker.Not(checker.Contains), "size=") 867 868 expectedOptions = []string{"rw", "nosuid", "nodev", "relatime", "size=8192k"} 869 out, _ = dockerCmd(c, "run", "--tmpfs", "/tmp:rw,exec,size=8192k", "busybox", "sh", "-c", "mount | grep 'tmpfs on /tmp'") 870 for _, option := range expectedOptions { 871 c.Assert(out, checker.Contains, option) 872 } 873 874 expectedOptions = []string{"rw", "nosuid", "nodev", "noexec", "relatime", "size=4096k"} 875 out, _ = dockerCmd(c, "run", "--tmpfs", "/tmp:rw,size=8192k,exec,size=4096k,noexec", "busybox", "sh", "-c", "mount | grep 'tmpfs on /tmp'") 876 for _, option := range expectedOptions { 877 c.Assert(out, checker.Contains, option) 878 } 879 880 // We use debian:jessie as there is no findmnt in busybox. Also the output will be in the format of 881 // TARGET PROPAGATION 882 // /tmp shared 883 // so we only capture `shared` here. 884 expectedOptions = []string{"shared"} 885 out, _ = dockerCmd(c, "run", "--tmpfs", "/tmp:shared", "debian:jessie", "findmnt", "-o", "TARGET,PROPAGATION", "/tmp") 886 for _, option := range expectedOptions { 887 c.Assert(out, checker.Contains, option) 888 } 889 } 890 891 func (s *DockerSuite) TestRunSysctls(c *check.C) { 892 testRequires(c, DaemonIsLinux) 893 var err error 894 895 out, _ := dockerCmd(c, "run", "--sysctl", "net.ipv4.ip_forward=1", "--name", "test", "busybox", "cat", "/proc/sys/net/ipv4/ip_forward") 896 c.Assert(strings.TrimSpace(out), check.Equals, "1") 897 898 out = inspectFieldJSON(c, "test", "HostConfig.Sysctls") 899 900 sysctls := make(map[string]string) 901 err = json.Unmarshal([]byte(out), &sysctls) 902 c.Assert(err, check.IsNil) 903 c.Assert(sysctls["net.ipv4.ip_forward"], check.Equals, "1") 904 905 out, _ = dockerCmd(c, "run", "--sysctl", "net.ipv4.ip_forward=0", "--name", "test1", "busybox", "cat", "/proc/sys/net/ipv4/ip_forward") 906 c.Assert(strings.TrimSpace(out), check.Equals, "0") 907 908 out = inspectFieldJSON(c, "test1", "HostConfig.Sysctls") 909 910 err = json.Unmarshal([]byte(out), &sysctls) 911 c.Assert(err, check.IsNil) 912 c.Assert(sysctls["net.ipv4.ip_forward"], check.Equals, "0") 913 914 icmd.RunCommand(dockerBinary, "run", "--sysctl", "kernel.foobar=1", "--name", "test2", 915 "busybox", "cat", "/proc/sys/kernel/foobar").Assert(c, icmd.Expected{ 916 ExitCode: 125, 917 Err: "invalid argument", 918 }) 919 } 920 921 // TestRunSeccompProfileDenyUnshare checks that 'docker run --security-opt seccomp=/tmp/profile.json debian:jessie unshare' exits with operation not permitted. 922 func (s *DockerSuite) TestRunSeccompProfileDenyUnshare(c *check.C) { 923 testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor) 924 jsonData := `{ 925 "defaultAction": "SCMP_ACT_ALLOW", 926 "syscalls": [ 927 { 928 "name": "unshare", 929 "action": "SCMP_ACT_ERRNO" 930 } 931 ] 932 }` 933 tmpFile, err := ioutil.TempFile("", "profile.json") 934 if err != nil { 935 c.Fatal(err) 936 } 937 defer tmpFile.Close() 938 939 if _, err := tmpFile.Write([]byte(jsonData)); err != nil { 940 c.Fatal(err) 941 } 942 icmd.RunCommand(dockerBinary, "run", "--security-opt", "apparmor=unconfined", 943 "--security-opt", "seccomp="+tmpFile.Name(), 944 "debian:jessie", "unshare", "-p", "-m", "-f", "-r", "mount", "-t", "proc", "none", "/proc").Assert(c, icmd.Expected{ 945 ExitCode: 1, 946 Err: "Operation not permitted", 947 }) 948 } 949 950 // TestRunSeccompProfileDenyChmod checks that 'docker run --security-opt seccomp=/tmp/profile.json busybox chmod 400 /etc/hostname' exits with operation not permitted. 951 func (s *DockerSuite) TestRunSeccompProfileDenyChmod(c *check.C) { 952 testRequires(c, SameHostDaemon, seccompEnabled) 953 jsonData := `{ 954 "defaultAction": "SCMP_ACT_ALLOW", 955 "syscalls": [ 956 { 957 "name": "chmod", 958 "action": "SCMP_ACT_ERRNO" 959 }, 960 { 961 "name":"fchmod", 962 "action": "SCMP_ACT_ERRNO" 963 }, 964 { 965 "name": "fchmodat", 966 "action":"SCMP_ACT_ERRNO" 967 } 968 ] 969 }` 970 tmpFile, err := ioutil.TempFile("", "profile.json") 971 c.Assert(err, check.IsNil) 972 defer tmpFile.Close() 973 974 if _, err := tmpFile.Write([]byte(jsonData)); err != nil { 975 c.Fatal(err) 976 } 977 icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp="+tmpFile.Name(), 978 "busybox", "chmod", "400", "/etc/hostname").Assert(c, icmd.Expected{ 979 ExitCode: 1, 980 Err: "Operation not permitted", 981 }) 982 } 983 984 // TestRunSeccompProfileDenyUnshareUserns checks that 'docker run debian:jessie unshare --map-root-user --user sh -c whoami' with a specific profile to 985 // deny unshare of a userns exits with operation not permitted. 986 func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) { 987 testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor) 988 // from sched.h 989 jsonData := fmt.Sprintf(`{ 990 "defaultAction": "SCMP_ACT_ALLOW", 991 "syscalls": [ 992 { 993 "name": "unshare", 994 "action": "SCMP_ACT_ERRNO", 995 "args": [ 996 { 997 "index": 0, 998 "value": %d, 999 "op": "SCMP_CMP_EQ" 1000 } 1001 ] 1002 } 1003 ] 1004 }`, uint64(0x10000000)) 1005 tmpFile, err := ioutil.TempFile("", "profile.json") 1006 if err != nil { 1007 c.Fatal(err) 1008 } 1009 defer tmpFile.Close() 1010 1011 if _, err := tmpFile.Write([]byte(jsonData)); err != nil { 1012 c.Fatal(err) 1013 } 1014 icmd.RunCommand(dockerBinary, "run", 1015 "--security-opt", "apparmor=unconfined", "--security-opt", "seccomp="+tmpFile.Name(), 1016 "debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami").Assert(c, icmd.Expected{ 1017 ExitCode: 1, 1018 Err: "Operation not permitted", 1019 }) 1020 } 1021 1022 // TestRunSeccompProfileDenyCloneUserns checks that 'docker run syscall-test' 1023 // with a the default seccomp profile exits with operation not permitted. 1024 func (s *DockerSuite) TestRunSeccompProfileDenyCloneUserns(c *check.C) { 1025 testRequires(c, SameHostDaemon, seccompEnabled) 1026 ensureSyscallTest(c) 1027 1028 icmd.RunCommand(dockerBinary, "run", "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{ 1029 ExitCode: 1, 1030 Err: "clone failed: Operation not permitted", 1031 }) 1032 } 1033 1034 // TestRunSeccompUnconfinedCloneUserns checks that 1035 // 'docker run --security-opt seccomp=unconfined syscall-test' allows creating a userns. 1036 func (s *DockerSuite) TestRunSeccompUnconfinedCloneUserns(c *check.C) { 1037 testRequires(c, SameHostDaemon, seccompEnabled, UserNamespaceInKernel, NotUserNamespace, unprivilegedUsernsClone) 1038 ensureSyscallTest(c) 1039 1040 // make sure running w privileged is ok 1041 icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined", 1042 "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{ 1043 Out: "nobody", 1044 }) 1045 } 1046 1047 // TestRunSeccompAllowPrivCloneUserns checks that 'docker run --privileged syscall-test' 1048 // allows creating a userns. 1049 func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) { 1050 testRequires(c, SameHostDaemon, seccompEnabled, UserNamespaceInKernel, NotUserNamespace) 1051 ensureSyscallTest(c) 1052 1053 // make sure running w privileged is ok 1054 icmd.RunCommand(dockerBinary, "run", "--privileged", "syscall-test", "userns-test", "id").Assert(c, icmd.Expected{ 1055 Out: "nobody", 1056 }) 1057 } 1058 1059 // TestRunSeccompProfileAllow32Bit checks that 32 bit code can run on x86_64 1060 // with the default seccomp profile. 1061 func (s *DockerSuite) TestRunSeccompProfileAllow32Bit(c *check.C) { 1062 testRequires(c, SameHostDaemon, seccompEnabled, IsAmd64) 1063 ensureSyscallTest(c) 1064 1065 icmd.RunCommand(dockerBinary, "run", "syscall-test", "exit32-test").Assert(c, icmd.Success) 1066 } 1067 1068 // TestRunSeccompAllowSetrlimit checks that 'docker run debian:jessie ulimit -v 1048510' succeeds. 1069 func (s *DockerSuite) TestRunSeccompAllowSetrlimit(c *check.C) { 1070 testRequires(c, SameHostDaemon, seccompEnabled) 1071 1072 // ulimit uses setrlimit, so we want to make sure we don't break it 1073 icmd.RunCommand(dockerBinary, "run", "debian:jessie", "bash", "-c", "ulimit -v 1048510").Assert(c, icmd.Success) 1074 } 1075 1076 func (s *DockerSuite) TestRunSeccompDefaultProfileAcct(c *check.C) { 1077 testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace) 1078 ensureSyscallTest(c) 1079 1080 out, _, err := dockerCmdWithError("run", "syscall-test", "acct-test") 1081 if err == nil || !strings.Contains(out, "Operation not permitted") { 1082 c.Fatalf("test 0: expected Operation not permitted, got: %s", out) 1083 } 1084 1085 out, _, err = dockerCmdWithError("run", "--cap-add", "sys_admin", "syscall-test", "acct-test") 1086 if err == nil || !strings.Contains(out, "Operation not permitted") { 1087 c.Fatalf("test 1: expected Operation not permitted, got: %s", out) 1088 } 1089 1090 out, _, err = dockerCmdWithError("run", "--cap-add", "sys_pacct", "syscall-test", "acct-test") 1091 if err == nil || !strings.Contains(out, "No such file or directory") { 1092 c.Fatalf("test 2: expected No such file or directory, got: %s", out) 1093 } 1094 1095 out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "syscall-test", "acct-test") 1096 if err == nil || !strings.Contains(out, "No such file or directory") { 1097 c.Fatalf("test 3: expected No such file or directory, got: %s", out) 1098 } 1099 1100 out, _, err = dockerCmdWithError("run", "--cap-drop", "ALL", "--cap-add", "sys_pacct", "syscall-test", "acct-test") 1101 if err == nil || !strings.Contains(out, "No such file or directory") { 1102 c.Fatalf("test 4: expected No such file or directory, got: %s", out) 1103 } 1104 } 1105 1106 func (s *DockerSuite) TestRunSeccompDefaultProfileNS(c *check.C) { 1107 testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace) 1108 ensureSyscallTest(c) 1109 1110 out, _, err := dockerCmdWithError("run", "syscall-test", "ns-test", "echo", "hello0") 1111 if err == nil || !strings.Contains(out, "Operation not permitted") { 1112 c.Fatalf("test 0: expected Operation not permitted, got: %s", out) 1113 } 1114 1115 out, _, err = dockerCmdWithError("run", "--cap-add", "sys_admin", "syscall-test", "ns-test", "echo", "hello1") 1116 if err != nil || !strings.Contains(out, "hello1") { 1117 c.Fatalf("test 1: expected hello1, got: %s, %v", out, err) 1118 } 1119 1120 out, _, err = dockerCmdWithError("run", "--cap-drop", "all", "--cap-add", "sys_admin", "syscall-test", "ns-test", "echo", "hello2") 1121 if err != nil || !strings.Contains(out, "hello2") { 1122 c.Fatalf("test 2: expected hello2, got: %s, %v", out, err) 1123 } 1124 1125 out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "syscall-test", "ns-test", "echo", "hello3") 1126 if err != nil || !strings.Contains(out, "hello3") { 1127 c.Fatalf("test 3: expected hello3, got: %s, %v", out, err) 1128 } 1129 1130 out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "--security-opt", "seccomp=unconfined", "syscall-test", "acct-test") 1131 if err == nil || !strings.Contains(out, "No such file or directory") { 1132 c.Fatalf("test 4: expected No such file or directory, got: %s", out) 1133 } 1134 1135 out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "--security-opt", "seccomp=unconfined", "syscall-test", "ns-test", "echo", "hello4") 1136 if err != nil || !strings.Contains(out, "hello4") { 1137 c.Fatalf("test 5: expected hello4, got: %s, %v", out, err) 1138 } 1139 } 1140 1141 // TestRunNoNewPrivSetuid checks that --security-opt='no-new-privileges=true' prevents 1142 // effective uid transtions on executing setuid binaries. 1143 func (s *DockerSuite) TestRunNoNewPrivSetuid(c *check.C) { 1144 testRequires(c, DaemonIsLinux, NotUserNamespace, SameHostDaemon) 1145 ensureNNPTest(c) 1146 1147 // test that running a setuid binary results in no effective uid transition 1148 icmd.RunCommand(dockerBinary, "run", "--security-opt", "no-new-privileges=true", "--user", "1000", 1149 "nnp-test", "/usr/bin/nnp-test").Assert(c, icmd.Expected{ 1150 Out: "EUID=1000", 1151 }) 1152 } 1153 1154 // TestLegacyRunNoNewPrivSetuid checks that --security-opt=no-new-privileges prevents 1155 // effective uid transtions on executing setuid binaries. 1156 func (s *DockerSuite) TestLegacyRunNoNewPrivSetuid(c *check.C) { 1157 testRequires(c, DaemonIsLinux, NotUserNamespace, SameHostDaemon) 1158 ensureNNPTest(c) 1159 1160 // test that running a setuid binary results in no effective uid transition 1161 icmd.RunCommand(dockerBinary, "run", "--security-opt", "no-new-privileges", "--user", "1000", 1162 "nnp-test", "/usr/bin/nnp-test").Assert(c, icmd.Expected{ 1163 Out: "EUID=1000", 1164 }) 1165 } 1166 1167 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChown(c *check.C) { 1168 testRequires(c, DaemonIsLinux) 1169 ensureSyscallTest(c) 1170 1171 // test that a root user has default capability CAP_CHOWN 1172 dockerCmd(c, "run", "busybox", "chown", "100", "/tmp") 1173 // test that non root user does not have default capability CAP_CHOWN 1174 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "chown", "100", "/tmp").Assert(c, icmd.Expected{ 1175 ExitCode: 1, 1176 Err: "Operation not permitted", 1177 }) 1178 // test that root user can drop default capability CAP_CHOWN 1179 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "chown", "busybox", "chown", "100", "/tmp").Assert(c, icmd.Expected{ 1180 ExitCode: 1, 1181 Err: "Operation not permitted", 1182 }) 1183 } 1184 1185 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesDacOverride(c *check.C) { 1186 testRequires(c, DaemonIsLinux) 1187 ensureSyscallTest(c) 1188 1189 // test that a root user has default capability CAP_DAC_OVERRIDE 1190 dockerCmd(c, "run", "busybox", "sh", "-c", "echo test > /etc/passwd") 1191 // test that non root user does not have default capability CAP_DAC_OVERRIDE 1192 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "sh", "-c", "echo test > /etc/passwd").Assert(c, icmd.Expected{ 1193 ExitCode: 1, 1194 Err: "Permission denied", 1195 }) 1196 } 1197 1198 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesFowner(c *check.C) { 1199 testRequires(c, DaemonIsLinux) 1200 ensureSyscallTest(c) 1201 1202 // test that a root user has default capability CAP_FOWNER 1203 dockerCmd(c, "run", "busybox", "chmod", "777", "/etc/passwd") 1204 // test that non root user does not have default capability CAP_FOWNER 1205 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "chmod", "777", "/etc/passwd").Assert(c, icmd.Expected{ 1206 ExitCode: 1, 1207 Err: "Operation not permitted", 1208 }) 1209 // TODO test that root user can drop default capability CAP_FOWNER 1210 } 1211 1212 // TODO CAP_KILL 1213 1214 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetuid(c *check.C) { 1215 testRequires(c, DaemonIsLinux) 1216 ensureSyscallTest(c) 1217 1218 // test that a root user has default capability CAP_SETUID 1219 dockerCmd(c, "run", "syscall-test", "setuid-test") 1220 // test that non root user does not have default capability CAP_SETUID 1221 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setuid-test").Assert(c, icmd.Expected{ 1222 ExitCode: 1, 1223 Err: "Operation not permitted", 1224 }) 1225 // test that root user can drop default capability CAP_SETUID 1226 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "setuid", "syscall-test", "setuid-test").Assert(c, icmd.Expected{ 1227 ExitCode: 1, 1228 Err: "Operation not permitted", 1229 }) 1230 } 1231 1232 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetgid(c *check.C) { 1233 testRequires(c, DaemonIsLinux) 1234 ensureSyscallTest(c) 1235 1236 // test that a root user has default capability CAP_SETGID 1237 dockerCmd(c, "run", "syscall-test", "setgid-test") 1238 // test that non root user does not have default capability CAP_SETGID 1239 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setgid-test").Assert(c, icmd.Expected{ 1240 ExitCode: 1, 1241 Err: "Operation not permitted", 1242 }) 1243 // test that root user can drop default capability CAP_SETGID 1244 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "setgid", "syscall-test", "setgid-test").Assert(c, icmd.Expected{ 1245 ExitCode: 1, 1246 Err: "Operation not permitted", 1247 }) 1248 } 1249 1250 // TODO CAP_SETPCAP 1251 1252 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetBindService(c *check.C) { 1253 testRequires(c, DaemonIsLinux) 1254 ensureSyscallTest(c) 1255 1256 // test that a root user has default capability CAP_NET_BIND_SERVICE 1257 dockerCmd(c, "run", "syscall-test", "socket-test") 1258 // test that non root user does not have default capability CAP_NET_BIND_SERVICE 1259 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "socket-test").Assert(c, icmd.Expected{ 1260 ExitCode: 1, 1261 Err: "Permission denied", 1262 }) 1263 // test that root user can drop default capability CAP_NET_BIND_SERVICE 1264 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "net_bind_service", "syscall-test", "socket-test").Assert(c, icmd.Expected{ 1265 ExitCode: 1, 1266 Err: "Permission denied", 1267 }) 1268 } 1269 1270 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetRaw(c *check.C) { 1271 testRequires(c, DaemonIsLinux) 1272 ensureSyscallTest(c) 1273 1274 // test that a root user has default capability CAP_NET_RAW 1275 dockerCmd(c, "run", "syscall-test", "raw-test") 1276 // test that non root user does not have default capability CAP_NET_RAW 1277 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "raw-test").Assert(c, icmd.Expected{ 1278 ExitCode: 1, 1279 Err: "Operation not permitted", 1280 }) 1281 // test that root user can drop default capability CAP_NET_RAW 1282 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "net_raw", "syscall-test", "raw-test").Assert(c, icmd.Expected{ 1283 ExitCode: 1, 1284 Err: "Operation not permitted", 1285 }) 1286 } 1287 1288 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChroot(c *check.C) { 1289 testRequires(c, DaemonIsLinux) 1290 ensureSyscallTest(c) 1291 1292 // test that a root user has default capability CAP_SYS_CHROOT 1293 dockerCmd(c, "run", "busybox", "chroot", "/", "/bin/true") 1294 // test that non root user does not have default capability CAP_SYS_CHROOT 1295 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "chroot", "/", "/bin/true").Assert(c, icmd.Expected{ 1296 ExitCode: 1, 1297 Err: "Operation not permitted", 1298 }) 1299 // test that root user can drop default capability CAP_SYS_CHROOT 1300 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "sys_chroot", "busybox", "chroot", "/", "/bin/true").Assert(c, icmd.Expected{ 1301 ExitCode: 1, 1302 Err: "Operation not permitted", 1303 }) 1304 } 1305 1306 func (s *DockerSuite) TestUserNoEffectiveCapabilitiesMknod(c *check.C) { 1307 testRequires(c, DaemonIsLinux, NotUserNamespace) 1308 ensureSyscallTest(c) 1309 1310 // test that a root user has default capability CAP_MKNOD 1311 dockerCmd(c, "run", "busybox", "mknod", "/tmp/node", "b", "1", "2") 1312 // test that non root user does not have default capability CAP_MKNOD 1313 // test that root user can drop default capability CAP_SYS_CHROOT 1314 icmd.RunCommand(dockerBinary, "run", "--user", "1000:1000", "busybox", "mknod", "/tmp/node", "b", "1", "2").Assert(c, icmd.Expected{ 1315 ExitCode: 1, 1316 Err: "Operation not permitted", 1317 }) 1318 // test that root user can drop default capability CAP_MKNOD 1319 icmd.RunCommand(dockerBinary, "run", "--cap-drop", "mknod", "busybox", "mknod", "/tmp/node", "b", "1", "2").Assert(c, icmd.Expected{ 1320 ExitCode: 1, 1321 Err: "Operation not permitted", 1322 }) 1323 } 1324 1325 // TODO CAP_AUDIT_WRITE 1326 // TODO CAP_SETFCAP 1327 1328 func (s *DockerSuite) TestRunApparmorProcDirectory(c *check.C) { 1329 testRequires(c, SameHostDaemon, Apparmor) 1330 1331 // running w seccomp unconfined tests the apparmor profile 1332 result := icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "busybox", "chmod", "777", "/proc/1/cgroup") 1333 result.Assert(c, icmd.Expected{ExitCode: 1}) 1334 if !(strings.Contains(result.Combined(), "Permission denied") || strings.Contains(result.Combined(), "Operation not permitted")) { 1335 c.Fatalf("expected chmod 777 /proc/1/cgroup to fail, got %s: %v", result.Combined(), result.Error) 1336 } 1337 1338 result = icmd.RunCommand(dockerBinary, "run", "--security-opt", "seccomp=unconfined", "busybox", "chmod", "777", "/proc/1/attr/current") 1339 result.Assert(c, icmd.Expected{ExitCode: 1}) 1340 if !(strings.Contains(result.Combined(), "Permission denied") || strings.Contains(result.Combined(), "Operation not permitted")) { 1341 c.Fatalf("expected chmod 777 /proc/1/attr/current to fail, got %s: %v", result.Combined(), result.Error) 1342 } 1343 } 1344 1345 // make sure the default profile can be successfully parsed (using unshare as it is 1346 // something which we know is blocked in the default profile) 1347 func (s *DockerSuite) TestRunSeccompWithDefaultProfile(c *check.C) { 1348 testRequires(c, SameHostDaemon, seccompEnabled) 1349 1350 out, _, err := dockerCmdWithError("run", "--security-opt", "seccomp=../profiles/seccomp/default.json", "debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami") 1351 c.Assert(err, checker.NotNil, check.Commentf(out)) 1352 c.Assert(strings.TrimSpace(out), checker.Equals, "unshare: unshare failed: Operation not permitted") 1353 } 1354 1355 // TestRunDeviceSymlink checks run with device that follows symlink (#13840 and #22271) 1356 func (s *DockerSuite) TestRunDeviceSymlink(c *check.C) { 1357 testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm, SameHostDaemon) 1358 if _, err := os.Stat("/dev/zero"); err != nil { 1359 c.Skip("Host does not have /dev/zero") 1360 } 1361 1362 // Create a temporary directory to create symlink 1363 tmpDir, err := ioutil.TempDir("", "docker_device_follow_symlink_tests") 1364 c.Assert(err, checker.IsNil) 1365 1366 defer os.RemoveAll(tmpDir) 1367 1368 // Create a symbolic link to /dev/zero 1369 symZero := filepath.Join(tmpDir, "zero") 1370 err = os.Symlink("/dev/zero", symZero) 1371 c.Assert(err, checker.IsNil) 1372 1373 // Create a temporary file "temp" inside tmpDir, write some data to "tmpDir/temp", 1374 // then create a symlink "tmpDir/file" to the temporary file "tmpDir/temp". 1375 tmpFile := filepath.Join(tmpDir, "temp") 1376 err = ioutil.WriteFile(tmpFile, []byte("temp"), 0666) 1377 c.Assert(err, checker.IsNil) 1378 symFile := filepath.Join(tmpDir, "file") 1379 err = os.Symlink(tmpFile, symFile) 1380 c.Assert(err, checker.IsNil) 1381 1382 // Create a symbolic link to /dev/zero, this time with a relative path (#22271) 1383 err = os.Symlink("zero", "/dev/symzero") 1384 if err != nil { 1385 c.Fatal("/dev/symzero creation failed") 1386 } 1387 // We need to remove this symbolic link here as it is created in /dev/, not temporary directory as above 1388 defer os.Remove("/dev/symzero") 1389 1390 // md5sum of 'dd if=/dev/zero bs=4K count=8' is bb7df04e1b0a2570657527a7e108ae23 1391 out, _ := dockerCmd(c, "run", "--device", symZero+":/dev/symzero", "busybox", "sh", "-c", "dd if=/dev/symzero bs=4K count=8 | md5sum") 1392 c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "bb7df04e1b0a2570657527a7e108ae23", check.Commentf("expected output bb7df04e1b0a2570657527a7e108ae23")) 1393 1394 // symlink "tmpDir/file" to a file "tmpDir/temp" will result in an error as it is not a device. 1395 out, _, err = dockerCmdWithError("run", "--device", symFile+":/dev/symzero", "busybox", "sh", "-c", "dd if=/dev/symzero bs=4K count=8 | md5sum") 1396 c.Assert(err, check.NotNil) 1397 c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "not a device node", check.Commentf("expected output 'not a device node'")) 1398 1399 // md5sum of 'dd if=/dev/zero bs=4K count=8' is bb7df04e1b0a2570657527a7e108ae23 (this time check with relative path backed, see #22271) 1400 out, _ = dockerCmd(c, "run", "--device", "/dev/symzero:/dev/symzero", "busybox", "sh", "-c", "dd if=/dev/symzero bs=4K count=8 | md5sum") 1401 c.Assert(strings.Trim(out, "\r\n"), checker.Contains, "bb7df04e1b0a2570657527a7e108ae23", check.Commentf("expected output bb7df04e1b0a2570657527a7e108ae23")) 1402 } 1403 1404 // TestRunPIDsLimit makes sure the pids cgroup is set with --pids-limit 1405 func (s *DockerSuite) TestRunPIDsLimit(c *check.C) { 1406 testRequires(c, SameHostDaemon, pidsLimit) 1407 1408 file := "/sys/fs/cgroup/pids/pids.max" 1409 out, _ := dockerCmd(c, "run", "--name", "skittles", "--pids-limit", "4", "busybox", "cat", file) 1410 c.Assert(strings.TrimSpace(out), checker.Equals, "4") 1411 1412 out = inspectField(c, "skittles", "HostConfig.PidsLimit") 1413 c.Assert(out, checker.Equals, "4", check.Commentf("setting the pids limit failed")) 1414 } 1415 1416 func (s *DockerSuite) TestRunPrivilegedAllowedDevices(c *check.C) { 1417 testRequires(c, DaemonIsLinux, NotUserNamespace) 1418 1419 file := "/sys/fs/cgroup/devices/devices.list" 1420 out, _ := dockerCmd(c, "run", "--privileged", "busybox", "cat", file) 1421 c.Logf("out: %q", out) 1422 c.Assert(strings.TrimSpace(out), checker.Equals, "a *:* rwm") 1423 } 1424 1425 func (s *DockerSuite) TestRunUserDeviceAllowed(c *check.C) { 1426 testRequires(c, DaemonIsLinux) 1427 1428 fi, err := os.Stat("/dev/snd/timer") 1429 if err != nil { 1430 c.Skip("Host does not have /dev/snd/timer") 1431 } 1432 stat, ok := fi.Sys().(*syscall.Stat_t) 1433 if !ok { 1434 c.Skip("Could not stat /dev/snd/timer") 1435 } 1436 1437 file := "/sys/fs/cgroup/devices/devices.list" 1438 out, _ := dockerCmd(c, "run", "--device", "/dev/snd/timer:w", "busybox", "cat", file) 1439 c.Assert(out, checker.Contains, fmt.Sprintf("c %d:%d w", stat.Rdev/256, stat.Rdev%256)) 1440 } 1441 1442 func (s *DockerDaemonSuite) TestRunSeccompJSONNewFormat(c *check.C) { 1443 testRequires(c, SameHostDaemon, seccompEnabled) 1444 1445 s.d.StartWithBusybox(c) 1446 1447 jsonData := `{ 1448 "defaultAction": "SCMP_ACT_ALLOW", 1449 "syscalls": [ 1450 { 1451 "names": ["chmod", "fchmod", "fchmodat"], 1452 "action": "SCMP_ACT_ERRNO" 1453 } 1454 ] 1455 }` 1456 tmpFile, err := ioutil.TempFile("", "profile.json") 1457 c.Assert(err, check.IsNil) 1458 defer tmpFile.Close() 1459 _, err = tmpFile.Write([]byte(jsonData)) 1460 c.Assert(err, check.IsNil) 1461 1462 out, err := s.d.Cmd("run", "--security-opt", "seccomp="+tmpFile.Name(), "busybox", "chmod", "777", ".") 1463 c.Assert(err, check.NotNil) 1464 c.Assert(out, checker.Contains, "Operation not permitted") 1465 } 1466 1467 func (s *DockerDaemonSuite) TestRunSeccompJSONNoNameAndNames(c *check.C) { 1468 testRequires(c, SameHostDaemon, seccompEnabled) 1469 1470 s.d.StartWithBusybox(c) 1471 1472 jsonData := `{ 1473 "defaultAction": "SCMP_ACT_ALLOW", 1474 "syscalls": [ 1475 { 1476 "name": "chmod", 1477 "names": ["fchmod", "fchmodat"], 1478 "action": "SCMP_ACT_ERRNO" 1479 } 1480 ] 1481 }` 1482 tmpFile, err := ioutil.TempFile("", "profile.json") 1483 c.Assert(err, check.IsNil) 1484 defer tmpFile.Close() 1485 _, err = tmpFile.Write([]byte(jsonData)) 1486 c.Assert(err, check.IsNil) 1487 1488 out, err := s.d.Cmd("run", "--security-opt", "seccomp="+tmpFile.Name(), "busybox", "chmod", "777", ".") 1489 c.Assert(err, check.NotNil) 1490 c.Assert(out, checker.Contains, "'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'") 1491 } 1492 1493 func (s *DockerDaemonSuite) TestRunSeccompJSONNoArchAndArchMap(c *check.C) { 1494 testRequires(c, SameHostDaemon, seccompEnabled) 1495 1496 s.d.StartWithBusybox(c) 1497 1498 jsonData := `{ 1499 "archMap": [ 1500 { 1501 "architecture": "SCMP_ARCH_X86_64", 1502 "subArchitectures": [ 1503 "SCMP_ARCH_X86", 1504 "SCMP_ARCH_X32" 1505 ] 1506 } 1507 ], 1508 "architectures": [ 1509 "SCMP_ARCH_X32" 1510 ], 1511 "defaultAction": "SCMP_ACT_ALLOW", 1512 "syscalls": [ 1513 { 1514 "names": ["chmod", "fchmod", "fchmodat"], 1515 "action": "SCMP_ACT_ERRNO" 1516 } 1517 ] 1518 }` 1519 tmpFile, err := ioutil.TempFile("", "profile.json") 1520 c.Assert(err, check.IsNil) 1521 defer tmpFile.Close() 1522 _, err = tmpFile.Write([]byte(jsonData)) 1523 c.Assert(err, check.IsNil) 1524 1525 out, err := s.d.Cmd("run", "--security-opt", "seccomp="+tmpFile.Name(), "busybox", "chmod", "777", ".") 1526 c.Assert(err, check.NotNil) 1527 c.Assert(out, checker.Contains, "'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'") 1528 } 1529 1530 func (s *DockerDaemonSuite) TestRunWithDaemonDefaultSeccompProfile(c *check.C) { 1531 testRequires(c, SameHostDaemon, seccompEnabled) 1532 1533 s.d.StartWithBusybox(c) 1534 1535 // 1) verify I can run containers with the Docker default shipped profile which allows chmod 1536 _, err := s.d.Cmd("run", "busybox", "chmod", "777", ".") 1537 c.Assert(err, check.IsNil) 1538 1539 jsonData := `{ 1540 "defaultAction": "SCMP_ACT_ALLOW", 1541 "syscalls": [ 1542 { 1543 "name": "chmod", 1544 "action": "SCMP_ACT_ERRNO" 1545 } 1546 ] 1547 }` 1548 tmpFile, err := ioutil.TempFile("", "profile.json") 1549 c.Assert(err, check.IsNil) 1550 defer tmpFile.Close() 1551 _, err = tmpFile.Write([]byte(jsonData)) 1552 c.Assert(err, check.IsNil) 1553 1554 // 2) restart the daemon and add a custom seccomp profile in which we deny chmod 1555 s.d.Restart(c, "--seccomp-profile="+tmpFile.Name()) 1556 1557 out, err := s.d.Cmd("run", "busybox", "chmod", "777", ".") 1558 c.Assert(err, check.NotNil) 1559 c.Assert(out, checker.Contains, "Operation not permitted") 1560 } 1561 1562 func (s *DockerSuite) TestRunWithNanoCPUs(c *check.C) { 1563 testRequires(c, cpuCfsQuota, cpuCfsPeriod) 1564 1565 file1 := "/sys/fs/cgroup/cpu/cpu.cfs_quota_us" 1566 file2 := "/sys/fs/cgroup/cpu/cpu.cfs_period_us" 1567 out, _ := dockerCmd(c, "run", "--cpus", "0.5", "--name", "test", "busybox", "sh", "-c", fmt.Sprintf("cat %s && cat %s", file1, file2)) 1568 c.Assert(strings.TrimSpace(out), checker.Equals, "50000\n100000") 1569 1570 clt, err := client.NewEnvClient() 1571 c.Assert(err, checker.IsNil) 1572 inspect, err := clt.ContainerInspect(context.Background(), "test") 1573 c.Assert(err, checker.IsNil) 1574 c.Assert(inspect.HostConfig.NanoCPUs, checker.Equals, int64(500000000)) 1575 1576 out = inspectField(c, "test", "HostConfig.CpuQuota") 1577 c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS quota should be 0")) 1578 out = inspectField(c, "test", "HostConfig.CpuPeriod") 1579 c.Assert(out, checker.Equals, "0", check.Commentf("CPU CFS period should be 0")) 1580 1581 out, _, err = dockerCmdWithError("run", "--cpus", "0.5", "--cpu-quota", "50000", "--cpu-period", "100000", "busybox", "sh") 1582 c.Assert(err, check.NotNil) 1583 c.Assert(out, checker.Contains, "Conflicting options: Nano CPUs and CPU Period cannot both be set") 1584 }