Signed-off-by: Jessica Frazelle <acidburn@docker.com>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,15 @@ |
| 0 |
+FROM debian:jessie |
|
| 1 |
+ |
|
| 2 |
+RUN apt-get update && apt-get install -y \ |
|
| 3 |
+ gcc \ |
|
| 4 |
+ libc6-dev \ |
|
| 5 |
+ --no-install-recommends \ |
|
| 6 |
+ && rm -rf /var/lib/apt/lists/* |
|
| 7 |
+ |
|
| 8 |
+COPY . /usr/src/ |
|
| 9 |
+ |
|
| 10 |
+WORKDIR /usr/src/ |
|
| 11 |
+ |
|
| 12 |
+RUN gcc -g -Wall -static userns.c -o /usr/bin/userns-test \ |
|
| 13 |
+ && gcc -g -Wall -static ns.c -o /usr/bin/ns-test \ |
|
| 14 |
+ && gcc -g -Wall -static acct.c -o /usr/bin/acct-test |
| 0 | 15 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 0 |
+#define _GNU_SOURCE |
|
| 1 |
+#include <unistd.h> |
|
| 2 |
+#include <stdlib.h> |
|
| 3 |
+#include <stdio.h> |
|
| 4 |
+#include <string.h> |
|
| 5 |
+#include <errno.h> |
|
| 6 |
+ |
|
| 7 |
+int main(int argc, char **argv) |
|
| 8 |
+{
|
|
| 9 |
+ int err = acct("/tmp/t");
|
|
| 10 |
+ if (err == -1) {
|
|
| 11 |
+ fprintf(stderr, "acct failed: %s\n", strerror(errno)); |
|
| 12 |
+ exit(EXIT_FAILURE); |
|
| 13 |
+ } |
|
| 14 |
+ exit(EXIT_SUCCESS); |
|
| 15 |
+} |
| 0 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,63 @@ |
| 0 |
+#define _GNU_SOURCE |
|
| 1 |
+#include <errno.h> |
|
| 2 |
+#include <sched.h> |
|
| 3 |
+#include <signal.h> |
|
| 4 |
+#include <stdio.h> |
|
| 5 |
+#include <stdlib.h> |
|
| 6 |
+#include <string.h> |
|
| 7 |
+#include <sys/mman.h> |
|
| 8 |
+#include <sys/wait.h> |
|
| 9 |
+#include <unistd.h> |
|
| 10 |
+ |
|
| 11 |
+#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */ |
|
| 12 |
+ |
|
| 13 |
+struct clone_args {
|
|
| 14 |
+ char **argv; |
|
| 15 |
+}; |
|
| 16 |
+ |
|
| 17 |
+// child_exec is the func that will be executed as the result of clone |
|
| 18 |
+static int child_exec(void *stuff) |
|
| 19 |
+{
|
|
| 20 |
+ struct clone_args *args = (struct clone_args *)stuff; |
|
| 21 |
+ if (execvp(args->argv[0], args->argv) != 0) {
|
|
| 22 |
+ fprintf(stderr, "failed to execvp argments %s\n", |
|
| 23 |
+ strerror(errno)); |
|
| 24 |
+ exit(-1); |
|
| 25 |
+ } |
|
| 26 |
+ // we should never reach here! |
|
| 27 |
+ exit(EXIT_FAILURE); |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+int main(int argc, char **argv) |
|
| 31 |
+{
|
|
| 32 |
+ struct clone_args args; |
|
| 33 |
+ args.argv = &argv[1]; |
|
| 34 |
+ |
|
| 35 |
+ int clone_flags = CLONE_NEWNS | CLONE_NEWPID | SIGCHLD; |
|
| 36 |
+ |
|
| 37 |
+ // allocate stack for child |
|
| 38 |
+ char *stack; /* Start of stack buffer */ |
|
| 39 |
+ char *child_stack; /* End of stack buffer */ |
|
| 40 |
+ stack = |
|
| 41 |
+ mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, |
|
| 42 |
+ MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0); |
|
| 43 |
+ if (stack == MAP_FAILED) {
|
|
| 44 |
+ fprintf(stderr, "mmap failed: %s\n", strerror(errno)); |
|
| 45 |
+ exit(EXIT_FAILURE); |
|
| 46 |
+ } |
|
| 47 |
+ child_stack = stack + STACK_SIZE; /* Assume stack grows downward */ |
|
| 48 |
+ |
|
| 49 |
+ // the result of this call is that our child_exec will be run in another |
|
| 50 |
+ // process returning it's pid |
|
| 51 |
+ pid_t pid = clone(child_exec, child_stack, clone_flags, &args); |
|
| 52 |
+ if (pid < 0) {
|
|
| 53 |
+ fprintf(stderr, "clone failed: %s\n", strerror(errno)); |
|
| 54 |
+ exit(EXIT_FAILURE); |
|
| 55 |
+ } |
|
| 56 |
+ // lets wait on our child process here before we, the parent, exits |
|
| 57 |
+ if (waitpid(pid, NULL, 0) == -1) {
|
|
| 58 |
+ fprintf(stderr, "failed to wait pid %d\n", pid); |
|
| 59 |
+ exit(EXIT_FAILURE); |
|
| 60 |
+ } |
|
| 61 |
+ exit(EXIT_SUCCESS); |
|
| 62 |
+} |
| 0 | 63 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,63 @@ |
| 0 |
+#define _GNU_SOURCE |
|
| 1 |
+#include <errno.h> |
|
| 2 |
+#include <sched.h> |
|
| 3 |
+#include <signal.h> |
|
| 4 |
+#include <stdio.h> |
|
| 5 |
+#include <stdlib.h> |
|
| 6 |
+#include <string.h> |
|
| 7 |
+#include <sys/mman.h> |
|
| 8 |
+#include <sys/wait.h> |
|
| 9 |
+#include <unistd.h> |
|
| 10 |
+ |
|
| 11 |
+#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */ |
|
| 12 |
+ |
|
| 13 |
+struct clone_args {
|
|
| 14 |
+ char **argv; |
|
| 15 |
+}; |
|
| 16 |
+ |
|
| 17 |
+// child_exec is the func that will be executed as the result of clone |
|
| 18 |
+static int child_exec(void *stuff) |
|
| 19 |
+{
|
|
| 20 |
+ struct clone_args *args = (struct clone_args *)stuff; |
|
| 21 |
+ if (execvp(args->argv[0], args->argv) != 0) {
|
|
| 22 |
+ fprintf(stderr, "failed to execvp argments %s\n", |
|
| 23 |
+ strerror(errno)); |
|
| 24 |
+ exit(-1); |
|
| 25 |
+ } |
|
| 26 |
+ // we should never reach here! |
|
| 27 |
+ exit(EXIT_FAILURE); |
|
| 28 |
+} |
|
| 29 |
+ |
|
| 30 |
+int main(int argc, char **argv) |
|
| 31 |
+{
|
|
| 32 |
+ struct clone_args args; |
|
| 33 |
+ args.argv = &argv[1]; |
|
| 34 |
+ |
|
| 35 |
+ int clone_flags = CLONE_NEWUSER | SIGCHLD; |
|
| 36 |
+ |
|
| 37 |
+ // allocate stack for child |
|
| 38 |
+ char *stack; /* Start of stack buffer */ |
|
| 39 |
+ char *child_stack; /* End of stack buffer */ |
|
| 40 |
+ stack = |
|
| 41 |
+ mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, |
|
| 42 |
+ MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0); |
|
| 43 |
+ if (stack == MAP_FAILED) {
|
|
| 44 |
+ fprintf(stderr, "mmap failed: %s\n", strerror(errno)); |
|
| 45 |
+ exit(EXIT_FAILURE); |
|
| 46 |
+ } |
|
| 47 |
+ child_stack = stack + STACK_SIZE; /* Assume stack grows downward */ |
|
| 48 |
+ |
|
| 49 |
+ // the result of this call is that our child_exec will be run in another |
|
| 50 |
+ // process returning it's pid |
|
| 51 |
+ pid_t pid = clone(child_exec, child_stack, clone_flags, &args); |
|
| 52 |
+ if (pid < 0) {
|
|
| 53 |
+ fprintf(stderr, "clone failed: %s\n", strerror(errno)); |
|
| 54 |
+ exit(EXIT_FAILURE); |
|
| 55 |
+ } |
|
| 56 |
+ // lets wait on our child process here before we, the parent, exits |
|
| 57 |
+ if (waitpid(pid, NULL, 0) == -1) {
|
|
| 58 |
+ fprintf(stderr, "failed to wait pid %d\n", pid); |
|
| 59 |
+ exit(EXIT_FAILURE); |
|
| 60 |
+ } |
|
| 61 |
+ exit(EXIT_SUCCESS); |
|
| 62 |
+} |
| 4 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,54 +0,0 @@ |
| 1 |
-#define _GNU_SOURCE |
|
| 2 |
-#include <sched.h> |
|
| 3 |
-#include <unistd.h> |
|
| 4 |
-#include <stdlib.h> |
|
| 5 |
-#include <sys/wait.h> |
|
| 6 |
-#include <signal.h> |
|
| 7 |
-#include <fcntl.h> |
|
| 8 |
-#include <stdio.h> |
|
| 9 |
-#include <string.h> |
|
| 10 |
-#include <limits.h> |
|
| 11 |
-#include <errno.h> |
|
| 12 |
- |
|
| 13 |
-#define STACKSIZE (1024*1024) |
|
| 14 |
-static char child_stack[STACKSIZE]; |
|
| 15 |
- |
|
| 16 |
-struct clone_args {
|
|
| 17 |
- char **argv; |
|
| 18 |
-}; |
|
| 19 |
- |
|
| 20 |
-// child_exec is the func that will be executed as the result of clone |
|
| 21 |
-static int child_exec(void *stuff) |
|
| 22 |
-{
|
|
| 23 |
- struct clone_args *args = (struct clone_args *)stuff; |
|
| 24 |
- if (execvp(args->argv[0], args->argv) != 0) {
|
|
| 25 |
- fprintf(stderr, "failed to execvp argments %s\n", |
|
| 26 |
- strerror(errno)); |
|
| 27 |
- exit(-1); |
|
| 28 |
- } |
|
| 29 |
- // we should never reach here! |
|
| 30 |
- exit(EXIT_FAILURE); |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-int main(int argc, char **argv) |
|
| 34 |
-{
|
|
| 35 |
- struct clone_args args; |
|
| 36 |
- args.argv = &argv[1]; |
|
| 37 |
- |
|
| 38 |
- int clone_flags = CLONE_NEWUSER | SIGCHLD; |
|
| 39 |
- |
|
| 40 |
- // the result of this call is that our child_exec will be run in another |
|
| 41 |
- // process returning it's pid |
|
| 42 |
- pid_t pid = |
|
| 43 |
- clone(child_exec, child_stack + STACKSIZE, clone_flags, &args); |
|
| 44 |
- if (pid < 0) {
|
|
| 45 |
- fprintf(stderr, "clone failed: %s\n", strerror(errno)); |
|
| 46 |
- exit(EXIT_FAILURE); |
|
| 47 |
- } |
|
| 48 |
- // lets wait on our child process here before we, the parent, exits |
|
| 49 |
- if (waitpid(pid, NULL, 0) == -1) {
|
|
| 50 |
- fprintf(stderr, "failed to wait pid %d\n", pid); |
|
| 51 |
- exit(EXIT_FAILURE); |
|
| 52 |
- } |
|
| 53 |
- exit(EXIT_SUCCESS); |
|
| 54 |
-} |
| 0 | 8 |
deleted file mode 100644 |
| ... | ... |
@@ -1,17 +0,0 @@ |
| 1 |
-#!/bin/bash |
|
| 2 |
-set -e |
|
| 3 |
- |
|
| 4 |
-# Build a C binary for cloning a userns for seccomp tests |
|
| 5 |
-# and compile it for target daemon |
|
| 6 |
- |
|
| 7 |
-dir="$DEST/userns-test" |
|
| 8 |
-mkdir -p "$dir" |
|
| 9 |
-( |
|
| 10 |
- if [ "$(go env GOOS)" = "linux" ]; then |
|
| 11 |
- cd "$dir" |
|
| 12 |
- gcc -g -Wall -static ../../../../contrib/userns-test/main.c -o ./userns-test |
|
| 13 |
- cp ../../../../contrib/userns-test/Dockerfile . |
|
| 14 |
- docker build -qt userns-test . > /dev/null |
|
| 15 |
- fi |
|
| 16 |
-) |
|
| 17 |
-rm -rf "$dir" |
| ... | ... |
@@ -586,12 +586,12 @@ func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
|
| 586 | 586 |
} |
| 587 | 587 |
} |
| 588 | 588 |
|
| 589 |
-// TestRunSeccompProfileDenyCloneUserns checks that 'docker run userns-test' |
|
| 589 |
+// TestRunSeccompProfileDenyCloneUserns checks that 'docker run syscall-test' |
|
| 590 | 590 |
// with a the default seccomp profile exits with operation not permitted. |
| 591 | 591 |
func (s *DockerSuite) TestRunSeccompProfileDenyCloneUserns(c *check.C) {
|
| 592 | 592 |
testRequires(c, SameHostDaemon, seccompEnabled) |
| 593 | 593 |
|
| 594 |
- runCmd := exec.Command(dockerBinary, "run", "userns-test", "id") |
|
| 594 |
+ runCmd := exec.Command(dockerBinary, "run", "syscall-test", "userns-test", "id") |
|
| 595 | 595 |
out, _, err := runCommandWithOutput(runCmd) |
| 596 | 596 |
if err == nil || !strings.Contains(out, "clone failed: Operation not permitted") {
|
| 597 | 597 |
c.Fatalf("expected clone userns with default seccomp profile denied to fail, got %s: %v", out, err)
|
| ... | ... |
@@ -599,24 +599,24 @@ func (s *DockerSuite) TestRunSeccompProfileDenyCloneUserns(c *check.C) {
|
| 599 | 599 |
} |
| 600 | 600 |
|
| 601 | 601 |
// TestRunSeccompUnconfinedCloneUserns checks that |
| 602 |
-// 'docker run --security-opt seccomp:unconfined userns-test' allows creating a userns. |
|
| 602 |
+// 'docker run --security-opt seccomp:unconfined syscall-test' allows creating a userns. |
|
| 603 | 603 |
func (s *DockerSuite) TestRunSeccompUnconfinedCloneUserns(c *check.C) {
|
| 604 | 604 |
testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace) |
| 605 | 605 |
|
| 606 | 606 |
// make sure running w privileged is ok |
| 607 |
- runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp:unconfined", "userns-test", "id") |
|
| 607 |
+ runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp:unconfined", "syscall-test", "userns-test", "id") |
|
| 608 | 608 |
if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
|
| 609 | 609 |
c.Fatalf("expected clone userns with --security-opt seccomp:unconfined to succeed, got %s: %v", out, err)
|
| 610 | 610 |
} |
| 611 | 611 |
} |
| 612 | 612 |
|
| 613 |
-// TestRunSeccompAllowPrivCloneUserns checks that 'docker run --privileged userns-test' |
|
| 613 |
+// TestRunSeccompAllowPrivCloneUserns checks that 'docker run --privileged syscall-test' |
|
| 614 | 614 |
// allows creating a userns. |
| 615 | 615 |
func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) {
|
| 616 | 616 |
testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace) |
| 617 | 617 |
|
| 618 | 618 |
// make sure running w privileged is ok |
| 619 |
- runCmd := exec.Command(dockerBinary, "run", "--privileged", "userns-test", "id") |
|
| 619 |
+ runCmd := exec.Command(dockerBinary, "run", "--privileged", "syscall-test", "userns-test", "id") |
|
| 620 | 620 |
if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
|
| 621 | 621 |
c.Fatalf("expected clone userns with --privileged to succeed, got %s: %v", out, err)
|
| 622 | 622 |
} |
| ... | ... |
@@ -624,7 +624,7 @@ func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) {
|
| 624 | 624 |
|
| 625 | 625 |
// TestRunSeccompAllowAptKey checks that 'docker run debian:jessie apt-key' succeeds. |
| 626 | 626 |
func (s *DockerSuite) TestRunSeccompAllowAptKey(c *check.C) {
|
| 627 |
- testRequires(c, SameHostDaemon, seccompEnabled) |
|
| 627 |
+ testRequires(c, SameHostDaemon, seccompEnabled, Network) |
|
| 628 | 628 |
|
| 629 | 629 |
// apt-key uses setrlimit & getrlimit, so we want to make sure we don't break it |
| 630 | 630 |
runCmd := exec.Command(dockerBinary, "run", "debian:jessie", "apt-key", "adv", "--keyserver", "hkp://p80.pool.sks-keyservers.net:80", "--recv-keys", "E871F18B51E0147C77796AC81196BA81F6B0FC61") |
| ... | ... |
@@ -632,3 +632,27 @@ func (s *DockerSuite) TestRunSeccompAllowAptKey(c *check.C) {
|
| 632 | 632 |
c.Fatalf("expected apt-key with seccomp to succeed, got %s: %v", out, err)
|
| 633 | 633 |
} |
| 634 | 634 |
} |
| 635 |
+ |
|
| 636 |
+func (s *DockerSuite) TestRunSeccompDefaultProfile(c *check.C) {
|
|
| 637 |
+ testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace) |
|
| 638 |
+ |
|
| 639 |
+ out, _, err := dockerCmdWithError("run", "--cap-add", "ALL", "syscall-test", "acct-test")
|
|
| 640 |
+ if err == nil || !strings.Contains(out, "Operation not permitted") {
|
|
| 641 |
+ c.Fatalf("expected Operation not permitted, got: %s", out)
|
|
| 642 |
+ } |
|
| 643 |
+ |
|
| 644 |
+ out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "syscall-test", "ns-test", "echo", "hello")
|
|
| 645 |
+ if err == nil || !strings.Contains(out, "Operation not permitted") {
|
|
| 646 |
+ c.Fatalf("expected Operation not permitted, got: %s", out)
|
|
| 647 |
+ } |
|
| 648 |
+ |
|
| 649 |
+ out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "--security-opt", "seccomp:unconfined", "syscall-test", "acct-test")
|
|
| 650 |
+ if err == nil || !strings.Contains(out, "No such file or directory") {
|
|
| 651 |
+ c.Fatalf("expected No such file or directory, got: %s", out)
|
|
| 652 |
+ } |
|
| 653 |
+ |
|
| 654 |
+ out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "--security-opt", "seccomp:unconfined", "syscall-test", "ns-test", "echo", "hello")
|
|
| 655 |
+ if err != nil || !strings.Contains(out, "hello") {
|
|
| 656 |
+ c.Fatalf("expected hello, got: %s, %v", out, err)
|
|
| 657 |
+ } |
|
| 658 |
+} |