Skip to content

Commit

Permalink
rootless: allow single mappings
Browse files Browse the repository at this point in the history
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:

containers/storage#303

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

Closes: containers#1651

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe authored and muayyad-alsadi committed Apr 21, 2019
1 parent 6da5f03 commit b796e46
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 57 deletions.
59 changes: 4 additions & 55 deletions pkg/rootless/rootless_linux.go
Expand Up @@ -11,7 +11,6 @@ import (
"os/user"
"runtime"
"strconv"
"strings"
"sync"
"syscall"
"unsafe"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -237,60 +220,29 @@ 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()
}

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 {
Expand All @@ -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 {
Expand Down
2 changes: 0 additions & 2 deletions test/e2e/rootless_test.go
Expand Up @@ -126,7 +126,6 @@ var _ = Describe("Podman rootless", func() {
env := os.Environ()
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
env = append(env, fmt.Sprintf("HOME=%s", home))
env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1")
env = append(env, "USER=foo")

cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, "", env)
Expand Down Expand Up @@ -171,7 +170,6 @@ var _ = Describe("Podman rootless", func() {
env := os.Environ()
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
env = append(env, fmt.Sprintf("HOME=%s", home))
env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1")
env = append(env, "USER=foo")

allArgs := append([]string{"run"}, args...)
Expand Down

0 comments on commit b796e46

Please sign in to comment.