Merge pull request #29076 from justincormack/seccomp-socket-to-them
Block obsolete and unusual socket families in the default seccomp profile
(cherry picked from commit 48184351c9
)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
9fb5c83df0
commit
1235b56fbc
6 changed files with 392 additions and 7 deletions
|
@ -10,6 +10,7 @@ RUN gcc -g -Wall -static userns.c -o /usr/bin/userns-test \
|
||||||
&& gcc -g -Wall -static setuid.c -o /usr/bin/setuid-test \
|
&& gcc -g -Wall -static setuid.c -o /usr/bin/setuid-test \
|
||||||
&& gcc -g -Wall -static setgid.c -o /usr/bin/setgid-test \
|
&& gcc -g -Wall -static setgid.c -o /usr/bin/setgid-test \
|
||||||
&& gcc -g -Wall -static socket.c -o /usr/bin/socket-test \
|
&& gcc -g -Wall -static socket.c -o /usr/bin/socket-test \
|
||||||
&& gcc -g -Wall -static raw.c -o /usr/bin/raw-test
|
&& gcc -g -Wall -static raw.c -o /usr/bin/raw-test \
|
||||||
|
&& gcc -g -Wall -static appletalk.c -o /usr/bin/appletalk-test
|
||||||
|
|
||||||
RUN [ "$(uname -m)" = "x86_64" ] && gcc -s -m32 -nostdlib exit32.s -o /usr/bin/exit32-test || true
|
RUN [ "$(uname -m)" = "x86_64" ] && gcc -s -m32 -nostdlib exit32.s -o /usr/bin/exit32-test || true
|
||||||
|
|
12
contrib/syscall-test/appletalk.c
Normal file
12
contrib/syscall-test/appletalk.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
if (socket(AF_APPLETALK, SOCK_DGRAM, 0) != -1) {
|
||||||
|
fprintf(stderr, "Opening Appletalk socket worked, should be blocked\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -979,7 +979,7 @@ func (s *DockerSuite) TestRunSeccompProfileDenyChmod(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestRunSeccompProfileDenyUnshareUserns checks that 'docker run debian:jessie unshare --map-root-user --user sh -c whoami' with a specific profile to
|
// TestRunSeccompProfileDenyUnshareUserns checks that 'docker run debian:jessie unshare --map-root-user --user sh -c whoami' with a specific profile to
|
||||||
// deny unhare of a userns exits with operation not permitted.
|
// deny unshare of a userns exits with operation not permitted.
|
||||||
func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
|
func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
|
||||||
testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor)
|
testRequires(c, SameHostDaemon, seccompEnabled, NotArm, Apparmor)
|
||||||
// from sched.h
|
// from sched.h
|
||||||
|
@ -1015,6 +1015,18 @@ func (s *DockerSuite) TestRunSeccompProfileDenyUnshareUserns(c *check.C) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestRunSeccompProfileDenyUnusualSocketFamilies checks that rarely used socket families such as Appletalk are blocked by the default profile
|
||||||
|
func (s *DockerSuite) TestRunSeccompProfileDenyUnusualSocketFamilies(c *check.C) {
|
||||||
|
testRequires(c, SameHostDaemon, seccompEnabled)
|
||||||
|
ensureSyscallTest(c)
|
||||||
|
|
||||||
|
runCmd := exec.Command(dockerBinary, "run", "syscall-test", "appletalk-test")
|
||||||
|
_, _, err := runCommandWithOutput(runCmd)
|
||||||
|
if err != nil {
|
||||||
|
c.Fatal("expected opening appletalk socket family to fail")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestRunSeccompProfileDenyCloneUserns checks that 'docker run syscall-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) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ func ensureSyscallTest(c *check.C) {
|
||||||
gcc, err := exec.LookPath("gcc")
|
gcc, err := exec.LookPath("gcc")
|
||||||
c.Assert(err, checker.IsNil, check.Commentf("could not find gcc"))
|
c.Assert(err, checker.IsNil, check.Commentf("could not find gcc"))
|
||||||
|
|
||||||
tests := []string{"userns", "ns", "acct", "setuid", "setgid", "socket", "raw"}
|
tests := []string{"userns", "ns", "acct", "setuid", "setgid", "socket", "raw", "appletalk"}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
out, err := exec.Command(gcc, "-g", "-Wall", "-static", fmt.Sprintf("../contrib/syscall-test/%s.c", test), "-o", fmt.Sprintf("%s/%s-test", tmp, test)).CombinedOutput()
|
out, err := exec.Command(gcc, "-g", "-Wall", "-static", fmt.Sprintf("../contrib/syscall-test/%s.c", test), "-o", fmt.Sprintf("%s/%s-test", tmp, test)).CombinedOutput()
|
||||||
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
|
c.Assert(err, checker.IsNil, check.Commentf(string(out)))
|
||||||
|
|
|
@ -312,8 +312,6 @@
|
||||||
"signalfd",
|
"signalfd",
|
||||||
"signalfd4",
|
"signalfd4",
|
||||||
"sigreturn",
|
"sigreturn",
|
||||||
"socket",
|
|
||||||
"socketcall",
|
|
||||||
"socketpair",
|
"socketpair",
|
||||||
"splice",
|
"splice",
|
||||||
"stat",
|
"stat",
|
||||||
|
@ -415,6 +413,223 @@
|
||||||
"includes": {},
|
"includes": {},
|
||||||
"excludes": {}
|
"excludes": {}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socket"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socket"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 2,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socket"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 10,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socket"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 16,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socket"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 17,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socketcall"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_GT"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socketcall"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socketcall"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"value": 2,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socketcall"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"value": 10,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socketcall"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"value": 16,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": [
|
||||||
|
"socketcall"
|
||||||
|
],
|
||||||
|
"action": "SCMP_ACT_ALLOW",
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"value": 1,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"index": 1,
|
||||||
|
"value": 17,
|
||||||
|
"valueTwo": 0,
|
||||||
|
"op": "SCMP_CMP_EQ"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment": "",
|
||||||
|
"includes": {},
|
||||||
|
"excludes": {}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"names": [
|
"names": [
|
||||||
"sync_file_range2"
|
"sync_file_range2"
|
||||||
|
|
|
@ -306,8 +306,6 @@ func DefaultProfile() *types.Seccomp {
|
||||||
"signalfd",
|
"signalfd",
|
||||||
"signalfd4",
|
"signalfd4",
|
||||||
"sigreturn",
|
"sigreturn",
|
||||||
"socket",
|
|
||||||
"socketcall",
|
|
||||||
"socketpair",
|
"socketpair",
|
||||||
"splice",
|
"splice",
|
||||||
"stat",
|
"stat",
|
||||||
|
@ -388,6 +386,153 @@ func DefaultProfile() *types.Seccomp {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socket"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: syscall.AF_UNIX,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socket"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: syscall.AF_INET,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socket"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: syscall.AF_INET6,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socket"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: syscall.AF_NETLINK,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socket"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: syscall.AF_PACKET,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// socketcall(1, ...) is equivalent to socket(...) on some architectures eg i386
|
||||||
|
{
|
||||||
|
Names: []string{"socketcall"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 1,
|
||||||
|
Op: types.OpGreaterThan,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socketcall"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 1,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: syscall.AF_UNIX,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socketcall"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 1,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: syscall.AF_INET,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socketcall"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 1,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: syscall.AF_INET6,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socketcall"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 1,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: syscall.AF_NETLINK,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"socketcall"},
|
||||||
|
Action: types.ActAllow,
|
||||||
|
Args: []*types.Arg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 1,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Index: 1,
|
||||||
|
Value: syscall.AF_PACKET,
|
||||||
|
Op: types.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Names: []string{
|
Names: []string{
|
||||||
"sync_file_range2",
|
"sync_file_range2",
|
||||||
|
|
Loading…
Reference in a new issue