From 93bbc76ee53240e0862c6f1ff409e7a4ee0883dc Mon Sep 17 00:00:00 2001 From: Justin Cormack Date: Wed, 27 Jul 2016 18:42:34 +0100 Subject: [PATCH] Add a test that the default seccomp profile allows execution of 32 bit binaries While testing #24510 I noticed that 32 bit syscalls were incorrectly being blocked and we did not have a test for this, so adding one. This is only tested on amd64 as it is the only architecture that reliably supports 32 bit code execution, others only do sometimes. There is no 32 bit libc in the buildpack-deps so we cannot build 32 bit C code easily so use the simplest assembly program which just calls the exit syscall. Signed-off-by: Justin Cormack --- contrib/syscall-test/Dockerfile | 2 ++ contrib/syscall-test/exit32.s | 7 +++++++ hack/make/.ensure-syscall-test | 3 +++ integration-cli/docker_cli_run_unix_test.go | 11 +++++++++++ integration-cli/requirements.go | 4 ++++ 5 files changed, 27 insertions(+) create mode 100644 contrib/syscall-test/exit32.s diff --git a/contrib/syscall-test/Dockerfile b/contrib/syscall-test/Dockerfile index 8cd6bebf3d..a2f96b45e6 100644 --- a/contrib/syscall-test/Dockerfile +++ b/contrib/syscall-test/Dockerfile @@ -7,3 +7,5 @@ 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 + +RUN [ "$(uname -m)" = "x86_64" ] && gcc -s -m32 -nostdlib exit32.s -o /usr/bin/exit32-test || true diff --git a/contrib/syscall-test/exit32.s b/contrib/syscall-test/exit32.s new file mode 100644 index 0000000000..8bbb5c58b3 --- /dev/null +++ b/contrib/syscall-test/exit32.s @@ -0,0 +1,7 @@ +.globl _start +.text +_start: + xorl %eax, %eax + incl %eax + movb $0, %bl + int $0x80 diff --git a/hack/make/.ensure-syscall-test b/hack/make/.ensure-syscall-test index 376fef1cf0..b2eba6bc39 100644 --- a/hack/make/.ensure-syscall-test +++ b/hack/make/.ensure-syscall-test @@ -9,6 +9,9 @@ if [ "$DOCKER_ENGINE_GOOS" = "linux" ]; then gcc -g -Wall -static contrib/syscall-test/userns.c -o "${tmpdir}/userns-test" gcc -g -Wall -static contrib/syscall-test/ns.c -o "${tmpdir}/ns-test" gcc -g -Wall -static contrib/syscall-test/acct.c -o "${tmpdir}/acct-test" + if [ "$DOCKER_ENGINE_OSARCH" = "linux/amd64" ]; then + gcc -s -m32 -nostdlib contrib/syscall-test/exit32.s -o "${tmpdir}/exit32-test" + fi dockerfile="${tmpdir}/Dockerfile" cat <<-EOF > "$dockerfile" diff --git a/integration-cli/docker_cli_run_unix_test.go b/integration-cli/docker_cli_run_unix_test.go index c1995b7ce1..f16e210c27 100644 --- a/integration-cli/docker_cli_run_unix_test.go +++ b/integration-cli/docker_cli_run_unix_test.go @@ -1053,6 +1053,17 @@ func (s *DockerSuite) TestRunSeccompAllowPrivCloneUserns(c *check.C) { } } +// TestRunSeccompProfileAllow32Bit checks that 32 bit code can run on x86_64 +// with the default seccomp profile. +func (s *DockerSuite) TestRunSeccompProfileAllow32Bit(c *check.C) { + testRequires(c, SameHostDaemon, seccompEnabled, IsAmd64) + + runCmd := exec.Command(dockerBinary, "run", "syscall-test", "exit32-test", "id") + if out, _, err := runCommandWithOutput(runCmd); err != nil { + c.Fatalf("expected to be able to run 32 bit code, got %s: %v", out, err) + } +} + // TestRunSeccompAllowSetrlimit checks that 'docker run debian:jessie ulimit -v 1048510' succeeds. func (s *DockerSuite) TestRunSeccompAllowSetrlimit(c *check.C) { testRequires(c, SameHostDaemon, seccompEnabled) diff --git a/integration-cli/requirements.go b/integration-cli/requirements.go index 359359dab5..d475892107 100644 --- a/integration-cli/requirements.go +++ b/integration-cli/requirements.go @@ -38,6 +38,10 @@ var ( func() bool { return !utils.ExperimentalBuild() }, "Test requires a non experimental daemon", } + IsAmd64 = testRequirement{ + func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") == "amd64" }, + "Test requires a daemon running on amd64", + } NotArm = testRequirement{ func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" }, "Test requires a daemon not running on ARM",