Merge pull request #2894 from haircommander/chdir-fix-2

libct/init_linux: retry chdir to fix EPERM (regression in rc93)
This commit is contained in:
Mrunal Patel
2021-04-06 17:17:56 -07:00
committed by GitHub
2 changed files with 39 additions and 5 deletions
+22 -4
View File
@@ -131,6 +131,26 @@ func finalizeNamespace(config *initConfig) error {
return errors.Wrap(err, "close exec fds")
}
// we only do chdir if it's specified
doChdir := config.Cwd != ""
if doChdir {
// First, attempt the chdir before setting up the user.
// This could allow us to access a directory that the user running runc can access
// but the container user cannot.
err := unix.Chdir(config.Cwd)
switch {
case err == nil:
doChdir = false
case os.IsPermission(err):
// If we hit an EPERM, we should attempt again after setting up user.
// This will allow us to successfully chdir if the container user has access
// to the directory, but the user running runc does not.
// This is useful in cases where the cwd is also a volume that's been chowned to the container user.
default:
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err)
}
}
caps := &configs.Capabilities{}
if config.Capabilities != nil {
caps = config.Capabilities
@@ -152,10 +172,8 @@ func finalizeNamespace(config *initConfig) error {
if err := setupUser(config); err != nil {
return errors.Wrap(err, "setup user")
}
// Change working directory AFTER the user has been set up.
// Otherwise, if the cwd is also a volume that's been chowned to the container user (and not the user running runc),
// this command will EPERM.
if config.Cwd != "" {
// Change working directory AFTER the user has been set up, if we haven't done it yet.
if doChdir {
if err := unix.Chdir(config.Cwd); err != nil {
return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err)
}
+17 -1
View File
@@ -30,7 +30,7 @@ function teardown() {
# Verify a cwd owned by the container user can be chdir'd to,
# even if runc doesn't have the privilege to do so.
@test "runc create sets up user before chdir to cwd" {
@test "runc create sets up user before chdir to cwd if needed" {
requires rootless rootless_idmap
# Some setup for this test (AUX_DIR and AUX_UID) is done
@@ -56,3 +56,19 @@ function teardown() {
runc run test_busybox
[ "$status" -eq 0 ]
}
# Verify a cwd not owned by the container user can be chdir'd to,
# if runc does have the privilege to do so.
@test "runc create can chdir if runc has access" {
requires root
mkdir -p rootfs/home/nonroot
chmod 700 rootfs/home/nonroot
update_config ' .process.cwd = "/root"
| .process.user.uid = 42
| .process.args |= ["ls", "/tmp"]'
runc run test_busybox
[ "$status" -eq 0 ]
}