github.com/opencontainers/runtime-tools@v0.9.0/generate/seccomp/syscall_compare.go (about) 1 package seccomp 2 3 import ( 4 "fmt" 5 "reflect" 6 "strconv" 7 "strings" 8 9 rspec "github.com/opencontainers/runtime-spec/specs-go" 10 ) 11 12 // Determine if a new syscall rule should be appended, overwrite an existing rule 13 // or if no action should be taken at all 14 func decideCourseOfAction(newSyscall *rspec.LinuxSyscall, syscalls []rspec.LinuxSyscall) (string, error) { 15 ruleForSyscallAlreadyExists := false 16 17 var sliceOfDeterminedActions []string 18 for i, syscall := range syscalls { 19 if sameName(&syscall, newSyscall) { 20 ruleForSyscallAlreadyExists = true 21 22 if identical(newSyscall, &syscall) { 23 sliceOfDeterminedActions = append(sliceOfDeterminedActions, nothing) 24 } 25 26 if sameAction(newSyscall, &syscall) { 27 if bothHaveArgs(newSyscall, &syscall) { 28 sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) 29 } 30 if onlyOneHasArgs(newSyscall, &syscall) { 31 if firstParamOnlyHasArgs(newSyscall, &syscall) { 32 sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i)) 33 } else { 34 sliceOfDeterminedActions = append(sliceOfDeterminedActions, nothing) 35 } 36 } 37 } 38 39 if !sameAction(newSyscall, &syscall) { 40 if bothHaveArgs(newSyscall, &syscall) { 41 if sameArgs(newSyscall, &syscall) { 42 sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i)) 43 } 44 if !sameArgs(newSyscall, &syscall) { 45 sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) 46 } 47 } 48 if onlyOneHasArgs(newSyscall, &syscall) { 49 sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) 50 } 51 if neitherHasArgs(newSyscall, &syscall) { 52 sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i)) 53 } 54 } 55 } 56 } 57 58 if !ruleForSyscallAlreadyExists { 59 sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) 60 } 61 62 // Nothing has highest priority 63 for _, determinedAction := range sliceOfDeterminedActions { 64 if determinedAction == nothing { 65 return determinedAction, nil 66 } 67 } 68 69 // Overwrite has second highest priority 70 for _, determinedAction := range sliceOfDeterminedActions { 71 if strings.Contains(determinedAction, seccompOverwrite) { 72 return determinedAction, nil 73 } 74 } 75 76 // Append has the lowest priority 77 for _, determinedAction := range sliceOfDeterminedActions { 78 if determinedAction == seccompAppend { 79 return determinedAction, nil 80 } 81 } 82 83 return "", fmt.Errorf("Trouble determining action: %s", sliceOfDeterminedActions) 84 } 85 86 func hasArguments(config *rspec.LinuxSyscall) bool { 87 nilSyscall := new(rspec.LinuxSyscall) 88 return !sameArgs(nilSyscall, config) 89 } 90 91 func identical(config1, config2 *rspec.LinuxSyscall) bool { 92 return reflect.DeepEqual(config1, config2) 93 } 94 95 func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool { 96 samename := sameName(config1, config2) 97 sameAction := sameAction(config1, config2) 98 sameArgs := sameArgs(config1, config2) 99 100 return samename && !sameAction && sameArgs 101 } 102 103 func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool { 104 samename := sameName(config1, config2) 105 sameAction := sameAction(config1, config2) 106 sameArgs := sameArgs(config1, config2) 107 108 return samename && sameAction && !sameArgs 109 } 110 111 func sameName(config1, config2 *rspec.LinuxSyscall) bool { 112 return reflect.DeepEqual(config1.Names, config2.Names) 113 } 114 115 func sameAction(config1, config2 *rspec.LinuxSyscall) bool { 116 return config1.Action == config2.Action 117 } 118 119 func sameArgs(config1, config2 *rspec.LinuxSyscall) bool { 120 return reflect.DeepEqual(config1.Args, config2.Args) 121 } 122 123 func bothHaveArgs(config1, config2 *rspec.LinuxSyscall) bool { 124 return hasArguments(config1) && hasArguments(config2) 125 } 126 127 func onlyOneHasArgs(config1, config2 *rspec.LinuxSyscall) bool { 128 conf1 := hasArguments(config1) 129 conf2 := hasArguments(config2) 130 131 return (conf1 && !conf2) || (!conf1 && conf2) 132 } 133 134 func neitherHasArgs(config1, config2 *rspec.LinuxSyscall) bool { 135 return !hasArguments(config1) && !hasArguments(config2) 136 } 137 138 func firstParamOnlyHasArgs(config1, config2 *rspec.LinuxSyscall) bool { 139 return !hasArguments(config1) && hasArguments(config2) 140 }