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  }