Merge pull request #42005 from thaJeztah/refactor_seccomp

Refactor seccomp types to reuse runtime-spec, and add support for "ErrnoRet"
This commit is contained in:
Sebastiaan van Stijn 2021-07-07 11:58:13 +02:00 committed by GitHub
commit 5e4da6cc82
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 681 additions and 687 deletions

View file

@ -393,11 +393,7 @@
"write",
"writev"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {},
"excludes": {}
"action": "SCMP_ACT_ALLOW"
},
{
"names": [
@ -406,12 +402,9 @@
"ptrace"
],
"action": "SCMP_ACT_ALLOW",
"args": null,
"comment": "",
"includes": {
"minKernel": "4.8"
},
"excludes": {}
}
},
{
"names": [
@ -424,10 +417,7 @@
"value": 0,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
]
},
{
"names": [
@ -440,10 +430,7 @@
"value": 8,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
]
},
{
"names": [
@ -456,10 +443,7 @@
"value": 131072,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
]
},
{
"names": [
@ -472,10 +456,7 @@
"value": 131080,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
]
},
{
"names": [
@ -488,24 +469,18 @@
"value": 4294967295,
"op": "SCMP_CMP_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {}
]
},
{
"names": [
"sync_file_range2"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"ppc64le"
]
},
"excludes": {}
}
},
{
"names": [
@ -517,46 +492,37 @@
"set_tls"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"arm",
"arm64"
]
},
"excludes": {}
}
},
{
"names": [
"arch_prctl"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"amd64",
"x32"
]
},
"excludes": {}
}
},
{
"names": [
"modify_ldt"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"amd64",
"x32",
"x86"
]
},
"excludes": {}
}
},
{
"names": [
@ -565,29 +531,23 @@
"s390_runtime_instr"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"arches": [
"s390",
"s390x"
]
},
"excludes": {}
}
},
{
"names": [
"open_by_handle_at"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_DAC_READ_SEARCH"
]
},
"excludes": {}
}
},
{
"names": [
@ -614,14 +574,11 @@
"unshare"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_ADMIN"
]
},
"excludes": {}
}
},
{
"names": [
@ -635,8 +592,6 @@
"op": "SCMP_CMP_MASKED_EQ"
}
],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
@ -677,28 +632,22 @@
"reboot"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_BOOT"
]
},
"excludes": {}
}
},
{
"names": [
"chroot"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_CHROOT"
]
},
"excludes": {}
}
},
{
"names": [
@ -707,28 +656,22 @@
"finit_module"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_MODULE"
]
},
"excludes": {}
}
},
{
"names": [
"acct"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_PACCT"
]
},
"excludes": {}
}
},
{
"names": [
@ -740,14 +683,11 @@
"ptrace"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_PTRACE"
]
},
"excludes": {}
}
},
{
"names": [
@ -755,14 +695,11 @@
"ioperm"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_RAWIO"
]
},
"excludes": {}
}
},
{
"names": [
@ -771,28 +708,22 @@
"clock_settime"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_TIME"
]
},
"excludes": {}
}
},
{
"names": [
"vhangup"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_TTY_CONFIG"
]
},
"excludes": {}
}
},
{
"names": [
@ -801,28 +732,22 @@
"set_mempolicy"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_NICE"
]
},
"excludes": {}
}
},
{
"names": [
"syslog"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYSLOG"
]
},
"excludes": {}
}
}
]
}

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,12 @@
"name": "close",
"action": "SCMP_ACT_ALLOW",
"args": []
},
{
"name": "syslog",
"action": "SCMP_ACT_ERRNO",
"errnoRet": 12345,
"args": []
}
]
}

View file

@ -40,15 +40,18 @@ type Filter struct {
MinKernel *KernelVersion `json:"minKernel,omitempty"`
}
// Syscall is used to match a group of syscalls in Seccomp
// Syscall is used to match a group of syscalls in Seccomp. It extends the
// runtime-spec Syscall type, adding a "Name" field for backward compatibility
// with older JSON representations, additional "Comment" metadata, and conditional
// rules ("Includes", "Excludes") used to generate a runtime-spec Seccomp profile
// based on the container (capabilities) and host's (arch, kernel) configuration.
type Syscall struct {
Name string `json:"name,omitempty"`
Names []string `json:"names,omitempty"`
Action specs.LinuxSeccompAction `json:"action"`
Args []*specs.LinuxSeccompArg `json:"args"`
Comment string `json:"comment"`
Includes Filter `json:"includes"`
Excludes Filter `json:"excludes"`
specs.LinuxSyscall
// Deprecated: kept for backward compatibility with old JSON profiles, use Names instead
Name string `json:"name,omitempty"`
Comment string `json:"comment,omitempty"`
Includes *Filter `json:"includes,omitempty"`
Excludes *Filter `json:"excludes,omitempty"`
}
// KernelVersion holds information about the kernel.

View file

@ -111,68 +111,58 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error)
Loop:
// Loop through all syscall blocks and convert them to libcontainer format after filtering them
for _, call := range config.Syscalls {
if len(call.Excludes.Arches) > 0 {
if inSlice(call.Excludes.Arches, arch) {
continue Loop
if call.Excludes != nil {
if len(call.Excludes.Arches) > 0 {
if inSlice(call.Excludes.Arches, arch) {
continue Loop
}
}
}
if len(call.Excludes.Caps) > 0 {
for _, c := range call.Excludes.Caps {
if inSlice(rs.Process.Capabilities.Bounding, c) {
if len(call.Excludes.Caps) > 0 {
for _, c := range call.Excludes.Caps {
if inSlice(rs.Process.Capabilities.Bounding, c) {
continue Loop
}
}
}
if call.Excludes.MinKernel != nil {
if ok, err := kernelGreaterEqualThan(*call.Excludes.MinKernel); err != nil {
return nil, err
} else if ok {
continue Loop
}
}
}
if call.Excludes.MinKernel != nil {
if ok, err := kernelGreaterEqualThan(*call.Excludes.MinKernel); err != nil {
return nil, err
} else if ok {
continue Loop
}
}
if len(call.Includes.Arches) > 0 {
if !inSlice(call.Includes.Arches, arch) {
continue Loop
}
}
if len(call.Includes.Caps) > 0 {
for _, c := range call.Includes.Caps {
if !inSlice(rs.Process.Capabilities.Bounding, c) {
if call.Includes != nil {
if len(call.Includes.Arches) > 0 {
if !inSlice(call.Includes.Arches, arch) {
continue Loop
}
}
}
if call.Includes.MinKernel != nil {
if ok, err := kernelGreaterEqualThan(*call.Includes.MinKernel); err != nil {
return nil, err
} else if !ok {
continue Loop
if len(call.Includes.Caps) > 0 {
for _, c := range call.Includes.Caps {
if !inSlice(rs.Process.Capabilities.Bounding, c) {
continue Loop
}
}
}
if call.Includes.MinKernel != nil {
if ok, err := kernelGreaterEqualThan(*call.Includes.MinKernel); err != nil {
return nil, err
} else if !ok {
continue Loop
}
}
}
if call.Name != "" && len(call.Names) != 0 {
return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'")
}
if call.Name != "" {
newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall([]string{call.Name}, call.Action, call.Args))
} else {
newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Names, call.Action, call.Args))
if len(call.Names) != 0 {
return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'")
}
call.Names = append(call.Names, call.Name)
}
newConfig.Syscalls = append(newConfig.Syscalls, call.LinuxSyscall)
}
return newConfig, nil
}
func createSpecsSyscall(names []string, action specs.LinuxSeccompAction, args []*specs.LinuxSeccompArg) specs.LinuxSyscall {
newCall := specs.LinuxSyscall{
Names: names,
Action: action,
}
// Loop through all the arguments of the syscall and convert them
for _, arg := range args {
newCall.Args = append(newCall.Args, *arg)
}
return newCall
}

View file

@ -18,9 +18,45 @@ func TestLoadProfile(t *testing.T) {
t.Fatal(err)
}
rs := createSpec()
if _, err := LoadProfile(string(f), &rs); err != nil {
p, err := LoadProfile(string(f), &rs)
if err != nil {
t.Fatal(err)
}
var expectedErrno uint = 12345
expected := specs.LinuxSeccomp{
DefaultAction: "SCMP_ACT_ERRNO",
Syscalls: []specs.LinuxSyscall{
{
Names: []string{"clone"},
Action: "SCMP_ACT_ALLOW",
Args: []specs.LinuxSeccompArg{{
Index: 0,
Value: 2114060288,
ValueTwo: 0,
Op: "SCMP_CMP_MASKED_EQ",
}},
},
{
Names: []string{"open"},
Action: "SCMP_ACT_ALLOW",
Args: []specs.LinuxSeccompArg{},
},
{
Names: []string{"close"},
Action: "SCMP_ACT_ALLOW",
Args: []specs.LinuxSeccompArg{},
},
{
Names: []string{"syslog"},
Action: "SCMP_ACT_ERRNO",
ErrnoRet: &expectedErrno,
Args: []specs.LinuxSeccompArg{},
},
},
}
assert.DeepEqual(t, expected, *p)
}
// TestLoadLegacyProfile tests loading a seccomp profile in the old format