diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2018-09-21 10:16:39 +0200 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2018-09-21 14:34:58 +0000 |
commit | 4f42fe2e9e35a01181031ddca07c044647d7bf04 (patch) | |
tree | 4911e1d06edb7421d7e7826743a0bd57252858d1 | |
parent | 2d1b3e6c305edd1d1689d52aa19094b6c95874e1 (diff) | |
download | podman-4f42fe2e9e35a01181031ddca07c044647d7bf04.tar.gz podman-4f42fe2e9e35a01181031ddca07c044647d7bf04.tar.bz2 podman-4f42fe2e9e35a01181031ddca07c044647d7bf04.zip |
rootless: error out if there are not enough UIDs/GIDs available
Most container images assume there are at least 65536 UIDs/GIDs
available. Raise an error if there are not enough IDs allocated to
the current user.
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Closes: #1520
Approved by: rhatdan
-rw-r--r-- | pkg/rootless/rootless_linux.go | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index d0c6cfa16..5c45f2694 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -11,12 +11,14 @@ import ( "os/user" "runtime" "strconv" + "strings" "syscall" "unsafe" "github.com/containers/storage/pkg/idtools" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) /* @@ -136,6 +138,22 @@ 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 @@ -176,8 +194,28 @@ func BecomeRootInUserNS() (bool, int, error) { } } mappings, err := idtools.NewIDMappings(username, username) - if err != nil && os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") == "" { - return false, -1, err + if os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") == "" { + 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 { uids = mappings.UIDs() |