From f4158e00cac1f576f61904a73530c373c15354e2 Mon Sep 17 00:00:00 2001
From: Aleksa Sarai <asarai@suse.de>
Date: Sat, 18 Mar 2017 04:33:14 +1100
Subject: [PATCH 08/94] 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.

Change-Id: I7a7911f398a38b2d21e1bb6bc4b3131f6504ca8d
Signed-off-by: Aleksa Sarai <asarai@suse.de>
---
 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 1187835..99cc02c 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
-- 
2.7.4.3

