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>
... | ... |
@@ -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, |