Skip to content

Commit 80ee9e5

Browse files
author
Mrunal Patel
authored
Merge pull request #1616 from mheon/seccomp_fix_breakage
Fix breaking change in Seccomp profile behavior
2 parents c05f636 + e9193ba commit 80ee9e5

File tree

2 files changed

+135
-8
lines changed

2 files changed

+135
-8
lines changed

libcontainer/integration/seccomp_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,99 @@ func TestSeccompDenyWriteMultipleConditions(t *testing.T) {
321321
t.Fatalf("Expected output %s but got %s\n", expected, actual)
322322
}
323323
}
324+
325+
func TestSeccompMultipleConditionSameArgDeniesStdout(t *testing.T) {
326+
if testing.Short() {
327+
return
328+
}
329+
330+
rootfs, err := newRootfs()
331+
if err != nil {
332+
t.Fatal(err)
333+
}
334+
defer remove(rootfs)
335+
336+
// Prevent writing to both stdout and stderr
337+
config := newTemplateConfig(rootfs)
338+
config.Seccomp = &configs.Seccomp{
339+
DefaultAction: configs.Allow,
340+
Syscalls: []*configs.Syscall{
341+
{
342+
Name: "write",
343+
Action: configs.Errno,
344+
Args: []*configs.Arg{
345+
{
346+
Index: 0,
347+
Value: 1,
348+
Op: configs.EqualTo,
349+
},
350+
{
351+
Index: 0,
352+
Value: 2,
353+
Op: configs.EqualTo,
354+
},
355+
},
356+
},
357+
},
358+
}
359+
360+
buffers, exitCode, err := runContainer(config, "", "ls", "/")
361+
if err != nil {
362+
t.Fatalf("%s: %s", buffers, err)
363+
}
364+
if exitCode != 0 {
365+
t.Fatalf("exit code not 0. code %d buffers %s", exitCode, buffers)
366+
}
367+
// Verify that nothing was printed
368+
if len(buffers.Stdout.String()) != 0 {
369+
t.Fatalf("Something was written to stdout, write call succeeded!\n")
370+
}
371+
}
372+
373+
func TestSeccompMultipleConditionSameArgDeniesStderr(t *testing.T) {
374+
if testing.Short() {
375+
return
376+
}
377+
378+
rootfs, err := newRootfs()
379+
if err != nil {
380+
t.Fatal(err)
381+
}
382+
defer remove(rootfs)
383+
384+
// Prevent writing to both stdout and stderr
385+
config := newTemplateConfig(rootfs)
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(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+
// Verify nothing was printed
416+
if len(buffers.Stderr.String()) != 0 {
417+
t.Fatalf("Something was written to stderr, write call succeeded!\n")
418+
}
419+
}

libcontainer/seccomp/seccomp_linux.go

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ var (
2222
actErrno = libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM))
2323
)
2424

25+
const (
26+
// Linux system calls can have at most 6 arguments
27+
syscallMaxArguments int = 6
28+
)
29+
2530
// Filters given syscalls in a container, preventing them from being used
2631
// Started in the container init process, and carried over to all child processes
2732
// Setns calls, however, require a separate invocation, as they are not children
@@ -45,11 +50,11 @@ func InitSeccomp(config *configs.Seccomp) error {
4550
for _, arch := range config.Architectures {
4651
scmpArch, err := libseccomp.GetArchFromString(arch)
4752
if err != nil {
48-
return err
53+
return fmt.Errorf("error validating Seccomp architecture: %s", err)
4954
}
5055

5156
if err := filter.AddArch(scmpArch); err != nil {
52-
return err
57+
return fmt.Errorf("error adding architecture to seccomp filter: %s", err)
5358
}
5459
}
5560

@@ -170,29 +175,55 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error {
170175
// Convert the call's action to the libseccomp equivalent
171176
callAct, err := getAction(call.Action)
172177
if err != nil {
173-
return err
178+
return fmt.Errorf("action in seccomp profile is invalid: %s", err)
174179
}
175180

176181
// Unconditional match - just add the rule
177182
if len(call.Args) == 0 {
178183
if err = filter.AddRule(callNum, callAct); err != nil {
179-
return err
184+
return fmt.Errorf("error adding seccomp filter rule for syscall %s: %s", call.Name, err)
180185
}
181186
} else {
182-
// Conditional match - convert the per-arg rules into library format
187+
// If two or more arguments have the same condition,
188+
// Revert to old behavior, adding each condition as a separate rule
189+
argCounts := make([]uint, syscallMaxArguments)
183190
conditions := []libseccomp.ScmpCondition{}
184191

185192
for _, cond := range call.Args {
186193
newCond, err := getCondition(cond)
187194
if err != nil {
188-
return err
195+
return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %s", call.Name, err)
189196
}
190197

198+
argCounts[cond.Index] += 1
199+
191200
conditions = append(conditions, newCond)
192201
}
193202

194-
if err = filter.AddRuleConditional(callNum, callAct, conditions); err != nil {
195-
return err
203+
hasMultipleArgs := false
204+
for _, count := range argCounts {
205+
if count > 1 {
206+
hasMultipleArgs = true
207+
break
208+
}
209+
}
210+
211+
if hasMultipleArgs {
212+
// Revert to old behavior
213+
// Add each condition attached to a separate rule
214+
for _, cond := range conditions {
215+
condArr := []libseccomp.ScmpCondition{cond}
216+
217+
if err = filter.AddRuleConditional(callNum, callAct, condArr); err != nil {
218+
return fmt.Errorf("error adding seccomp rule for syscall %s: %s", call.Name, err)
219+
}
220+
}
221+
} else {
222+
// No conditions share same argument
223+
// Use new, proper behavior
224+
if err = filter.AddRuleConditional(callNum, callAct, conditions); err != nil {
225+
return fmt.Errorf("error adding seccomp rule for syscall %s: %s", call.Name, err)
226+
}
196227
}
197228
}
198229

0 commit comments

Comments
 (0)