summaryrefslogtreecommitdiff
path: root/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go
blob: 25daf0752d1670ad73421c8b86c3050f7867d757 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package seccomp

import (
	"fmt"
	"strconv"
	"strings"

	rspec "github.com/opencontainers/runtime-spec/specs-go"
)

// SyscallOpts contain options for parsing syscall rules
type SyscallOpts struct {
	Action   string
	Syscall  string
	Index    string
	Value    string
	ValueTwo string
	Operator string
}

// ParseSyscallFlag takes a SyscallOpts struct and the seccomp configuration
// and sets the new syscall rule accordingly
func ParseSyscallFlag(args SyscallOpts, config *rspec.LinuxSeccomp) error {
	var arguments []string
	if args.Index != "" && args.Value != "" && args.ValueTwo != "" && args.Operator != "" {
		arguments = []string{args.Action, args.Syscall, args.Index, args.Value,
			args.ValueTwo, args.Operator}
	} else {
		arguments = []string{args.Action, args.Syscall}
	}

	action, _ := parseAction(arguments[0])
	if action == config.DefaultAction && args.argsAreEmpty() {
		// default already set, no need to make changes
		return nil
	}

	var newSyscall rspec.LinuxSyscall
	numOfArgs := len(arguments)
	if numOfArgs == 6 || numOfArgs == 2 {
		argStruct, err := parseArguments(arguments[1:])
		if err != nil {
			return err
		}
		newSyscall = newSyscallStruct(arguments[1], action, argStruct)
	} else {
		return fmt.Errorf("incorrect number of arguments to ParseSyscall: %d", numOfArgs)
	}

	descison, err := decideCourseOfAction(&newSyscall, config.Syscalls)
	if err != nil {
		return err
	}
	delimDescison := strings.Split(descison, ":")

	if delimDescison[0] == seccompAppend {
		config.Syscalls = append(config.Syscalls, newSyscall)
	}

	if delimDescison[0] == seccompOverwrite {
		indexForOverwrite, err := strconv.ParseInt(delimDescison[1], 10, 32)
		if err != nil {
			return err
		}
		config.Syscalls[indexForOverwrite] = newSyscall
	}

	return nil
}

var actions = map[string]rspec.LinuxSeccompAction{
	"allow": rspec.ActAllow,
	"errno": rspec.ActErrno,
	"kill":  rspec.ActKill,
	"trace": rspec.ActTrace,
	"trap":  rspec.ActTrap,
}

// Take passed action, return the SCMP_ACT_<ACTION> version of it
func parseAction(action string) (rspec.LinuxSeccompAction, error) {
	a, ok := actions[action]
	if !ok {
		return "", fmt.Errorf("unrecognized action: %s", action)
	}
	return a, nil
}

// ParseDefaultAction sets the default action of the seccomp configuration
// and then removes any rules that were already specified with this action
func ParseDefaultAction(action string, config *rspec.LinuxSeccomp) error {
	if action == "" {
		return nil
	}

	defaultAction, err := parseAction(action)
	if err != nil {
		return err
	}
	config.DefaultAction = defaultAction
	err = RemoveAllMatchingRules(config, defaultAction)
	if err != nil {
		return err
	}
	return nil
}

// ParseDefaultActionForce simply sets the default action of the seccomp configuration
func ParseDefaultActionForce(action string, config *rspec.LinuxSeccomp) error {
	if action == "" {
		return nil
	}

	defaultAction, err := parseAction(action)
	if err != nil {
		return err
	}
	config.DefaultAction = defaultAction
	return nil
}

func newSyscallStruct(name string, action rspec.LinuxSeccompAction, args []rspec.LinuxSeccompArg) rspec.LinuxSyscall {
	syscallStruct := rspec.LinuxSyscall{
		Names:  []string{name},
		Action: action,
		Args:   args,
	}
	return syscallStruct
}

func (s SyscallOpts) argsAreEmpty() bool {
	return (s.Index == "" &&
		s.Value == "" &&
		s.ValueTwo == "" &&
		s.Operator == "")
}