You've already forked runc
mirror of
https://github.com/opencontainers/runc.git
synced 2026-10-23 19:49:01 +03:00
libct: don't reset selinux labels on init error path
Both linuxStandardInit.Init and linuxSetnsInit.Init deferred a
selinux.SetKeyLabel("") / selinux.SetExecLabel("") call to reset the
labels on return. These deferred calls are useless: on success the
function ends with execve(2) and never returns, and on failure runc init
exits right after, so there is nothing left to reset.
Worse, they are actively harmful. They run after utils.UnsafeCloseFrom,
which closes every file descriptor that must not leak into the
container, including the procfs handle cached internally by libpathrs.
Writing the label then re-opens /proc, and libpathrs aborts the whole
process:
thread '<unnamed>' (1) panicked at src/procfs.rs:349:22:
cached procfs handle should be valid: [...] Bad file descriptor
SIGABRT: abort
So a plain execve failure (a bad ELF, or an exec denied by policy) was
reported as a Rust panic plus a Go stack dump instead of the actual
error.
Drop the deferred calls, and add a test case.
Fixes #5438
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
@@ -38,7 +38,6 @@ func (l *linuxSetnsInit) Init() error {
|
||||
if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
defer selinux.SetKeyLabel("") //nolint: errcheck
|
||||
}
|
||||
// Do not inherit the parent's session keyring.
|
||||
if _, err := keys.JoinSessionKeyring(l.getSessionRingName()); err != nil {
|
||||
@@ -102,7 +101,6 @@ func (l *linuxSetnsInit) Init() error {
|
||||
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
|
||||
|
||||
@@ -54,7 +54,6 @@ func (l *linuxStandardInit) Init() error {
|
||||
if err := selinux.SetKeyLabel(l.config.ProcessLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
defer selinux.SetKeyLabel("") //nolint: errcheck
|
||||
}
|
||||
ringname, keepperms, newperms := l.getSessionRingParams()
|
||||
|
||||
@@ -185,7 +184,6 @@ func (l *linuxStandardInit) Init() error {
|
||||
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
|
||||
|
||||
@@ -104,3 +104,20 @@ function enable_userns() {
|
||||
enable_userns
|
||||
exec_check_label
|
||||
}
|
||||
|
||||
# Check that an execve failure is reported as such, rather than aborting
|
||||
# runc init. See https://github.com/opencontainers/runc/issues/5438.
|
||||
@test "runc run (execve error + custom selinux label)" {
|
||||
cat <<-EOF >rootfs/run.sh
|
||||
#!/mmnnttbb foo bar
|
||||
sh
|
||||
EOF
|
||||
chmod +x rootfs/run.sh
|
||||
|
||||
update_config ' .process.selinuxLabel |= "system_u:system_r:container_t:s0:c4,c5"
|
||||
| .process.args = ["/run.sh"]'
|
||||
runc run tst
|
||||
[ "$status" -ne 0 ]
|
||||
[ ${#lines[@]} -eq 1 ]
|
||||
[[ "${lines[0]}" = "exec /run.sh: no such file or directory" ]]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user