diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 6dad3114333..5f23a2cf1b3 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -16,6 +16,7 @@ import ( "github.com/containerd/console" "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/selinux/go-selinux" "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" "golang.org/x/sys/unix" @@ -24,6 +25,7 @@ import ( "github.com/opencontainers/runc/internal/cmsg" "github.com/opencontainers/runc/internal/linux" "github.com/opencontainers/runc/internal/pathrs" + "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/capabilities" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" @@ -735,3 +737,25 @@ func setupPidfd(socket *os.File, initType string) error { } return unix.Close(pidFd) } + +// applyMACLabels configures the SELinux exec label and AppArmor profile to be +// applied on the next execve. +func applyMACLabels(config *initConfig) (closer func(), err error) { + // initialises the labeling system + selinux.GetEnabled() + + if config.ProcessLabel != "" { + if err := selinux.SetExecLabel(config.ProcessLabel); err != nil { + return nil, fmt.Errorf("can't set process label: %w", err) + } + closer = func() { + selinux.SetExecLabel("") //nolint: errcheck + } + } + + if err := apparmor.ApplyProfile(config.AppArmorProfile); err != nil { + return closer, fmt.Errorf("unable to apply apparmor profile: %w", err) + } + + return closer, nil +} diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index 7f7c0771754..75e54c5b5aa 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -11,7 +11,6 @@ import ( "golang.org/x/sys/unix" "github.com/opencontainers/runc/internal/linux" - "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/keys" "github.com/opencontainers/runc/libcontainer/seccomp" "github.com/opencontainers/runc/libcontainer/system" @@ -51,6 +50,14 @@ func (l *linuxSetnsInit) Init() error { } } + closer, err := applyMACLabels(l.config) + if closer != nil { + defer closer() + } + if err != nil { + return err + } + if l.config.CreateConsole { if err := setupConsole(l.consoleSocket, l.config, false); err != nil { return err @@ -98,12 +105,7 @@ func (l *linuxSetnsInit) Init() error { if err := syncParentReady(l.pipe); err != nil { return fmt.Errorf("sync ready: %w", err) } - if l.config.ProcessLabel != "" { - if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { - return err - } - defer selinux.SetExecLabel("") //nolint: errcheck - } + // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. @@ -119,9 +121,7 @@ func (l *linuxSetnsInit) Init() error { if err := finalizeNamespace(l.config); err != nil { return err } - if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { - return err - } + // Check for the arg early to make sure it exists. name, err := exec.LookPath(l.config.Args[0]) if err != nil { diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index 933c1de3441..9378e7c360b 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -14,7 +14,6 @@ import ( "github.com/opencontainers/runc/internal/linux" "github.com/opencontainers/runc/internal/pathrs" "github.com/opencontainers/runc/internal/sys" - "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/keys" "github.com/opencontainers/runc/libcontainer/seccomp" @@ -79,6 +78,14 @@ func (l *linuxStandardInit) Init() error { } } + closer, err := applyMACLabels(l.config) + if closer != nil { + defer closer() + } + if err != nil { + return err + } + if err := setupNetwork(l.config); err != nil { return err } @@ -86,10 +93,11 @@ func (l *linuxStandardInit) Init() error { return err } - // initialises the labeling system - selinux.GetEnabled() + if err := sys.WriteSysctls(l.config.Config.Sysctl); err != nil { + return err + } - err := prepareRootfs(l.pipe, l.config) + err = prepareRootfs(l.pipe, l.config) if err != nil { return err } @@ -129,13 +137,7 @@ func (l *linuxStandardInit) Init() error { return &os.SyscallError{Syscall: "setdomainname", Err: err} } } - if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { - return fmt.Errorf("unable to apply apparmor profile: %w", err) - } - if err := sys.WriteSysctls(l.config.Config.Sysctl); err != nil { - return err - } for _, path := range l.config.Config.ReadonlyPaths { if err := readonlyPath(path); err != nil { return fmt.Errorf("can't make %q read-only: %w", path, err) @@ -181,12 +183,6 @@ func (l *linuxStandardInit) Init() error { if err := syncParentReady(l.pipe); err != nil { return fmt.Errorf("sync ready: %w", err) } - if l.config.ProcessLabel != "" { - if err := selinux.SetExecLabel(l.config.ProcessLabel); err != nil { - return fmt.Errorf("can't set process label: %w", err) - } - defer selinux.SetExecLabel("") //nolint: errcheck - } // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible.