github.com/opencontainers/runtime-tools@v0.9.0/generate/seccomp/parse_action.go (about)

     1  package seccomp
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	rspec "github.com/opencontainers/runtime-spec/specs-go"
     9  )
    10  
    11  // SyscallOpts contain options for parsing syscall rules
    12  type SyscallOpts struct {
    13  	Action   string
    14  	Syscall  string
    15  	Index    string
    16  	Value    string
    17  	ValueTwo string
    18  	Operator string
    19  }
    20  
    21  // ParseSyscallFlag takes a SyscallOpts struct and the seccomp configuration
    22  // and sets the new syscall rule accordingly
    23  func ParseSyscallFlag(args SyscallOpts, config *rspec.LinuxSeccomp) error {
    24  	var arguments []string
    25  	if args.Index != "" && args.Value != "" && args.ValueTwo != "" && args.Operator != "" {
    26  		arguments = []string{args.Action, args.Syscall, args.Index, args.Value,
    27  			args.ValueTwo, args.Operator}
    28  	} else {
    29  		arguments = []string{args.Action, args.Syscall}
    30  	}
    31  
    32  	action, _ := parseAction(arguments[0])
    33  	if action == config.DefaultAction && args.argsAreEmpty() {
    34  		// default already set, no need to make changes
    35  		return nil
    36  	}
    37  
    38  	var newSyscall rspec.LinuxSyscall
    39  	numOfArgs := len(arguments)
    40  	if numOfArgs == 6 || numOfArgs == 2 {
    41  		argStruct, err := parseArguments(arguments[1:])
    42  		if err != nil {
    43  			return err
    44  		}
    45  		newSyscall = newSyscallStruct(arguments[1], action, argStruct)
    46  	} else {
    47  		return fmt.Errorf("incorrect number of arguments to ParseSyscall: %d", numOfArgs)
    48  	}
    49  
    50  	descison, err := decideCourseOfAction(&newSyscall, config.Syscalls)
    51  	if err != nil {
    52  		return err
    53  	}
    54  	delimDescison := strings.Split(descison, ":")
    55  
    56  	if delimDescison[0] == seccompAppend {
    57  		config.Syscalls = append(config.Syscalls, newSyscall)
    58  	}
    59  
    60  	if delimDescison[0] == seccompOverwrite {
    61  		indexForOverwrite, err := strconv.ParseInt(delimDescison[1], 10, 32)
    62  		if err != nil {
    63  			return err
    64  		}
    65  		config.Syscalls[indexForOverwrite] = newSyscall
    66  	}
    67  
    68  	return nil
    69  }
    70  
    71  var actions = map[string]rspec.LinuxSeccompAction{
    72  	"allow": rspec.ActAllow,
    73  	"errno": rspec.ActErrno,
    74  	"kill":  rspec.ActKill,
    75  	"trace": rspec.ActTrace,
    76  	"trap":  rspec.ActTrap,
    77  }
    78  
    79  // Take passed action, return the SCMP_ACT_<ACTION> version of it
    80  func parseAction(action string) (rspec.LinuxSeccompAction, error) {
    81  	a, ok := actions[action]
    82  	if !ok {
    83  		return "", fmt.Errorf("unrecognized action: %s", action)
    84  	}
    85  	return a, nil
    86  }
    87  
    88  // ParseDefaultAction sets the default action of the seccomp configuration
    89  // and then removes any rules that were already specified with this action
    90  func ParseDefaultAction(action string, config *rspec.LinuxSeccomp) error {
    91  	if action == "" {
    92  		return nil
    93  	}
    94  
    95  	defaultAction, err := parseAction(action)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	config.DefaultAction = defaultAction
   100  	err = RemoveAllMatchingRules(config, defaultAction)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return nil
   105  }
   106  
   107  // ParseDefaultActionForce simply sets the default action of the seccomp configuration
   108  func ParseDefaultActionForce(action string, config *rspec.LinuxSeccomp) error {
   109  	if action == "" {
   110  		return nil
   111  	}
   112  
   113  	defaultAction, err := parseAction(action)
   114  	if err != nil {
   115  		return err
   116  	}
   117  	config.DefaultAction = defaultAction
   118  	return nil
   119  }
   120  
   121  func newSyscallStruct(name string, action rspec.LinuxSeccompAction, args []rspec.LinuxSeccompArg) rspec.LinuxSyscall {
   122  	syscallStruct := rspec.LinuxSyscall{
   123  		Names:  []string{name},
   124  		Action: action,
   125  		Args:   args,
   126  	}
   127  	return syscallStruct
   128  }
   129  
   130  func (s SyscallOpts) argsAreEmpty() bool {
   131  	return (s.Index == "" &&
   132  		s.Value == "" &&
   133  		s.ValueTwo == "" &&
   134  		s.Operator == "")
   135  }