Browse code

Enable seccomp for s390x

To implement seccomp for s390x the following changes are required:

1) seccomp_default: Add s390 compat mode

On s390x (64 bit) we can run s390 (32 bit) programs in 32 bit
compat mode. Therefore add this information to arches().

2) seccomp_default: Use correct flags parameter for sys_clone on s390x

On s390x the second parameter for the clone system call is the flags
parameter. On all other architectures it is the first one.

See kernel code kernel/fork.c:

#elif defined(CONFIG_CLONE_BACKWARDS2)
SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags,
int __user *, parent_tidptr,

So fix the docker default seccomp rule and check for the second
parameter on s390/s390x.

3) seccomp_default: Add s390 specific syscalls

For s390 we currently have three additional system calls that should
be added to the seccomp whitelist:

- Other architectures can read/write unprivileged from/to PCI MMIO memory.
On s390 the instructions are privileged and therefore we need system
calls for that purpose:

* s390_pci_mmio_write()
* s390_pci_mmio_read()

- Runtime instrumentation:

* s390_runtime_instr()

4) test_integration: Do not run seccomp default profile test on s390x

The generated profile that we check in is for amd64 and i386
architectures and does not work correctly on s390x.

See also: 75385dc216e ("Do not run the seccomp tests that use
default.json on non x86 architectures")

5) Dockerfile.s390x: Add "seccomp" to DOCKER_BUILDTAGS

Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>

Michael Holzheu authored on 2016/05/31 22:27:28
Showing 4 changed files
... ...
@@ -161,7 +161,7 @@ RUN useradd --create-home --gid docker unprivilegeduser
161 161
 
162 162
 VOLUME /var/lib/docker
163 163
 WORKDIR /go/src/github.com/docker/docker
164
-ENV DOCKER_BUILDTAGS apparmor selinux
164
+ENV DOCKER_BUILDTAGS apparmor selinux seccomp
165 165
 
166 166
 # Let us use a .bashrc file
167 167
 RUN ln -sfv $PWD/.bashrc ~/.bashrc
... ...
@@ -1184,7 +1184,7 @@ func (s *DockerSuite) TestRunApparmorProcDirectory(c *check.C) {
1184 1184
 // make sure the default profile can be successfully parsed (using unshare as it is
1185 1185
 // something which we know is blocked in the default profile)
1186 1186
 func (s *DockerSuite) TestRunSeccompWithDefaultProfile(c *check.C) {
1187
-	testRequires(c, SameHostDaemon, seccompEnabled, NotArm, NotPpc64le)
1187
+	testRequires(c, SameHostDaemon, seccompEnabled, NotArm, NotPpc64le, NotS390X)
1188 1188
 
1189 1189
 	out, _, err := dockerCmdWithError("run", "--security-opt", "seccomp=../profiles/seccomp/default.json", "debian:jessie", "unshare", "--map-root-user", "--user", "sh", "-c", "whoami")
1190 1190
 	c.Assert(err, checker.NotNil, check.Commentf(out))
... ...
@@ -42,6 +42,10 @@ var (
42 42
 		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "ppc64le" },
43 43
 		"Test requires a daemon not running on ppc64le",
44 44
 	}
45
+	NotS390X = testRequirement{
46
+		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "s390x" },
47
+		"Test requires a daemon not running on s390x",
48
+	}
45 49
 	SameHostDaemon = testRequirement{
46 50
 		func() bool { return isLocalDaemon },
47 51
 		"Test requires docker daemon to run on the same machine as CLI",
... ...
@@ -29,6 +29,8 @@ func arches() []types.Arch {
29 29
 		return []types.Arch{types.ArchMIPSEL, types.ArchMIPSEL64, types.ArchMIPSEL64N32}
30 30
 	case "mipsel64n32":
31 31
 		return []types.Arch{types.ArchMIPSEL, types.ArchMIPSEL64, types.ArchMIPSEL64N32}
32
+	case "s390x":
33
+		return []types.Arch{types.ArchS390, types.ArchS390X}
32 34
 	default:
33 35
 		return []types.Arch{}
34 36
 	}
... ...
@@ -1579,6 +1581,7 @@ func DefaultProfile(rs *specs.Spec) *types.Seccomp {
1579 1579
 		},
1580 1580
 	}
1581 1581
 
1582
+	var sysCloneFlagsIndex uint
1582 1583
 	var arch string
1583 1584
 	var native, err = libseccomp.GetNativeArch()
1584 1585
 	if err == nil {
... ...
@@ -1620,6 +1623,26 @@ func DefaultProfile(rs *specs.Spec) *types.Seccomp {
1620 1620
 				Args:   []*types.Arg{},
1621 1621
 			},
1622 1622
 		}...)
1623
+	case "s390", "s390x":
1624
+		syscalls = append(syscalls, []*types.Syscall{
1625
+			{
1626
+				Name:   "s390_pci_mmio_read",
1627
+				Action: types.ActAllow,
1628
+				Args:   []*types.Arg{},
1629
+			},
1630
+			{
1631
+				Name:   "s390_pci_mmio_write",
1632
+				Action: types.ActAllow,
1633
+				Args:   []*types.Arg{},
1634
+			},
1635
+			{
1636
+				Name:   "s390_runtime_instr",
1637
+				Action: types.ActAllow,
1638
+				Args:   []*types.Arg{},
1639
+			},
1640
+		}...)
1641
+		/* Flags parameter of the clone syscall is the 2nd on s390 */
1642
+		sysCloneFlagsIndex = 1
1623 1643
 	}
1624 1644
 
1625 1645
 	capSysAdmin := false
... ...
@@ -1841,7 +1864,7 @@ func DefaultProfile(rs *specs.Spec) *types.Seccomp {
1841 1841
 				Action: types.ActAllow,
1842 1842
 				Args: []*types.Arg{
1843 1843
 					{
1844
-						Index:    0,
1844
+						Index:    sysCloneFlagsIndex,
1845 1845
 						Value:    syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWUSER | syscall.CLONE_NEWPID | syscall.CLONE_NEWNET,
1846 1846
 						ValueTwo: 0,
1847 1847
 						Op:       types.OpMaskedEqual,