From 76aeaf8181fa0038983503294b02e0f42663953c Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Sat, 18 Mar 2017 04:33:14 +1100 Subject: [PATCH] libcontainer: init: fix unmapped console fchown If the stdio of the container is owned by a group which is not mapped in the user namespace, attempting to fchown the file descriptor will result in EINVAL. Counteract this by simply not doing an fchown if the group owner of the file descriptor has no host mapping according to the configured GIDMappings. Signed-off-by: Aleksa Sarai --- libcontainer/init_linux.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 118783516..99cc02cbd 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -277,7 +277,7 @@ func setupUser(config *initConfig) error { // before we change to the container's user make sure that the processes STDIO // is correctly owned by the user that we are switching to. - if err := fixStdioPermissions(execUser); err != nil { + if err := fixStdioPermissions(config, execUser); err != nil { return err } @@ -312,7 +312,7 @@ func setupUser(config *initConfig) error { // fixStdioPermissions fixes the permissions of PID 1's STDIO within the container to the specified user. // The ownership needs to match because it is created outside of the container and needs to be // localized. -func fixStdioPermissions(u *user.ExecUser) error { +func fixStdioPermissions(config *initConfig, u *user.ExecUser) error { var null syscall.Stat_t if err := syscall.Stat("/dev/null", &null); err != nil { return err @@ -326,10 +326,20 @@ func fixStdioPermissions(u *user.ExecUser) error { if err := syscall.Fstat(int(fd), &s); err != nil { return err } + // Skip chown of /dev/null if it was used as one of the STDIO fds. if s.Rdev == null.Rdev { continue } + + // Skip chown if s.Gid is actually an unmapped gid in the host. While + // this is a bit dodgy if it just so happens that the console _is_ + // owned by overflow_gid, there's no way for us to disambiguate this as + // a userspace program. + if _, err := config.Config.HostGID(int(s.Gid)); err != nil { + continue + } + // We only change the uid owner (as it is possible for the mount to // prefer a different gid, and there's no reason for us to change it). // The reason why we don't just leave the default uid=X mount setup is