diff options
Diffstat (limited to 'pkg/util')
-rw-r--r-- | pkg/util/utils.go | 53 | ||||
-rw-r--r-- | pkg/util/utils_supported.go | 34 | ||||
-rw-r--r-- | pkg/util/utils_windows.go | 11 |
3 files changed, 97 insertions, 1 deletions
diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 2a52e5129..a074f276c 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -3,6 +3,7 @@ package util import ( "fmt" "os" + ouser "os/user" "path/filepath" "strings" "sync" @@ -11,6 +12,8 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/image/types" "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/namespaces" + "github.com/containers/libpod/pkg/rootless" "github.com/containers/storage" "github.com/containers/storage/pkg/idtools" "github.com/opencontainers/image-spec/specs-go/v1" @@ -131,11 +134,59 @@ func GetImageConfig(changes []string) (v1.ImageConfig, error) { } // ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping -func ParseIDMapping(UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) { +func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []string, subUIDMap, subGIDMap string) (*storage.IDMappingOptions, error) { options := storage.IDMappingOptions{ HostUIDMapping: true, HostGIDMapping: true, } + + if mode.IsKeepID() { + if len(UIDMapSlice) > 0 || len(GIDMapSlice) > 0 { + return nil, errors.New("cannot specify custom mappings with --userns=keep-id") + } + if len(subUIDMap) > 0 || len(subGIDMap) > 0 { + return nil, errors.New("cannot specify subuidmap or subgidmap with --userns=keep-id") + } + if rootless.IsRootless() { + uid := rootless.GetRootlessUID() + gid := rootless.GetRootlessGID() + + username := os.Getenv("USER") + if username == "" { + user, err := ouser.LookupId(fmt.Sprintf("%d", uid)) + if err == nil { + username = user.Username + } + } + mappings, err := idtools.NewIDMappings(username, username) + if err != nil { + return nil, errors.Wrapf(err, "cannot find mappings for user %s", username) + } + maxUID, maxGID := 0, 0 + for _, u := range mappings.UIDs() { + maxUID += u.Size + } + for _, g := range mappings.GIDs() { + maxGID += g.Size + } + + options.UIDMap, options.GIDMap = nil, nil + + options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: uid}) + options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1}) + options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid}) + + options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: gid}) + options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1}) + options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid}) + + options.HostUIDMapping = false + options.HostGIDMapping = false + } + // Simply ignore the setting and do not setup an inner namespace for root as it is a no-op + return &options, nil + } + if subGIDMap == "" && subUIDMap != "" { subGIDMap = subUIDMap } diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go index af5e67fc1..3d9140a23 100644 --- a/pkg/util/utils_supported.go +++ b/pkg/util/utils_supported.go @@ -11,9 +11,33 @@ import ( "github.com/pkg/errors" "os" "path/filepath" + "sync" "syscall" ) +const ( + _cgroup2SuperMagic = 0x63677270 +) + +var ( + isUnifiedOnce sync.Once + isUnified bool + isUnifiedErr error +) + +// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode. +func IsCgroup2UnifiedMode() (bool, error) { + isUnifiedOnce.Do(func() { + var st syscall.Statfs_t + if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil { + isUnified, isUnifiedErr = false, err + } else { + isUnified, isUnifiedErr = st.Type == _cgroup2SuperMagic, nil + } + }) + return isUnified, isUnifiedErr +} + // GetRootlessRuntimeDir returns the runtime directory when running as non root func GetRootlessRuntimeDir() (string, error) { var rootlessRuntimeDirError error @@ -58,3 +82,13 @@ func GetRootlessRuntimeDir() (string, error) { } return rootlessRuntimeDir, nil } + +// GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for +// the pause process +func GetRootlessPauseProcessPidPath() (string, error) { + runtimeDir, err := GetRootlessRuntimeDir() + if err != nil { + return "", err + } + return filepath.Join(runtimeDir, "libpod", "pause.pid"), nil +} diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go index 1e9ccea90..3faa6f10c 100644 --- a/pkg/util/utils_windows.go +++ b/pkg/util/utils_windows.go @@ -10,3 +10,14 @@ import ( func GetRootlessRuntimeDir() (string, error) { return "", errors.New("this function is not implemented for windows") } + +// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode. +func IsCgroup2UnifiedMode() (bool, error) { + return false, errors.New("this function is not implemented for windows") +} + +// GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for +// the pause process +func GetRootlessPauseProcessPidPath() (string, error) { + return "", errors.New("this function is not implemented for windows") +} |