Skip to content

Commit 3778ae6

Browse files
authored
Merge pull request #4337 from AkihiroSuda/fix-4328
Revert "libcontainer: seccomp: pass around *os.File for notifyfd"
2 parents 8a324d6 + a5e660c commit 3778ae6

File tree

5 files changed

+35
-33
lines changed

5 files changed

+35
-33
lines changed

libcontainer/init_linux.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,11 @@ func syncParentHooks(pipe *syncSocket) error {
451451

452452
// syncParentSeccomp sends the fd associated with the seccomp file descriptor
453453
// to the parent, and wait for the parent to do pidfd_getfd() to grab a copy.
454-
func syncParentSeccomp(pipe *syncSocket, seccompFd *os.File) error {
455-
if seccompFd == nil {
454+
func syncParentSeccomp(pipe *syncSocket, seccompFd int) error {
455+
if seccompFd == -1 {
456456
return nil
457457
}
458-
defer seccompFd.Close()
458+
defer unix.Close(seccompFd)
459459

460460
// Tell parent to grab our fd.
461461
//
@@ -466,7 +466,7 @@ func syncParentSeccomp(pipe *syncSocket, seccompFd *os.File) error {
466466
// before the parent gets the file descriptor would deadlock "runc init" if
467467
// we allowed it for SCMP_ACT_NOTIFY). See seccomp.InitSeccomp() for more
468468
// details.
469-
if err := writeSyncArg(pipe, procSeccomp, seccompFd.Fd()); err != nil {
469+
if err := writeSyncArg(pipe, procSeccomp, seccompFd); err != nil {
470470
return err
471471
}
472472
// Wait for parent to tell us they've grabbed the seccompfd.

libcontainer/seccomp/patchbpf/enosys_linux.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -704,32 +704,33 @@ func sysSeccompSetFilter(flags uint, filter []unix.SockFilter) (fd int, err erro
704704
// patches said filter to handle -ENOSYS in a much nicer manner than the
705705
// default libseccomp default action behaviour, and loads the patched filter
706706
// into the kernel for the current process.
707-
func PatchAndLoad(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (*os.File, error) {
707+
func PatchAndLoad(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (int, error) {
708708
// Generate a patched filter.
709709
fprog, err := enosysPatchFilter(config, filter)
710710
if err != nil {
711-
return nil, fmt.Errorf("error patching filter: %w", err)
711+
return -1, fmt.Errorf("error patching filter: %w", err)
712712
}
713713

714714
// Get the set of libseccomp flags set.
715715
seccompFlags, noNewPrivs, err := filterFlags(config, filter)
716716
if err != nil {
717-
return nil, fmt.Errorf("unable to fetch seccomp filter flags: %w", err)
717+
return -1, fmt.Errorf("unable to fetch seccomp filter flags: %w", err)
718718
}
719719

720720
// Set no_new_privs if it was requested, though in runc we handle
721721
// no_new_privs separately so warn if we hit this path.
722722
if noNewPrivs {
723723
logrus.Warnf("potentially misconfigured filter -- setting no_new_privs in seccomp path")
724724
if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil {
725-
return nil, fmt.Errorf("error enabling no_new_privs bit: %w", err)
725+
return -1, fmt.Errorf("error enabling no_new_privs bit: %w", err)
726726
}
727727
}
728728

729729
// Finally, load the filter.
730730
fd, err := sysSeccompSetFilter(seccompFlags, fprog)
731731
if err != nil {
732-
return nil, fmt.Errorf("error loading seccomp filter: %w", err)
732+
return -1, fmt.Errorf("error loading seccomp filter: %w", err)
733733
}
734-
return os.NewFile(uintptr(fd), "[seccomp filter]"), nil
734+
735+
return fd, nil
735736
}

libcontainer/seccomp/seccomp_linux.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package seccomp
55
import (
66
"errors"
77
"fmt"
8-
"os"
98

109
libseccomp "github.com/seccomp/libseccomp-golang"
1110
"github.com/sirupsen/logrus"
@@ -27,24 +26,25 @@ const (
2726
)
2827

2928
// InitSeccomp installs the seccomp filters to be used in the container as
30-
// specified in config. Returns the seccomp file descriptor if any of the
31-
// filters include a SCMP_ACT_NOTIFY action.
32-
func InitSeccomp(config *configs.Seccomp) (*os.File, error) {
29+
// specified in config.
30+
// Returns the seccomp file descriptor if any of the filters include a
31+
// SCMP_ACT_NOTIFY action, otherwise returns -1.
32+
func InitSeccomp(config *configs.Seccomp) (int, error) {
3333
if config == nil {
34-
return nil, errors.New("cannot initialize Seccomp - nil config passed")
34+
return -1, errors.New("cannot initialize Seccomp - nil config passed")
3535
}
3636

3737
defaultAction, err := getAction(config.DefaultAction, config.DefaultErrnoRet)
3838
if err != nil {
39-
return nil, errors.New("error initializing seccomp - invalid default action")
39+
return -1, errors.New("error initializing seccomp - invalid default action")
4040
}
4141

4242
// Ignore the error since pre-2.4 libseccomp is treated as API level 0.
4343
apiLevel, _ := libseccomp.GetAPI()
4444
for _, call := range config.Syscalls {
4545
if call.Action == configs.Notify {
4646
if apiLevel < 6 {
47-
return nil, fmt.Errorf("seccomp notify unsupported: API level: got %d, want at least 6. Please try with libseccomp >= 2.5.0 and Linux >= 5.7", apiLevel)
47+
return -1, fmt.Errorf("seccomp notify unsupported: API level: got %d, want at least 6. Please try with libseccomp >= 2.5.0 and Linux >= 5.7", apiLevel)
4848
}
4949

5050
// We can't allow the write syscall to notify to the seccomp agent.
@@ -60,36 +60,36 @@ func InitSeccomp(config *configs.Seccomp) (*os.File, error) {
6060
// agent allows those syscalls to proceed, initialization works just fine and the agent can
6161
// handle future read()/close() syscalls as it wanted.
6262
if call.Name == "write" {
63-
return nil, errors.New("SCMP_ACT_NOTIFY cannot be used for the write syscall")
63+
return -1, errors.New("SCMP_ACT_NOTIFY cannot be used for the write syscall")
6464
}
6565
}
6666
}
6767

6868
// See comment on why write is not allowed. The same reason applies, as this can mean handling write too.
6969
if defaultAction == libseccomp.ActNotify {
70-
return nil, errors.New("SCMP_ACT_NOTIFY cannot be used as default action")
70+
return -1, errors.New("SCMP_ACT_NOTIFY cannot be used as default action")
7171
}
7272

7373
filter, err := libseccomp.NewFilter(defaultAction)
7474
if err != nil {
75-
return nil, fmt.Errorf("error creating filter: %w", err)
75+
return -1, fmt.Errorf("error creating filter: %w", err)
7676
}
7777

7878
// Add extra architectures
7979
for _, arch := range config.Architectures {
8080
scmpArch, err := libseccomp.GetArchFromString(arch)
8181
if err != nil {
82-
return nil, fmt.Errorf("error validating Seccomp architecture: %w", err)
82+
return -1, fmt.Errorf("error validating Seccomp architecture: %w", err)
8383
}
8484
if err := filter.AddArch(scmpArch); err != nil {
85-
return nil, fmt.Errorf("error adding architecture to seccomp filter: %w", err)
85+
return -1, fmt.Errorf("error adding architecture to seccomp filter: %w", err)
8686
}
8787
}
8888

8989
// Add extra flags.
9090
for _, flag := range config.Flags {
9191
if err := setFlag(filter, flag); err != nil {
92-
return nil, err
92+
return -1, err
9393
}
9494
}
9595

@@ -109,24 +109,25 @@ func InitSeccomp(config *configs.Seccomp) (*os.File, error) {
109109

110110
// Unset no new privs bit
111111
if err := filter.SetNoNewPrivsBit(false); err != nil {
112-
return nil, fmt.Errorf("error setting no new privileges: %w", err)
112+
return -1, fmt.Errorf("error setting no new privileges: %w", err)
113113
}
114114

115115
// Add a rule for each syscall
116116
for _, call := range config.Syscalls {
117117
if call == nil {
118-
return nil, errors.New("encountered nil syscall while initializing Seccomp")
118+
return -1, errors.New("encountered nil syscall while initializing Seccomp")
119119
}
120120

121121
if err := matchCall(filter, call, defaultAction); err != nil {
122-
return nil, err
122+
return -1, err
123123
}
124124
}
125125

126126
seccompFd, err := patchbpf.PatchAndLoad(config, filter)
127127
if err != nil {
128-
return nil, fmt.Errorf("error loading seccomp filter into kernel: %w", err)
128+
return -1, fmt.Errorf("error loading seccomp filter into kernel: %w", err)
129129
}
130+
130131
return seccompFd, nil
131132
}
132133

libcontainer/seccomp/seccomp_unsupported.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package seccomp
44

55
import (
66
"errors"
7-
"os"
87

98
"github.com/opencontainers/runc/libcontainer/configs"
109
"github.com/opencontainers/runtime-spec/specs-go"
@@ -13,11 +12,11 @@ import (
1312
var ErrSeccompNotEnabled = errors.New("seccomp: config provided but seccomp not supported")
1413

1514
// InitSeccomp does nothing because seccomp is not supported.
16-
func InitSeccomp(config *configs.Seccomp) (*os.File, error) {
15+
func InitSeccomp(config *configs.Seccomp) (int, error) {
1716
if config != nil {
18-
return nil, ErrSeccompNotEnabled
17+
return -1, ErrSeccompNotEnabled
1918
}
20-
return nil, nil
19+
return -1, nil
2120
}
2221

2322
// FlagSupported tells if a provided seccomp flag is supported.

tests/integration/seccomp-notify.bats

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,17 @@ function scmp_act_notify_template() {
8383
}
8484

8585
# Test important syscalls (some might be executed by runc) work fine when handled by the agent. noNewPrivileges FALSE.
86+
# fcntl: https://github.com/opencontainers/runc/issues/4328
8687
@test "runc run [seccomp] (SCMP_ACT_NOTIFY important syscalls noNewPrivileges false)" {
87-
scmp_act_notify_template "/bin/true" false '"execve","openat","open","read","close"'
88+
scmp_act_notify_template "/bin/true" false '"execve","openat","open","read","close","fcntl"'
8889

8990
runc run test_busybox
9091
[ "$status" -eq 0 ]
9192
}
9293

9394
# Test important syscalls (some might be executed by runc) work fine when handled by the agent. noNewPrivileges TRUE.
9495
@test "runc run [seccomp] (SCMP_ACT_NOTIFY important syscalls noNewPrivileges true)" {
95-
scmp_act_notify_template "/bin/true" true '"execve","openat","open","read","close"'
96+
scmp_act_notify_template "/bin/true" true '"execve","openat","open","read","close","fcntl"'
9697

9798
runc run test_busybox
9899
[ "$status" -eq 0 ]

0 commit comments

Comments
 (0)