From 0dad64f7ad4d27a02aa0c6605304832e87a79974 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 18 Sep 2015 13:55:49 -0700 Subject: [PATCH] Fix STDIO permissions when container user not root Fix the permissions of the container's main processes STDIO when the process is not run as the root user. This changes the permissions right before switching to the specified user so that it's STDIO matches it's UID and GID. Add a test for checking that the STDIO of the process is owned by the specified user. Signed-off-by: Michael Crosby --- libcontainer/init_linux.go | 12 +++++++++++- libcontainer/integration/exec_test.go | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index d7058eaa..0433913a 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -187,7 +187,17 @@ func setupUser(config *initConfig) error { return err } } - + // change the permissions on the STDIO of the current process so that when the user + // is changed for the container, it's STDIO of the process matches the user. + for _, fd := range []uintptr{ + os.Stdin.Fd(), + os.Stderr.Fd(), + os.Stdout.Fd(), + } { + if err := syscall.Fchown(int(fd), execUser.Uid, execUser.Gid); err != nil { + return err + } + } suppGroups := append(execUser.Sgids, addGroups...) if err := syscall.Setgroups(suppGroups); err != nil { return err diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go index 582d6bb3..04fbe651 100644 --- a/libcontainer/integration/exec_test.go +++ b/libcontainer/integration/exec_test.go @@ -994,3 +994,23 @@ func TestHook(t *testing.T) { t.Fatalf("expected file to not exist, got %s", fi.Name()) } } + +func TestSTDIOPermissions(t *testing.T) { + if testing.Short() { + return + } + + rootfs, err := newRootfs() + ok(t, err) + defer remove(rootfs) + config := newTemplateConfig(rootfs) + buffers, exitCode, err := runContainer(config, "", "sh", "-c", "echo hi > /dev/stderr") + ok(t, err) + if exitCode != 0 { + t.Fatalf("exit code not 0. code %d stderr %q", exitCode, buffers.Stderr) + } + + if actual := strings.Trim(buffers.Stderr.String(), "\n"); actual != "hi" { + t.Fatalf("stderr should equal be equal %q %q", actual, "hi") + } +}