From f4f2c05c4df42be398d0486a8bd3c4152e54e797 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Fri, 17 Jan 2020 10:45:56 -0500 Subject: [PATCH] chroot: handle slightly broken seccomp defaults When a seccomp rule includes multiple equality checks for the same argument for a syscall, they can never ALL be satisfied. Because that's how they're supposed to be treated, libseccomp returns an error when we try to add them as part of the same conditional rule. Try to detect this exact case, and if we detect it, treat each condition as its own rule. Signed-off-by: Nalin Dahyabhai --- chroot/seccomp.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/chroot/seccomp.go b/chroot/seccomp.go index f2c55017f54..12a9b003231 100644 --- a/chroot/seccomp.go +++ b/chroot/seccomp.go @@ -3,7 +3,7 @@ package chroot import ( - "github.com/opencontainers/runtime-spec/specs-go" + specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" libseccomp "github.com/seccomp/libseccomp-golang" "github.com/sirupsen/logrus" @@ -118,15 +118,32 @@ func setSeccomp(spec *specs.Spec) error { continue } var conditions []libseccomp.ScmpCondition + opsAreAllEquality := true for _, arg := range rule.Args { condition, err := libseccomp.MakeCondition(arg.Index, mapOp(arg.Op), arg.Value, arg.ValueTwo) if err != nil { return errors.Wrapf(err, "error building a seccomp condition %d:%v:%d:%d", arg.Index, arg.Op, arg.Value, arg.ValueTwo) } + if arg.Op != specs.OpEqualTo { + opsAreAllEquality = false + } conditions = append(conditions, condition) } if err = filter.AddRuleConditional(scnum, mapAction(rule.Action), conditions); err != nil { - return errors.Wrapf(err, "error adding a conditional rule (%q:%q) to seccomp filter", scnames[scnum], rule.Action) + // Okay, if the rules specify multiple equality + // checks, assume someone thought that they + // were OR'd, when in fact they're ordinarily + // supposed to be AND'd. Break them up into + // different rules to get that OR effect. + if len(rule.Args) > 1 && opsAreAllEquality && err.Error() == "two checks on same syscall argument" { + for i := range conditions { + if err = filter.AddRuleConditional(scnum, mapAction(rule.Action), conditions[i:i+1]); err != nil { + return errors.Wrapf(err, "error adding a conditional rule (%q:%q[%d]) to seccomp filter", scnames[scnum], rule.Action, i) + } + } + } else { + return errors.Wrapf(err, "error adding a conditional rule (%q:%q) to seccomp filter", scnames[scnum], rule.Action) + } } } }