mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
Merge pull request from GHSA-xr7r-f8xq-vfvv
fix GHSA-xr7r-f8xq-vfvv and harden fd leaks
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
@@ -89,7 +90,7 @@ func Init() {
|
||||
}
|
||||
// Normally, StartInitialization() never returns, meaning
|
||||
// if we are here, it had failed.
|
||||
os.Exit(1)
|
||||
os.Exit(255)
|
||||
}
|
||||
|
||||
// Normally, this function does not return. If it returns, with or without an
|
||||
@@ -274,6 +275,32 @@ func populateProcessEnvironment(env []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// verifyCwd ensures that the current directory is actually inside the mount
|
||||
// namespace root of the current process.
|
||||
func verifyCwd() error {
|
||||
// getcwd(2) on Linux detects if cwd is outside of the rootfs of the
|
||||
// current mount namespace root, and in that case prefixes "(unreachable)"
|
||||
// to the returned string. glibc's getcwd(3) and Go's Getwd() both detect
|
||||
// when this happens and return ENOENT rather than returning a non-absolute
|
||||
// path. In both cases we can therefore easily detect if we have an invalid
|
||||
// cwd by checking the return value of getcwd(3). See getcwd(3) for more
|
||||
// details, and CVE-2024-21626 for the security issue that motivated this
|
||||
// check.
|
||||
//
|
||||
// We have to use unix.Getwd() here because os.Getwd() has a workaround for
|
||||
// $PWD which involves doing stat(.), which can fail if the current
|
||||
// directory is inaccessible to the container process.
|
||||
if wd, err := unix.Getwd(); errors.Is(err, unix.ENOENT) {
|
||||
return errors.New("current working directory is outside of container mount namespace root -- possible container breakout detected")
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("failed to verify if current working directory is safe: %w", err)
|
||||
} else if !filepath.IsAbs(wd) {
|
||||
// We shouldn't ever hit this, but check just in case.
|
||||
return fmt.Errorf("current working directory is not absolute -- possible container breakout detected: cwd is %q", wd)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// finalizeNamespace drops the caps, sets the correct user
|
||||
// and working dir, and closes any leaked file descriptors
|
||||
// before executing the command inside the namespace
|
||||
@@ -332,6 +359,10 @@ func finalizeNamespace(config *initConfig) error {
|
||||
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err)
|
||||
}
|
||||
}
|
||||
// Make sure our final working directory is inside the container.
|
||||
if err := verifyCwd(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := system.ClearKeepCaps(); err != nil {
|
||||
return fmt.Errorf("unable to clear keep caps: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user