k3s/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go

141 lines
4.1 KiB
Go

package seccomp
import (
"fmt"
"reflect"
"strconv"
"strings"
rspec "github.com/opencontainers/runtime-spec/specs-go"
)
// Determine if a new syscall rule should be appended, overwrite an existing rule
// or if no action should be taken at all
func decideCourseOfAction(newSyscall *rspec.LinuxSyscall, syscalls []rspec.LinuxSyscall) (string, error) {
ruleForSyscallAlreadyExists := false
var sliceOfDeterminedActions []string
for i, syscall := range syscalls {
if sameName(&syscall, newSyscall) {
ruleForSyscallAlreadyExists = true
if identical(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, nothing)
}
if sameAction(newSyscall, &syscall) {
if bothHaveArgs(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend)
}
if onlyOneHasArgs(newSyscall, &syscall) {
if firstParamOnlyHasArgs(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i))
} else {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, nothing)
}
}
}
if !sameAction(newSyscall, &syscall) {
if bothHaveArgs(newSyscall, &syscall) {
if sameArgs(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i))
}
if !sameArgs(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend)
}
}
if onlyOneHasArgs(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend)
}
if neitherHasArgs(newSyscall, &syscall) {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i))
}
}
}
}
if !ruleForSyscallAlreadyExists {
sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend)
}
// Nothing has highest priority
for _, determinedAction := range sliceOfDeterminedActions {
if determinedAction == nothing {
return determinedAction, nil
}
}
// Overwrite has second highest priority
for _, determinedAction := range sliceOfDeterminedActions {
if strings.Contains(determinedAction, seccompOverwrite) {
return determinedAction, nil
}
}
// Append has the lowest priority
for _, determinedAction := range sliceOfDeterminedActions {
if determinedAction == seccompAppend {
return determinedAction, nil
}
}
return "", fmt.Errorf("Trouble determining action: %s", sliceOfDeterminedActions)
}
func hasArguments(config *rspec.LinuxSyscall) bool {
nilSyscall := new(rspec.LinuxSyscall)
return !sameArgs(nilSyscall, config)
}
func identical(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1, config2)
}
func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
samename := sameName(config1, config2)
sameAction := sameAction(config1, config2)
sameArgs := sameArgs(config1, config2)
return samename && !sameAction && sameArgs
}
func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
samename := sameName(config1, config2)
sameAction := sameAction(config1, config2)
sameArgs := sameArgs(config1, config2)
return samename && sameAction && !sameArgs
}
func sameName(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1.Names, config2.Names)
}
func sameAction(config1, config2 *rspec.LinuxSyscall) bool {
return config1.Action == config2.Action
}
func sameArgs(config1, config2 *rspec.LinuxSyscall) bool {
return reflect.DeepEqual(config1.Args, config2.Args)
}
func bothHaveArgs(config1, config2 *rspec.LinuxSyscall) bool {
return hasArguments(config1) && hasArguments(config2)
}
func onlyOneHasArgs(config1, config2 *rspec.LinuxSyscall) bool {
conf1 := hasArguments(config1)
conf2 := hasArguments(config2)
return (conf1 && !conf2) || (!conf1 && conf2)
}
func neitherHasArgs(config1, config2 *rspec.LinuxSyscall) bool {
return !hasArguments(config1) && !hasArguments(config2)
}
func firstParamOnlyHasArgs(config1, config2 *rspec.LinuxSyscall) bool {
return !hasArguments(config1) && hasArguments(config2)
}