Explorar o código

add more seccomp profile tests

Signed-off-by: Jessica Frazelle <acidburn@docker.com>
Jessica Frazelle %!s(int64=9) %!d(string=hai) anos
pai
achega
327421d1df

+ 15 - 0
contrib/syscall-test/Dockerfile

@@ -0,0 +1,15 @@
+FROM debian:jessie
+
+RUN apt-get update && apt-get install -y \
+	gcc \
+	libc6-dev \
+	--no-install-recommends \
+	&& rm -rf /var/lib/apt/lists/*
+
+COPY . /usr/src/
+
+WORKDIR /usr/src/
+
+RUN gcc -g -Wall -static userns.c -o /usr/bin/userns-test \
+	&& gcc -g -Wall -static ns.c -o /usr/bin/ns-test \
+	&& gcc -g -Wall -static acct.c -o /usr/bin/acct-test

+ 16 - 0
contrib/syscall-test/acct.c

@@ -0,0 +1,16 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+int main(int argc, char **argv)
+{
+	int err = acct("/tmp/t");
+	if (err == -1) {
+		fprintf(stderr, "acct failed: %s\n", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+	exit(EXIT_SUCCESS);
+}

+ 63 - 0
contrib/syscall-test/ns.c

@@ -0,0 +1,63 @@
+#define _GNU_SOURCE
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define STACK_SIZE (1024 * 1024)	/* Stack size for cloned child */
+
+struct clone_args {
+	char **argv;
+};
+
+// child_exec is the func that will be executed as the result of clone
+static int child_exec(void *stuff)
+{
+	struct clone_args *args = (struct clone_args *)stuff;
+	if (execvp(args->argv[0], args->argv) != 0) {
+		fprintf(stderr, "failed to execvp argments %s\n",
+			strerror(errno));
+		exit(-1);
+	}
+	// we should never reach here!
+	exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+	struct clone_args args;
+	args.argv = &argv[1];
+
+	int clone_flags = CLONE_NEWNS | CLONE_NEWPID | SIGCHLD;
+
+	// allocate stack for child
+	char *stack;		/* Start of stack buffer */
+	char *child_stack;	/* End of stack buffer */
+	stack =
+	    mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
+		 MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0);
+	if (stack == MAP_FAILED) {
+		fprintf(stderr, "mmap failed: %s\n", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+	child_stack = stack + STACK_SIZE;	/* Assume stack grows downward */
+
+	// the result of this call is that our child_exec will be run in another
+	// process returning it's pid
+	pid_t pid = clone(child_exec, child_stack, clone_flags, &args);
+	if (pid < 0) {
+		fprintf(stderr, "clone failed: %s\n", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+	// lets wait on our child process here before we, the parent, exits
+	if (waitpid(pid, NULL, 0) == -1) {
+		fprintf(stderr, "failed to wait pid %d\n", pid);
+		exit(EXIT_FAILURE);
+	}
+	exit(EXIT_SUCCESS);
+}

+ 19 - 10
contrib/userns-test/main.c → contrib/syscall-test/userns.c

@@ -1,17 +1,15 @@
 #define _GNU_SOURCE
 #define _GNU_SOURCE
+#include <errno.h>
 #include <sched.h>
 #include <sched.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/wait.h>
 #include <signal.h>
 #include <signal.h>
-#include <fcntl.h>
 #include <stdio.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <string.h>
-#include <limits.h>
-#include <errno.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
 
-#define STACKSIZE (1024*1024)
-static char child_stack[STACKSIZE];
+#define STACK_SIZE (1024 * 1024)	/* Stack size for cloned child */
 
 
 struct clone_args {
 struct clone_args {
 	char **argv;
 	char **argv;
@@ -37,10 +35,21 @@ int main(int argc, char **argv)
 
 
 	int clone_flags = CLONE_NEWUSER | SIGCHLD;
 	int clone_flags = CLONE_NEWUSER | SIGCHLD;
 
 
+	// allocate stack for child
+	char *stack;		/* Start of stack buffer */
+	char *child_stack;	/* End of stack buffer */
+	stack =
+	    mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
+		 MAP_SHARED | MAP_ANON | MAP_STACK, -1, 0);
+	if (stack == MAP_FAILED) {
+		fprintf(stderr, "mmap failed: %s\n", strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+	child_stack = stack + STACK_SIZE;	/* Assume stack grows downward */
+
 	// the result of this call is that our child_exec will be run in another
 	// the result of this call is that our child_exec will be run in another
 	// process returning it's pid
 	// process returning it's pid
-	pid_t pid =
-	    clone(child_exec, child_stack + STACKSIZE, clone_flags, &args);
+	pid_t pid = clone(child_exec, child_stack, clone_flags, &args);
 	if (pid < 0) {
 	if (pid < 0) {
 		fprintf(stderr, "clone failed: %s\n", strerror(errno));
 		fprintf(stderr, "clone failed: %s\n", strerror(errno));
 		exit(EXIT_FAILURE);
 		exit(EXIT_FAILURE);

+ 0 - 3
contrib/userns-test/Dockerfile

@@ -1,3 +0,0 @@
-FROM debian:jessie
-COPY userns-test .
-ENTRYPOINT ["./userns-test"]

+ 8 - 0
hack/make/.ensure-syscall-test

@@ -0,0 +1,8 @@
+#!/bin/bash
+set -e
+
+# Build a C binary for cloning a userns for seccomp tests
+# and compile it for target daemon
+if [ "$DOCKER_ENGINE_GOOS" = "linux" ]; then
+	docker build -qt syscall-test contrib/syscall-test > /dev/null
+fi

+ 0 - 17
hack/make/.ensure-userns-test

@@ -1,17 +0,0 @@
-#!/bin/bash
-set -e
-
-# Build a C binary for cloning a userns for seccomp tests
-# and compile it for target daemon
-
-dir="$DEST/userns-test"
-mkdir -p "$dir"
-(
-	if [ "$(go env GOOS)" = "linux" ]; then
-		cd "$dir"
-		gcc -g -Wall -static ../../../../contrib/userns-test/main.c -o ./userns-test
-		cp ../../../../contrib/userns-test/Dockerfile .
-		docker build -qt userns-test . > /dev/null
-	fi
-)
-rm -rf "$dir"

+ 1 - 1
hack/make/.integration-daemon-setup

@@ -10,4 +10,4 @@ export DOCKER_ENGINE_GOARCH=$(echo $DOCKER_ENGINE_OSARCH | cut -d'/' -f2)
 bundle .ensure-emptyfs
 bundle .ensure-emptyfs
 bundle .ensure-frozen-images
 bundle .ensure-frozen-images
 bundle .ensure-httpserver
 bundle .ensure-httpserver
-bundle .ensure-userns-test
+bundle .ensure-syscall-test

+ 31 - 7
integration-cli/docker_cli_run_unix_test.go

@@ -586,12 +586,12 @@ func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
 	}
 	}
 }
 }
 
 
-// TestRunSeccompProfileDenyCloneUserns checks that 'docker run userns-test'
+// TestRunSeccompProfileDenyCloneUserns checks that 'docker run syscall-test'
 // with a the default seccomp profile exits with operation not permitted.
 // with a the default seccomp profile exits with operation not permitted.
 func (s *DockerSuite) TestRunSeccompProfileDenyCloneUserns(c *check.C) {
 func (s *DockerSuite) TestRunSeccompProfileDenyCloneUserns(c *check.C) {
 	testRequires(c, SameHostDaemon, seccompEnabled)
 	testRequires(c, SameHostDaemon, seccompEnabled)
 
 
-	runCmd := exec.Command(dockerBinary, "run", "userns-test", "id")
+	runCmd := exec.Command(dockerBinary, "run", "syscall-test", "userns-test", "id")
 	out, _, err := runCommandWithOutput(runCmd)
 	out, _, err := runCommandWithOutput(runCmd)
 	if err == nil || !strings.Contains(out, "clone failed: Operation not permitted") {
 	if err == nil || !strings.Contains(out, "clone failed: Operation not permitted") {
 		c.Fatalf("expected clone userns with default seccomp profile denied to fail, got %s: %v", out, err)
 		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) {
 }
 }
 
 
 // TestRunSeccompUnconfinedCloneUserns checks that
 // TestRunSeccompUnconfinedCloneUserns checks that
-// 'docker run --security-opt seccomp:unconfined userns-test' allows creating a userns.
+// 'docker run --security-opt seccomp:unconfined syscall-test' allows creating a userns.
 func (s *DockerSuite) TestRunSeccompUnconfinedCloneUserns(c *check.C) {
 func (s *DockerSuite) TestRunSeccompUnconfinedCloneUserns(c *check.C) {
 	testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace)
 	testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace)
 
 
 	// make sure running w privileged is ok
 	// make sure running w privileged is ok
-	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp:unconfined", "userns-test", "id")
+	runCmd := exec.Command(dockerBinary, "run", "--security-opt", "seccomp:unconfined", "syscall-test", "userns-test", "id")
 	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
 	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
 		c.Fatalf("expected clone userns with --security-opt seccomp:unconfined to succeed, got %s: %v", out, err)
 		c.Fatalf("expected clone userns with --security-opt seccomp:unconfined to succeed, got %s: %v", out, err)
 	}
 	}
 }
 }
 
 
-// TestRunSeccompAllowPrivCloneUserns checks that 'docker run --privileged userns-test'
+// TestRunSeccompAllowPrivCloneUserns checks that 'docker run --privileged syscall-test'
 // allows creating a userns.
 // allows creating a userns.
 func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) {
 func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) {
 	testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace)
 	testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace)
 
 
 	// make sure running w privileged is ok
 	// make sure running w privileged is ok
-	runCmd := exec.Command(dockerBinary, "run", "--privileged", "userns-test", "id")
+	runCmd := exec.Command(dockerBinary, "run", "--privileged", "syscall-test", "userns-test", "id")
 	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
 	if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "nobody") {
 		c.Fatalf("expected clone userns with --privileged to succeed, got %s: %v", out, err)
 		c.Fatalf("expected clone userns with --privileged to succeed, got %s: %v", out, err)
 	}
 	}
@@ -624,7 +624,7 @@ func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) {
 
 
 // TestRunSeccompAllowAptKey checks that 'docker run debian:jessie apt-key' succeeds.
 // TestRunSeccompAllowAptKey checks that 'docker run debian:jessie apt-key' succeeds.
 func (s *DockerSuite) TestRunSeccompAllowAptKey(c *check.C) {
 func (s *DockerSuite) TestRunSeccompAllowAptKey(c *check.C) {
-	testRequires(c, SameHostDaemon, seccompEnabled)
+	testRequires(c, SameHostDaemon, seccompEnabled, Network)
 
 
 	// apt-key uses setrlimit & getrlimit, so we want to make sure we don't break it
 	// apt-key uses setrlimit & getrlimit, so we want to make sure we don't break it
 	runCmd := exec.Command(dockerBinary, "run", "debian:jessie", "apt-key", "adv", "--keyserver", "hkp://p80.pool.sks-keyservers.net:80", "--recv-keys", "E871F18B51E0147C77796AC81196BA81F6B0FC61")
 	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) {
 		c.Fatalf("expected apt-key with seccomp to succeed, got %s: %v", out, err)
 		c.Fatalf("expected apt-key with seccomp to succeed, got %s: %v", out, err)
 	}
 	}
 }
 }
+
+func (s *DockerSuite) TestRunSeccompDefaultProfile(c *check.C) {
+	testRequires(c, SameHostDaemon, seccompEnabled, NotUserNamespace)
+
+	out, _, err := dockerCmdWithError("run", "--cap-add", "ALL", "syscall-test", "acct-test")
+	if err == nil || !strings.Contains(out, "Operation not permitted") {
+		c.Fatalf("expected Operation not permitted, got: %s", out)
+	}
+
+	out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "syscall-test", "ns-test", "echo", "hello")
+	if err == nil || !strings.Contains(out, "Operation not permitted") {
+		c.Fatalf("expected Operation not permitted, got: %s", out)
+	}
+
+	out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "--security-opt", "seccomp:unconfined", "syscall-test", "acct-test")
+	if err == nil || !strings.Contains(out, "No such file or directory") {
+		c.Fatalf("expected No such file or directory, got: %s", out)
+	}
+
+	out, _, err = dockerCmdWithError("run", "--cap-add", "ALL", "--security-opt", "seccomp:unconfined", "syscall-test", "ns-test", "echo", "hello")
+	if err != nil || !strings.Contains(out, "hello") {
+		c.Fatalf("expected hello, got: %s, %v", out, err)
+	}
+}