mirror of
https://github.com/containers/podman.git
synced 2025-06-05 14:06:01 +08:00
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:
@ -11,7 +11,6 @@ import (
|
|||||||
"os/user"
|
"os/user"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -192,22 +191,6 @@ func JoinNSPath(path string) (bool, int, error) {
|
|||||||
return true, int(ret), nil
|
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
|
// 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.
|
// 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
|
// 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")
|
return false, -1, errors.Errorf("cannot re-exec process")
|
||||||
}
|
}
|
||||||
|
|
||||||
allowSingleIDMapping := os.Getenv("PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS") != ""
|
|
||||||
|
|
||||||
var uids, gids []idtools.IDMap
|
var uids, gids []idtools.IDMap
|
||||||
username := os.Getenv("USER")
|
username := os.Getenv("USER")
|
||||||
if username == "" {
|
if username == "" {
|
||||||
user, err := user.LookupId(fmt.Sprintf("%d", os.Getuid()))
|
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 {
|
if err == nil {
|
||||||
username = user.Username
|
username = user.Username
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mappings, err := idtools.NewIDMappings(username, username)
|
mappings, err := idtools.NewIDMappings(username, username)
|
||||||
if !allowSingleIDMapping {
|
if err != nil {
|
||||||
if err != nil {
|
logrus.Warnf("cannot find mappings for user %s: %v", username, err)
|
||||||
return false, -1, err
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
uids = mappings.UIDs()
|
||||||
gids = mappings.GIDs()
|
gids = mappings.GIDs()
|
||||||
}
|
}
|
||||||
@ -285,12 +239,10 @@ func BecomeRootInUserNS() (bool, int, error) {
|
|||||||
uidsMapped := false
|
uidsMapped := false
|
||||||
if mappings != nil && uids != nil {
|
if mappings != nil && uids != nil {
|
||||||
err := tryMappingTool("newuidmap", pid, os.Getuid(), uids)
|
err := tryMappingTool("newuidmap", pid, os.Getuid(), uids)
|
||||||
if !allowSingleIDMapping && err != nil {
|
|
||||||
return false, 0, err
|
|
||||||
}
|
|
||||||
uidsMapped = err == nil
|
uidsMapped = err == nil
|
||||||
}
|
}
|
||||||
if !uidsMapped {
|
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)
|
setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
|
||||||
err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
|
err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -307,9 +259,6 @@ func BecomeRootInUserNS() (bool, int, error) {
|
|||||||
gidsMapped := false
|
gidsMapped := false
|
||||||
if mappings != nil && gids != nil {
|
if mappings != nil && gids != nil {
|
||||||
err := tryMappingTool("newgidmap", pid, os.Getgid(), gids)
|
err := tryMappingTool("newgidmap", pid, os.Getgid(), gids)
|
||||||
if !allowSingleIDMapping && err != nil {
|
|
||||||
return false, 0, err
|
|
||||||
}
|
|
||||||
gidsMapped = err == nil
|
gidsMapped = err == nil
|
||||||
}
|
}
|
||||||
if !gidsMapped {
|
if !gidsMapped {
|
||||||
|
@ -126,7 +126,6 @@ var _ = Describe("Podman rootless", func() {
|
|||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
|
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
|
||||||
env = append(env, fmt.Sprintf("HOME=%s", home))
|
env = append(env, fmt.Sprintf("HOME=%s", home))
|
||||||
env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1")
|
|
||||||
env = append(env, "USER=foo")
|
env = append(env, "USER=foo")
|
||||||
|
|
||||||
cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, "", env)
|
cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, "", env)
|
||||||
@ -171,7 +170,6 @@ var _ = Describe("Podman rootless", func() {
|
|||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
|
env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
|
||||||
env = append(env, fmt.Sprintf("HOME=%s", home))
|
env = append(env, fmt.Sprintf("HOME=%s", home))
|
||||||
env = append(env, "PODMAN_ALLOW_SINGLE_ID_MAPPING_IN_USERNS=1")
|
|
||||||
env = append(env, "USER=foo")
|
env = append(env, "USER=foo")
|
||||||
|
|
||||||
allArgs := append([]string{"run"}, args...)
|
allArgs := append([]string{"run"}, args...)
|
||||||
|
Reference in New Issue
Block a user