podman

Форк
0
205 строк · 6.5 Кб
1
//go:build linux && seccomp
2
// +build linux,seccomp
3

4
package chroot
5

6
import (
7
	"fmt"
8
	"os"
9

10
	"github.com/containers/common/pkg/seccomp"
11
	specs "github.com/opencontainers/runtime-spec/specs-go"
12
	libseccomp "github.com/seccomp/libseccomp-golang"
13
	"github.com/sirupsen/logrus"
14
)
15

16
const seccompAvailable = true
17

18
// setSeccomp sets the seccomp filter for ourselves and any processes that we'll start.
19
func setSeccomp(spec *specs.Spec) error {
20
	logrus.Debugf("setting seccomp configuration")
21
	if spec.Linux.Seccomp == nil {
22
		return nil
23
	}
24
	mapAction := func(specAction specs.LinuxSeccompAction, errnoRet *uint) libseccomp.ScmpAction {
25
		switch specAction {
26
		case specs.ActKill:
27
			return libseccomp.ActKillThread
28
		case specs.ActTrap:
29
			return libseccomp.ActTrap
30
		case specs.ActErrno:
31
			action := libseccomp.ActErrno
32
			if errnoRet != nil {
33
				action = action.SetReturnCode(int16(*errnoRet))
34
			}
35
			return action
36
		case specs.ActTrace:
37
			return libseccomp.ActTrace
38
		case specs.ActAllow:
39
			return libseccomp.ActAllow
40
		case specs.ActLog:
41
			return libseccomp.ActLog
42
		case specs.ActKillProcess:
43
			return libseccomp.ActKillProcess
44
		default:
45
			logrus.Errorf("unmappable action %v", specAction)
46
		}
47
		return libseccomp.ActInvalid
48
	}
49
	mapArch := func(specArch specs.Arch) libseccomp.ScmpArch {
50
		switch specArch {
51
		case specs.ArchX86:
52
			return libseccomp.ArchX86
53
		case specs.ArchX86_64:
54
			return libseccomp.ArchAMD64
55
		case specs.ArchX32:
56
			return libseccomp.ArchX32
57
		case specs.ArchARM:
58
			return libseccomp.ArchARM
59
		case specs.ArchAARCH64:
60
			return libseccomp.ArchARM64
61
		case specs.ArchMIPS:
62
			return libseccomp.ArchMIPS
63
		case specs.ArchMIPS64:
64
			return libseccomp.ArchMIPS64
65
		case specs.ArchMIPS64N32:
66
			return libseccomp.ArchMIPS64N32
67
		case specs.ArchMIPSEL:
68
			return libseccomp.ArchMIPSEL
69
		case specs.ArchMIPSEL64:
70
			return libseccomp.ArchMIPSEL64
71
		case specs.ArchMIPSEL64N32:
72
			return libseccomp.ArchMIPSEL64N32
73
		case specs.ArchPPC:
74
			return libseccomp.ArchPPC
75
		case specs.ArchPPC64:
76
			return libseccomp.ArchPPC64
77
		case specs.ArchPPC64LE:
78
			return libseccomp.ArchPPC64LE
79
		case specs.ArchS390:
80
			return libseccomp.ArchS390
81
		case specs.ArchS390X:
82
			return libseccomp.ArchS390X
83
		case specs.ArchPARISC:
84
			return libseccomp.ArchPARISC
85
		case specs.ArchPARISC64:
86
			return libseccomp.ArchPARISC64
87
		case specs.ArchRISCV64:
88
			return libseccomp.ArchRISCV64
89
		default:
90
			logrus.Errorf("unmappable arch %v", specArch)
91
		}
92
		return libseccomp.ArchInvalid
93
	}
94
	mapOp := func(op specs.LinuxSeccompOperator) libseccomp.ScmpCompareOp {
95
		switch op {
96
		case specs.OpNotEqual:
97
			return libseccomp.CompareNotEqual
98
		case specs.OpLessThan:
99
			return libseccomp.CompareLess
100
		case specs.OpLessEqual:
101
			return libseccomp.CompareLessOrEqual
102
		case specs.OpEqualTo:
103
			return libseccomp.CompareEqual
104
		case specs.OpGreaterEqual:
105
			return libseccomp.CompareGreaterEqual
106
		case specs.OpGreaterThan:
107
			return libseccomp.CompareGreater
108
		case specs.OpMaskedEqual:
109
			return libseccomp.CompareMaskedEqual
110
		default:
111
			logrus.Errorf("unmappable op %v", op)
112
		}
113
		return libseccomp.CompareInvalid
114
	}
115

116
	filter, err := libseccomp.NewFilter(mapAction(spec.Linux.Seccomp.DefaultAction, spec.Linux.Seccomp.DefaultErrnoRet))
117
	if err != nil {
118
		return fmt.Errorf("creating seccomp filter with default action %q: %w", spec.Linux.Seccomp.DefaultAction, err)
119
	}
120
	for _, arch := range spec.Linux.Seccomp.Architectures {
121
		if err = filter.AddArch(mapArch(arch)); err != nil {
122
			return fmt.Errorf("adding architecture %q(%q) to seccomp filter: %w", arch, mapArch(arch), err)
123
		}
124
	}
125
	for _, rule := range spec.Linux.Seccomp.Syscalls {
126
		scnames := make(map[libseccomp.ScmpSyscall]string)
127
		for _, name := range rule.Names {
128
			scnum, err := libseccomp.GetSyscallFromName(name)
129
			if err != nil {
130
				logrus.Debugf("error mapping syscall %q to a syscall, ignoring %q rule for %q", name, rule.Action, name)
131
				continue
132
			}
133
			scnames[scnum] = name
134
		}
135
		for scnum := range scnames {
136
			if len(rule.Args) == 0 {
137
				if err = filter.AddRule(scnum, mapAction(rule.Action, rule.ErrnoRet)); err != nil {
138
					return fmt.Errorf("adding a rule (%q:%q) to seccomp filter: %w", scnames[scnum], rule.Action, err)
139
				}
140
				continue
141
			}
142
			var conditions []libseccomp.ScmpCondition
143
			opsAreAllEquality := true
144
			for _, arg := range rule.Args {
145
				condition, err := libseccomp.MakeCondition(arg.Index, mapOp(arg.Op), arg.Value, arg.ValueTwo)
146
				if err != nil {
147
					return fmt.Errorf("building a seccomp condition %d:%v:%d:%d: %w", arg.Index, arg.Op, arg.Value, arg.ValueTwo, err)
148
				}
149
				if arg.Op != specs.OpEqualTo {
150
					opsAreAllEquality = false
151
				}
152
				conditions = append(conditions, condition)
153
			}
154
			if err = filter.AddRuleConditional(scnum, mapAction(rule.Action, rule.ErrnoRet), conditions); err != nil {
155
				// Okay, if the rules specify multiple equality
156
				// checks, assume someone thought that they
157
				// were OR'd, when in fact they're ordinarily
158
				// supposed to be AND'd.  Break them up into
159
				// different rules to get that OR effect.
160
				if len(rule.Args) > 1 && opsAreAllEquality && err.Error() == "two checks on same syscall argument" {
161
					for i := range conditions {
162
						if err = filter.AddRuleConditional(scnum, mapAction(rule.Action, rule.ErrnoRet), conditions[i:i+1]); err != nil {
163
							return fmt.Errorf("adding a conditional rule (%q:%q[%d]) to seccomp filter: %w", scnames[scnum], rule.Action, i, err)
164
						}
165
					}
166
				} else {
167
					return fmt.Errorf("adding a conditional rule (%q:%q) to seccomp filter: %w", scnames[scnum], rule.Action, err)
168
				}
169
			}
170
		}
171
	}
172
	if err = filter.SetNoNewPrivsBit(spec.Process.NoNewPrivileges); err != nil {
173
		return fmt.Errorf("setting no-new-privileges bit to %v: %w", spec.Process.NoNewPrivileges, err)
174
	}
175
	err = filter.Load()
176
	filter.Release()
177
	if err != nil {
178
		return fmt.Errorf("activating seccomp filter: %w", err)
179
	}
180
	return nil
181
}
182

183
func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
184
	switch seccompProfilePath {
185
	case "unconfined":
186
		spec.Linux.Seccomp = nil
187
	case "":
188
		seccompConfig, err := seccomp.GetDefaultProfile(spec)
189
		if err != nil {
190
			return fmt.Errorf("loading default seccomp profile failed: %w", err)
191
		}
192
		spec.Linux.Seccomp = seccompConfig
193
	default:
194
		seccompProfile, err := os.ReadFile(seccompProfilePath)
195
		if err != nil {
196
			return fmt.Errorf("opening seccomp profile failed: %w", err)
197
		}
198
		seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
199
		if err != nil {
200
			return fmt.Errorf("loading seccomp profile (%s) failed: %w", seccompProfilePath, err)
201
		}
202
		spec.Linux.Seccomp = seccompConfig
203
	}
204
	return nil
205
}
206

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.