Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion libcontainer/seccomp/seccomp_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func InitSeccomp(config *configs.Seccomp) (int, error) {

defaultAction, err := getAction(config.DefaultAction, config.DefaultErrnoRet)
if err != nil {
return -1, errors.New("error initializing seccomp - invalid default action")
return -1, fmt.Errorf("error initializing seccomp - invalid default action: %w", err)
}

// Ignore the error since pre-2.4 libseccomp is treated as API level 0.
Expand Down Expand Up @@ -197,6 +197,13 @@ func FlagSupported(flag specs.LinuxSeccompFlag) error {

// Convert Libcontainer Action to Libseccomp ScmpAction
func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error) {
if errnoRet != nil && act != configs.Errno && act != configs.Trace {
switch act {
case configs.Kill, configs.Trap, configs.Allow, configs.Log, configs.Notify, configs.KillThread, configs.KillProcess:
return libseccomp.ActInvalid, errors.New("errnoRet is only supported for SCMP_ACT_ERRNO and SCMP_ACT_TRACE")
}
}

switch act {
case configs.Kill, configs.KillThread:
return libseccomp.ActKillThread, nil
Expand Down
80 changes: 80 additions & 0 deletions libcontainer/seccomp/seccomp_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//go:build cgo && seccomp

package seccomp

import (
"strings"
"testing"

"github.com/opencontainers/runc/libcontainer/configs"
)

func TestGetActionErrnoRet(t *testing.T) {
errnoRet := uint(1)
tests := []struct {
name string
action configs.Action
wantErr bool
}{
{name: "kill", action: configs.Kill, wantErr: true},
{name: "errno", action: configs.Errno},
{name: "trap", action: configs.Trap, wantErr: true},
{name: "allow", action: configs.Allow, wantErr: true},
{name: "trace", action: configs.Trace},
{name: "log", action: configs.Log, wantErr: true},
{name: "notify", action: configs.Notify, wantErr: true},
{name: "kill thread", action: configs.KillThread, wantErr: true},
{name: "kill process", action: configs.KillProcess, wantErr: true},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := getAction(tt.action, &errnoRet)
if tt.wantErr && err == nil {
t.Fatal("expected errnoRet to be rejected for this action")
}
if !tt.wantErr && err != nil {
t.Fatalf("unexpected error: %v", err)
}
})
}
}

func TestInitSeccompRejectsErrnoRetForAllow(t *testing.T) {
errnoRet := uint(1)
tests := []struct {
name string
config *configs.Seccomp
}{
{
name: "default action",
config: &configs.Seccomp{
DefaultAction: configs.Allow,
DefaultErrnoRet: &errnoRet,
},
},
{
name: "syscall action",
config: &configs.Seccomp{
DefaultAction: configs.Allow,
Syscalls: []*configs.Syscall{{
Name: "getpid",
Action: configs.Allow,
ErrnoRet: &errnoRet,
}},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := InitSeccomp(tt.config)
if err == nil {
t.Fatal("expected errnoRet with SCMP_ACT_ALLOW to be rejected")
}
if !strings.Contains(err.Error(), "errnoRet is only supported") {
t.Fatalf("unexpected error: %v", err)
}
})
}
}