diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index b3e157bd..246ec95f 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -1797,8 +1797,7 @@ func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.Na Value: []byte(c.newgidmapPath), }) } - // The following only applies if we are root. - if !c.config.Rootless { + if requiresRootOrMappingTool(c.config) { // check if we have CAP_SETGID to setgroup properly pid, err := capability.NewPid(0) if err != nil { @@ -1843,3 +1842,10 @@ func ignoreTerminateErrors(err error) error { } return err } + +func requiresRootOrMappingTool(c *configs.Config) bool { + gidMap := []configs.IDMap{ + {ContainerID: 0, HostID: os.Getegid(), Size: 1}, + } + return !reflect.DeepEqual(c.GidMappings, gidMap) +} diff --git a/libcontainer/message_linux.go b/libcontainer/message_linux.go index ab453cde..ed7f986d 100644 --- a/libcontainer/message_linux.go +++ b/libcontainer/message_linux.go @@ -77,13 +77,13 @@ func (msg *Boolmsg) Serialize() []byte { native.PutUint16(buf[0:2], uint16(msg.Len())) native.PutUint16(buf[2:4], msg.Type) if msg.Value { - buf[4] = 1 + native.PutUint32(buf[4:8], uint32(1)) } else { - buf[4] = 0 + native.PutUint32(buf[4:8], uint32(0)) } return buf } func (msg *Boolmsg) Len() int { - return unix.NLA_HDRLEN + 1 + return unix.NLA_HDRLEN + 4 // alignment } diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c index 030e53a7..3bff7bf6 100644 --- a/libcontainer/nsenter/nsexec.c +++ b/libcontainer/nsenter/nsexec.c @@ -679,17 +679,15 @@ void nsexec(void) /* * Enable setgroups(2) if we've been asked to. But we also * have to explicitly disable setgroups(2) if we're - * creating a rootless container (this is required since - * Linux 3.19). + * creating a rootless container for single-entry mapping. + * i.e. config.is_setgroup == false. + * (this is required since Linux 3.19). + * + * For rootless multi-entry mapping, config.is_setgroup shall be true and + * newuidmap/newgidmap shall be used. */ - if (config.is_rootless && config.is_setgroup) { - kill(child, SIGKILL); - bail("cannot allow setgroup in an unprivileged user namespace setup"); - } - if (config.is_setgroup) - update_setgroups(child, SETGROUPS_ALLOW); - if (config.is_rootless) + if (config.is_rootless && !config.is_setgroup) update_setgroups(child, SETGROUPS_DENY); /* Set up mappings. */