Browse code

add more seccomp profile tests

Signed-off-by: Jessica Frazelle <acidburn@docker.com>

Jessica Frazelle authored on 2015/12/31 04:20:23
Showing 10 changed files
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
+}
0 63
deleted file mode 100644
... ...
@@ -1,3 +0,0 @@
1
-FROM debian:jessie
2
-COPY userns-test .
3
-ENTRYPOINT ["./userns-test"]
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
-}
55 1
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+#!/bin/bash
1
+set -e
2
+
3
+# Build a C binary for cloning a userns for seccomp tests
4
+# and compile it for target daemon
5
+if [ "$DOCKER_ENGINE_GOOS" = "linux" ]; then
6
+	docker build -qt syscall-test contrib/syscall-test > /dev/null
7
+fi
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"
... ...
@@ -10,4 +10,4 @@ export DOCKER_ENGINE_GOARCH=$(echo $DOCKER_ENGINE_OSARCH | cut -d'/' -f2)
10 10
 bundle .ensure-emptyfs
11 11
 bundle .ensure-frozen-images
12 12
 bundle .ensure-httpserver
13
-bundle .ensure-userns-test
13
+bundle .ensure-syscall-test
... ...
@@ -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
+}