rootless: allow single mappings

we were playing safe and not allowed any container to have less than
65536 mappings.  There are a couple of reasons to change it:

- it blocked libpod to work in an environment where
  newuidmap/newgidmap are not available, or not configured.

- not allowed to use different partitions of subuids, where each user
  has less than 65536 ids available.

Hopefully this change in containers/storage:

https://github.com/containers/storage/pull/303

will make error clearers if there are not enough IDs for the image
that is being used.

Closes: https://github.com/containers/libpod/issues/1651

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2019-03-10 22:38:12 +01:00
parent ddcdc0c172
commit af3e73426a
2 changed files with 4 additions and 57 deletions

View File

@ -11,7 +11,6 @@ import (
"os/user"
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"unsafe"
@ -192,22 +191,6 @@ func JoinNSPath(path string) (bool, int, error) {
return true, int(ret), nil
}
const defaultMinimumMappings = 65536
func getMinimumIDs(p string) int {
content, err := ioutil.ReadFile(p)
if err != nil {
logrus.Debugf("error reading data from %q, use a default value of %d", p, defaultMinimumMappings)
return defaultMinimumMappings
}
ret, err := strconv.Atoi(strings.TrimSuffix(string(content), "\n"))
if err != nil {
logrus.Debugf("error reading data from %q, use a default value of %d", p, defaultMinimumMappings)
return defaultMinimumMappings
}
return ret + 1
}
// BecomeRootInUserNS re-exec podman in a new userNS. It returns whether podman was re-executed
// into a new user namespace and the return code from the re-executed podman process.
// If podman was re-executed the caller needs to propagate the error code returned by the child
@ -237,47 +220,18 @@ func BecomeRootInUserNS() (bool, int, error) {
return false, -1, errors.Errorf("cannot re-exec process")
}
allowSingleIDMapping := os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") != ""
var uids, gids []idtools.IDMap
username := os.Getenv("USER")
if username == "" {
user, err := user.LookupId(fmt.Sprintf("%d", os.Getuid()))
if err != nil && !allowSingleIDMapping {
if os.IsNotExist(err) {
return false, 0, errors.Wrapf(err, "/etc/subuid or /etc/subgid does not exist, see subuid/subgid man pages for information on these files")
}
return false, 0, errors.Wrapf(err, "could not find user by UID nor USER env was set")
}
if err == nil {
username = user.Username
}
}
mappings, err := idtools.NewIDMappings(username, username)
if !allowSingleIDMapping {
if err != nil {
return false, -1, err
}
availableGIDs, availableUIDs := 0, 0
for _, i := range mappings.UIDs() {
availableUIDs += i.Size
}
minUIDs := getMinimumIDs("/proc/sys/kernel/overflowuid")
if availableUIDs < minUIDs {
return false, 0, fmt.Errorf("not enough UIDs available for the user, at least %d are needed", minUIDs)
}
for _, i := range mappings.GIDs() {
availableGIDs += i.Size
}
minGIDs := getMinimumIDs("/proc/sys/kernel/overflowgid")
if availableGIDs < minGIDs {
return false, 0, fmt.Errorf("not enough GIDs available for the user, at least %d are needed", minGIDs)
}
}
if err == nil {
if err != nil {
logrus.Warnf("cannot find mappings for user %s: %v", username, err)
} else {
uids = mappings.UIDs()
gids = mappings.GIDs()
}
@ -285,12 +239,10 @@ func BecomeRootInUserNS() (bool, int, error) {
uidsMapped := false
if mappings != nil && uids != nil {
err := tryMappingTool("newuidmap", pid, os.Getuid(), uids)
if !allowSingleIDMapping && err != nil {
return false, 0, err
}
uidsMapped = err == nil
}
if !uidsMapped {
logrus.Warnf("using rootless single mapping into the namespace. This might break some images. Check /etc/subuid and /etc/subgid for adding subids")
setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
if err != nil {
@ -307,9 +259,6 @@ func BecomeRootInUserNS() (bool, int, error) {
gidsMapped := false
if mappings != nil && gids != nil {
err := tryMappingTool("newgidmap", pid, os.Getgid(), gids)
if !allowSingleIDMapping && err != nil {
return false, 0, err
}
gidsMapped = err == nil
}
if !gidsMapped {