Skip to content

Commit 00b5c99

Browse files
committed
pkg/seccomp: simplify IsEnabled, update doc
Current implementation of seccomp.IsEnabled (rooted in runc) is not too good. First, it parses the whole /proc/self/status, adding each key: value pair into the map (lots of allocations and future work for garbage collector), when using a single key from that map. Second, the presence of "Seccomp" key in /proc/self/status merely means that kernel option CONFIG_SECCOMP is set, but there is a need to _also_ check for CONFIG_SECCOMP_FILTER (the code for which exists but never executed in case /proc/self/status has Seccomp key). Replace all this with a single call to prctl; see the long comment in the code for details. While at it, improve the IsEnabled documentation. NOTE historically, parsing /proc/self/status was added after a concern was raised in opencontainers/runc#471 that prctl(PR_GET_SECCOMP, ...) can result in the calling process being killed with SIGKILL. This is a valid concern, so the new code here does not use PR_GET_SECCOMP at all. Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 9efd3e2 commit 00b5c99

4 files changed

Lines changed: 33 additions & 147 deletions

File tree

pkg/seccomp/fixtures/proc_self_status

Lines changed: 0 additions & 47 deletions
This file was deleted.

pkg/seccomp/seccomp.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616

1717
package seccomp
1818

19-
// IsEnabled returns whether seccomp support is enabled
20-
// On Linux returns if the kernel has been configured to support seccomp.
21-
// From https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L86-L102
22-
// On non-Linux returns false
19+
// IsEnabled checks whether seccomp support is enabled. On Linux, it returns
20+
// true if the kernel has been configured to support seccomp (kernel options
21+
// CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are set). On non-Linux, it always
22+
// returns false.
2323
func IsEnabled() bool {
2424
return isEnabled()
2525
}

pkg/seccomp/seccomp_linux.go

Lines changed: 29 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -33,56 +33,37 @@
3333
package seccomp
3434

3535
import (
36-
"bufio"
37-
"os"
38-
"strings"
39-
4036
"golang.org/x/sys/unix"
4137
)
4238

43-
// isEnabled returns if the kernel has been configured to support seccomp.
44-
// From https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L86-L102
39+
// isEnabled returns whether the kernel has been configured to support seccomp
40+
// (including the check for CONFIG_SECCOMP_FILTER kernel option).
4541
func isEnabled() bool {
46-
// Try to read from /proc/self/status for kernels > 3.8
47-
s, err := parseStatusFile("/proc/self/status")
48-
if err != nil {
49-
// Check if Seccomp is supported, via CONFIG_SECCOMP.
50-
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
51-
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
52-
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
53-
return true
54-
}
55-
}
56-
return false
57-
}
58-
_, ok := s["Seccomp"]
59-
return ok
60-
}
61-
62-
// parseStatusFile is from https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L243-L268
63-
func parseStatusFile(path string) (map[string]string, error) {
64-
f, err := os.Open(path)
65-
if err != nil {
66-
return nil, err
67-
}
68-
defer f.Close()
69-
70-
s := bufio.NewScanner(f)
71-
status := make(map[string]string)
72-
73-
for s.Scan() {
74-
text := s.Text()
75-
parts := strings.Split(text, ":")
76-
77-
if len(parts) <= 1 {
78-
continue
79-
}
80-
81-
status[parts[0]] = parts[1]
82-
}
83-
if err := s.Err(); err != nil {
84-
return nil, err
85-
}
86-
87-
return status, nil
42+
// Excerpts from prctl(2), section ERRORS:
43+
//
44+
// EACCES
45+
// option is PR_SET_SECCOMP and arg2 is SECCOMP_MODE_FILTER, but
46+
// the process does not have the CAP_SYS_ADMIN capability or has
47+
// not set the no_new_privs attribute <...>.
48+
// <...>
49+
// EFAULT
50+
// option is PR_SET_SECCOMP, arg2 is SECCOMP_MODE_FILTER, the
51+
// system was built with CONFIG_SECCOMP_FILTER, and arg3 is an
52+
// invalid address.
53+
// <...>
54+
// EINVAL
55+
// option is PR_SET_SECCOMP or PR_GET_SECCOMP, and the kernel
56+
// was not configured with CONFIG_SECCOMP.
57+
//
58+
// EINVAL
59+
// option is PR_SET_SECCOMP, arg2 is SECCOMP_MODE_FILTER,
60+
// and the kernel was not configured with CONFIG_SECCOMP_FILTER.
61+
// <end of quote>
62+
//
63+
// Meaning, in case these kernel options are set (this is what we check
64+
// for here), we will get some other error (most probably EACCES or
65+
// EFAULT). IOW, EINVAL means "seccomp not supported", any other error
66+
// means it is supported.
67+
68+
return unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0) != unix.EINVAL
8869
}

pkg/seccomp/seccomp_linux_test.go

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)