Skip to content

Commit 81c4ac2

Browse files
authored
Merge pull request #5256 from kolyshkin/seccomp-enabled
pkg/seccomp: simplify and speed up isEnabled
2 parents 56512cc + 3292ea5 commit 81c4ac2

4 files changed

Lines changed: 43 additions & 146 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: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,56 +33,48 @@
3333
package seccomp
3434

3535
import (
36-
"bufio"
37-
"os"
38-
"strings"
36+
"sync"
3937

4038
"golang.org/x/sys/unix"
4139
)
4240

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
45-
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-
}
41+
var (
42+
enabled bool
43+
enabledOnce sync.Once
44+
)
8645

87-
return status, nil
46+
// isEnabled returns whether the kernel has been configured to support seccomp
47+
// (including the check for CONFIG_SECCOMP_FILTER kernel option).
48+
func isEnabled() bool {
49+
// Excerpts from prctl(2), section ERRORS:
50+
//
51+
// EACCES
52+
// option is PR_SET_SECCOMP and arg2 is SECCOMP_MODE_FILTER, but
53+
// the process does not have the CAP_SYS_ADMIN capability or has
54+
// not set the no_new_privs attribute <...>.
55+
// <...>
56+
// EFAULT
57+
// option is PR_SET_SECCOMP, arg2 is SECCOMP_MODE_FILTER, the
58+
// system was built with CONFIG_SECCOMP_FILTER, and arg3 is an
59+
// invalid address.
60+
// <...>
61+
// EINVAL
62+
// option is PR_SET_SECCOMP or PR_GET_SECCOMP, and the kernel
63+
// was not configured with CONFIG_SECCOMP.
64+
//
65+
// EINVAL
66+
// option is PR_SET_SECCOMP, arg2 is SECCOMP_MODE_FILTER,
67+
// and the kernel was not configured with CONFIG_SECCOMP_FILTER.
68+
// <end of quote>
69+
//
70+
// Meaning, in case these kernel options are set (this is what we check
71+
// for here), we will get some other error (most probably EACCES or
72+
// EFAULT). IOW, EINVAL means "seccomp not supported", any other error
73+
// means it is supported.
74+
75+
enabledOnce.Do(func() {
76+
enabled = unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0) != unix.EINVAL
77+
})
78+
79+
return enabled
8880
}

pkg/seccomp/seccomp_linux_test.go

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

0 commit comments

Comments
 (0)