summaryrefslogtreecommitdiffhomepage
path: root/pkg/seccomp/seccomp.go
diff options
context:
space:
mode:
authorFabricio Voznika <fvoznika@google.com>2018-11-20 22:55:41 -0800
committerShentubot <shentubot@google.com>2018-11-20 22:56:51 -0800
commiteaac94d91c28b745c51c33dd352ed9bfdd671b8c (patch)
treee552c91970be74c3a315bb6aa5eea157cb153890 /pkg/seccomp/seccomp.go
parent5236b78242677612ac71b19cee85b3bf4cca4008 (diff)
Use RET_KILL_PROCESS if available in kernel
RET_KILL_THREAD doesn't work well for Go because it will kill only the offending thread and leave the process hanging. RET_TRAP can be masked out and it's not guaranteed to kill the process. RET_KILL_PROCESS is available since 4.14. For older kernel, continue to use RET_TRAP as this is the best option (likely to kill process, easy to debug). PiperOrigin-RevId: 222357867 Change-Id: Icc1d7d731274b16c2125b7a1ba4f7883fbdb2cbd
Diffstat (limited to 'pkg/seccomp/seccomp.go')
-rw-r--r--pkg/seccomp/seccomp.go52
1 files changed, 44 insertions, 8 deletions
diff --git a/pkg/seccomp/seccomp.go b/pkg/seccomp/seccomp.go
index 1dfbf749e..9d714d02d 100644
--- a/pkg/seccomp/seccomp.go
+++ b/pkg/seccomp/seccomp.go
@@ -33,17 +33,42 @@ const (
defaultLabel = "default_action"
)
+func actionName(a uint32) string {
+ switch a {
+ case linux.SECCOMP_RET_KILL_PROCESS:
+ return "kill process"
+ case linux.SECCOMP_RET_TRAP:
+ return "trap"
+ }
+ panic(fmt.Sprintf("invalid action: %d", a))
+}
+
// Install generates BPF code based on the set of syscalls provided. It only
-// allows syscalls that conform to the specification and generates SIGSYS
-// trap unless kill is set.
+// allows syscalls that conform to the specification. Syscalls that violate the
+// specification will trigger RET_KILL_PROCESS, except for the cases below.
+//
+// RET_TRAP is used in violations, instead of RET_KILL_PROCESS, in the
+// following cases:
+// 1. Kernel doesn't support RET_KILL_PROCESS: RET_KILL_THREAD only kills the
+// offending thread and often keeps the sentry hanging.
+// 2. Debug: RET_TRAP generates a panic followed by a stack trace which is
+// much easier to debug then RET_KILL_PROCESS which can't be caught.
//
-// This is a convenience wrapper around BuildProgram and SetFilter.
-func Install(rules SyscallRules, kill bool) error {
- log.Infof("Installing seccomp filters for %d syscalls (kill=%t)", len(rules), kill)
- defaultAction := uint32(linux.SECCOMP_RET_TRAP)
- if kill {
- defaultAction = uint32(linux.SECCOMP_RET_KILL)
+// Be aware that RET_TRAP sends SIGSYS to the process and it may be ignored,
+// making it possible for the process to continue running after a violation.
+// However, it will leave a SECCOMP audit event trail behind. In any case, the
+// syscall is still blocked from executing.
+func Install(rules SyscallRules) error {
+ defaultAction, err := defaultAction()
+ if err != nil {
+ return err
}
+
+ // Uncomment to get stack trace when there is a violation.
+ // defaultAction = uint32(linux.SECCOMP_RET_TRAP)
+
+ log.Infof("Installing seccomp filters for %d syscalls (action=%s)", len(rules), actionName(defaultAction))
+
instrs, err := BuildProgram([]RuleSet{
RuleSet{
Rules: rules,
@@ -70,6 +95,17 @@ func Install(rules SyscallRules, kill bool) error {
return nil
}
+func defaultAction() (uint32, error) {
+ available, err := isKillProcessAvailable()
+ if err != nil {
+ return 0, err
+ }
+ if available {
+ return uint32(linux.SECCOMP_RET_KILL_PROCESS), nil
+ }
+ return uint32(linux.SECCOMP_RET_TRAP), nil
+}
+
// RuleSet is a set of rules and associated action.
type RuleSet struct {
Rules SyscallRules