diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index db2242e2..5d069593 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -1801,8 +1801,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 { @@ -1847,3 +1846,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/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c index 2c69cee5..60d8750d 100644 --- a/libcontainer/nsenter/nsexec.c +++ b/libcontainer/nsenter/nsexec.c @@ -678,17 +678,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. */