1
2
3
4 package integration
5
6 import (
7 "strings"
8 "syscall"
9 "testing"
10
11 "github.com/opencontainers/runc/libcontainer"
12 "github.com/opencontainers/runc/libcontainer/configs"
13 libseccomp "github.com/seccomp/libseccomp-golang"
14 )
15
16 func TestSeccompDenySyslogWithErrno(t *testing.T) {
17 if testing.Short() {
18 return
19 }
20
21 errnoRet := uint(syscall.ESRCH)
22
23 config := newTemplateConfig(t, nil)
24 config.Seccomp = &configs.Seccomp{
25 DefaultAction: configs.Allow,
26 Syscalls: []*configs.Syscall{
27 {
28 Name: "syslog",
29 Action: configs.Errno,
30 ErrnoRet: &errnoRet,
31 },
32 },
33 }
34
35 container, err := newContainer(t, config)
36 ok(t, err)
37 defer container.Destroy()
38
39 buffers := newStdBuffers()
40 pwd := &libcontainer.Process{
41 Cwd: "/",
42 Args: []string{"dmesg"},
43 Env: standardEnvironment,
44 Stdin: buffers.Stdin,
45 Stdout: buffers.Stdout,
46 Stderr: buffers.Stderr,
47 Init: true,
48 }
49
50 err = container.Run(pwd)
51 ok(t, err)
52 ps, err := pwd.Wait()
53 if err == nil {
54 t.Fatal("Expecting error (negative return code); instead exited cleanly!")
55 }
56
57 var exitCode int
58 status := ps.Sys().(syscall.WaitStatus)
59 if status.Exited() {
60 exitCode = status.ExitStatus()
61 } else if status.Signaled() {
62 exitCode = -int(status.Signal())
63 } else {
64 t.Fatalf("Unrecognized exit reason!")
65 }
66
67 if exitCode == 0 {
68 t.Fatalf("dmesg should fail with negative exit code, instead got %d!", exitCode)
69 }
70
71 expected := "dmesg: klogctl: No such process"
72 actual := strings.Trim(buffers.Stderr.String(), "\n")
73 if actual != expected {
74 t.Fatalf("Expected output %s but got %s\n", expected, actual)
75 }
76 }
77
78 func TestSeccompDenySyslog(t *testing.T) {
79 if testing.Short() {
80 return
81 }
82
83 config := newTemplateConfig(t, nil)
84 config.Seccomp = &configs.Seccomp{
85 DefaultAction: configs.Allow,
86 Syscalls: []*configs.Syscall{
87 {
88 Name: "syslog",
89 Action: configs.Errno,
90 },
91 },
92 }
93
94 container, err := newContainer(t, config)
95 ok(t, err)
96 defer container.Destroy()
97
98 buffers := newStdBuffers()
99 pwd := &libcontainer.Process{
100 Cwd: "/",
101 Args: []string{"dmesg"},
102 Env: standardEnvironment,
103 Stdin: buffers.Stdin,
104 Stdout: buffers.Stdout,
105 Stderr: buffers.Stderr,
106 Init: true,
107 }
108
109 err = container.Run(pwd)
110 ok(t, err)
111 ps, err := pwd.Wait()
112 if err == nil {
113 t.Fatal("Expecting error (negative return code); instead exited cleanly!")
114 }
115
116 var exitCode int
117 status := ps.Sys().(syscall.WaitStatus)
118 if status.Exited() {
119 exitCode = status.ExitStatus()
120 } else if status.Signaled() {
121 exitCode = -int(status.Signal())
122 } else {
123 t.Fatalf("Unrecognized exit reason!")
124 }
125
126 if exitCode == 0 {
127 t.Fatalf("dmesg should fail with negative exit code, instead got %d!", exitCode)
128 }
129
130 expected := "dmesg: klogctl: Operation not permitted"
131 actual := strings.Trim(buffers.Stderr.String(), "\n")
132 if actual != expected {
133 t.Fatalf("Expected output %s but got %s\n", expected, actual)
134 }
135 }
136
137 func TestSeccompPermitWriteConditional(t *testing.T) {
138 if testing.Short() {
139 return
140 }
141
142 config := newTemplateConfig(t, nil)
143 config.Seccomp = &configs.Seccomp{
144 DefaultAction: configs.Allow,
145 Syscalls: []*configs.Syscall{
146 {
147 Name: "write",
148 Action: configs.Errno,
149 Args: []*configs.Arg{
150 {
151 Index: 0,
152 Value: 2,
153 Op: configs.EqualTo,
154 },
155 },
156 },
157 },
158 }
159
160 container, err := newContainer(t, config)
161 ok(t, err)
162 defer container.Destroy()
163
164 buffers := newStdBuffers()
165 dmesg := &libcontainer.Process{
166 Cwd: "/",
167 Args: []string{"busybox", "ls", "/"},
168 Env: standardEnvironment,
169 Stdin: buffers.Stdin,
170 Stdout: buffers.Stdout,
171 Stderr: buffers.Stderr,
172 Init: true,
173 }
174
175 err = container.Run(dmesg)
176 ok(t, err)
177 if _, err := dmesg.Wait(); err != nil {
178 t.Fatalf("%s: %s", err, buffers.Stderr)
179 }
180 }
181
182 func TestSeccompDenyWriteConditional(t *testing.T) {
183 if testing.Short() {
184 return
185 }
186
187
188
189 major, minor, micro := libseccomp.GetLibraryVersion()
190 if (major == 2 && minor < 2) || (major == 2 && minor == 2 && micro < 1) {
191 return
192 }
193
194 config := newTemplateConfig(t, nil)
195 config.Seccomp = &configs.Seccomp{
196 DefaultAction: configs.Allow,
197 Syscalls: []*configs.Syscall{
198 {
199 Name: "write",
200 Action: configs.Errno,
201 Args: []*configs.Arg{
202 {
203 Index: 0,
204 Value: 2,
205 Op: configs.EqualTo,
206 },
207 },
208 },
209 },
210 }
211
212 container, err := newContainer(t, config)
213 ok(t, err)
214 defer container.Destroy()
215
216 buffers := newStdBuffers()
217 dmesg := &libcontainer.Process{
218 Cwd: "/",
219 Args: []string{"busybox", "ls", "does_not_exist"},
220 Env: standardEnvironment,
221 Stdin: buffers.Stdin,
222 Stdout: buffers.Stdout,
223 Stderr: buffers.Stderr,
224 Init: true,
225 }
226
227 err = container.Run(dmesg)
228 ok(t, err)
229
230 ps, err := dmesg.Wait()
231 if err == nil {
232 t.Fatal("Expecting negative return, instead got 0!")
233 }
234
235 var exitCode int
236 status := ps.Sys().(syscall.WaitStatus)
237 if status.Exited() {
238 exitCode = status.ExitStatus()
239 } else if status.Signaled() {
240 exitCode = -int(status.Signal())
241 } else {
242 t.Fatalf("Unrecognized exit reason!")
243 }
244
245 if exitCode == 0 {
246 t.Fatalf("Busybox should fail with negative exit code, instead got %d!", exitCode)
247 }
248
249
250 expected := ""
251 actual := strings.Trim(buffers.Stderr.String(), "\n")
252 if actual != expected {
253 t.Fatalf("Expected output %s but got %s\n", expected, actual)
254 }
255 }
256
257 func TestSeccompPermitWriteMultipleConditions(t *testing.T) {
258 if testing.Short() {
259 return
260 }
261
262 config := newTemplateConfig(t, nil)
263 config.Seccomp = &configs.Seccomp{
264 DefaultAction: configs.Allow,
265 Syscalls: []*configs.Syscall{
266 {
267 Name: "write",
268 Action: configs.Errno,
269 Args: []*configs.Arg{
270 {
271 Index: 0,
272 Value: 2,
273 Op: configs.EqualTo,
274 },
275 {
276 Index: 2,
277 Value: 0,
278 Op: configs.NotEqualTo,
279 },
280 },
281 },
282 },
283 }
284
285 buffers := runContainerOk(t, config, "ls", "/")
286
287
288 if len(buffers.Stdout.String()) == 0 {
289 t.Fatalf("Nothing was written to stdout, write call failed!\n")
290 }
291 }
292
293 func TestSeccompDenyWriteMultipleConditions(t *testing.T) {
294 if testing.Short() {
295 return
296 }
297
298
299
300 major, minor, micro := libseccomp.GetLibraryVersion()
301 if (major == 2 && minor < 2) || (major == 2 && minor == 2 && micro < 1) {
302 return
303 }
304
305 config := newTemplateConfig(t, nil)
306 config.Seccomp = &configs.Seccomp{
307 DefaultAction: configs.Allow,
308 Syscalls: []*configs.Syscall{
309 {
310 Name: "write",
311 Action: configs.Errno,
312 Args: []*configs.Arg{
313 {
314 Index: 0,
315 Value: 2,
316 Op: configs.EqualTo,
317 },
318 {
319 Index: 2,
320 Value: 0,
321 Op: configs.NotEqualTo,
322 },
323 },
324 },
325 },
326 }
327
328 buffers, exitCode, err := runContainer(t, config, "ls", "/does_not_exist")
329 if err == nil {
330 t.Fatalf("Expecting error return, instead got 0")
331 }
332 if exitCode == 0 {
333 t.Fatalf("Busybox should fail with negative exit code, instead got %d!", exitCode)
334 }
335
336 expected := ""
337 actual := strings.Trim(buffers.Stderr.String(), "\n")
338 if actual != expected {
339 t.Fatalf("Expected output %s but got %s\n", expected, actual)
340 }
341 }
342
343 func TestSeccompMultipleConditionSameArgDeniesStdout(t *testing.T) {
344 if testing.Short() {
345 return
346 }
347
348
349 config := newTemplateConfig(t, nil)
350 config.Seccomp = &configs.Seccomp{
351 DefaultAction: configs.Allow,
352 Syscalls: []*configs.Syscall{
353 {
354 Name: "write",
355 Action: configs.Errno,
356 Args: []*configs.Arg{
357 {
358 Index: 0,
359 Value: 1,
360 Op: configs.EqualTo,
361 },
362 {
363 Index: 0,
364 Value: 2,
365 Op: configs.EqualTo,
366 },
367 },
368 },
369 },
370 }
371
372 buffers := runContainerOk(t, config, "ls", "/")
373
374 if len(buffers.Stdout.String()) != 0 {
375 t.Fatalf("Something was written to stdout, write call succeeded!\n")
376 }
377 }
378
379 func TestSeccompMultipleConditionSameArgDeniesStderr(t *testing.T) {
380 if testing.Short() {
381 return
382 }
383
384
385 config := newTemplateConfig(t, nil)
386 config.Seccomp = &configs.Seccomp{
387 DefaultAction: configs.Allow,
388 Syscalls: []*configs.Syscall{
389 {
390 Name: "write",
391 Action: configs.Errno,
392 Args: []*configs.Arg{
393 {
394 Index: 0,
395 Value: 1,
396 Op: configs.EqualTo,
397 },
398 {
399 Index: 0,
400 Value: 2,
401 Op: configs.EqualTo,
402 },
403 },
404 },
405 },
406 }
407
408 buffers, exitCode, err := runContainer(t, config, "ls", "/does_not_exist")
409 if err == nil {
410 t.Fatalf("Expecting error return, instead got 0")
411 }
412 if exitCode == 0 {
413 t.Fatalf("Busybox should fail with negative exit code, instead got %d!", exitCode)
414 }
415
416 if len(buffers.Stderr.String()) != 0 {
417 t.Fatalf("Something was written to stderr, write call succeeded!\n")
418 }
419 }
420
View as plain text