summaryrefslogtreecommitdiff
path: root/pkg/util
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2022-04-13 14:06:05 -0400
committerDaniel J Walsh <dwalsh@redhat.com>2022-04-21 15:29:04 -0400
commit80c0fceb24b70a85f3f2ca8be29f4a131c0881d4 (patch)
treef7ceffaaf30f4b8057638db446b5512fbbe27318 /pkg/util
parent121dde6234ddfcaf11abea03449bfd2a11da90a5 (diff)
downloadpodman-80c0fceb24b70a85f3f2ca8be29f4a131c0881d4.tar.gz
podman-80c0fceb24b70a85f3f2ca8be29f4a131c0881d4.tar.bz2
podman-80c0fceb24b70a85f3f2ca8be29f4a131c0881d4.zip
Add support for --userns=nomap
From a security point of view, it would be nice to be able to map a rootless usernamespace that does not use your own UID within the container. This would add protection against a hostile process escapping the container and reading content in your homedir. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
Diffstat (limited to 'pkg/util')
-rw-r--r--pkg/util/utils.go105
1 files changed, 67 insertions, 38 deletions
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index b89978601..aed9aebfc 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -347,55 +347,84 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
// GetKeepIDMapping returns the mappings and the user to use when keep-id is used
func GetKeepIDMapping() (*stypes.IDMappingOptions, int, int, error) {
+ if !rootless.IsRootless() {
+ return nil, -1, -1, errors.New("keep-id is only supported in rootless mode")
+ }
options := stypes.IDMappingOptions{
- HostUIDMapping: true,
- HostGIDMapping: true,
+ HostUIDMapping: false,
+ HostGIDMapping: false,
}
- uid, gid := 0, 0
- if rootless.IsRootless() {
- min := func(a, b int) int {
- if a < b {
- return a
- }
- return b
+ min := func(a, b int) int {
+ if a < b {
+ return a
}
+ return b
+ }
- uid = rootless.GetRootlessUID()
- gid = rootless.GetRootlessGID()
+ uid := rootless.GetRootlessUID()
+ gid := rootless.GetRootlessGID()
- uids, gids, err := rootless.GetConfiguredMappings()
- if err != nil {
- return nil, -1, -1, errors.Wrapf(err, "cannot read mappings")
- }
- maxUID, maxGID := 0, 0
- for _, u := range uids {
- maxUID += u.Size
- }
- for _, g := range gids {
- maxGID += g.Size
- }
-
- options.UIDMap, options.GIDMap = nil, nil
+ uids, gids, err := rootless.GetConfiguredMappings()
+ if err != nil {
+ return nil, -1, -1, errors.Wrapf(err, "cannot read mappings")
+ }
+ if len(uids) == 0 || len(gids) == 0 {
+ return nil, -1, -1, errors.Wrapf(err, "keep-id requires additional UIDs or GIDs defined in /etc/subuid and /etc/subgid to function correctly")
+ }
+ maxUID, maxGID := 0, 0
+ for _, u := range uids {
+ maxUID += u.Size
+ }
+ for _, g := range gids {
+ maxGID += g.Size
+ }
- options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(uid, maxUID)})
- options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1})
- if maxUID > uid {
- options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid})
- }
+ options.UIDMap, options.GIDMap = nil, nil
- options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(gid, maxGID)})
- options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1})
- if maxGID > gid {
- options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
- }
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(uid, maxUID)})
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: 0, Size: 1})
+ if maxUID > uid {
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid + 1, HostID: uid + 1, Size: maxUID - uid})
+ }
- options.HostUIDMapping = false
- options.HostGIDMapping = false
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: 0, HostID: 1, Size: min(gid, maxGID)})
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: 0, Size: 1})
+ if maxGID > gid {
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
}
- // Simply ignore the setting and do not setup an inner namespace for root as it is a no-op
+
return &options, uid, gid, nil
}
+// GetNoMapMapping returns the mappings and the user to use when nomap is used
+func GetNoMapMapping() (*stypes.IDMappingOptions, int, int, error) {
+ if !rootless.IsRootless() {
+ return nil, -1, -1, errors.New("nomap is only supported in rootless mode")
+ }
+ options := stypes.IDMappingOptions{
+ HostUIDMapping: false,
+ HostGIDMapping: false,
+ }
+ uids, gids, err := rootless.GetConfiguredMappings()
+ if err != nil {
+ return nil, -1, -1, errors.Wrapf(err, "cannot read mappings")
+ }
+ if len(uids) == 0 || len(gids) == 0 {
+ return nil, -1, -1, errors.Wrapf(err, "nomap requires additional UIDs or GIDs defined in /etc/subuid and /etc/subgid to function correctly")
+ }
+ options.UIDMap, options.GIDMap = nil, nil
+ uid, gid := 0, 0
+ for _, u := range uids {
+ options.UIDMap = append(options.UIDMap, idtools.IDMap{ContainerID: uid, HostID: uid + 1, Size: u.Size})
+ uid += u.Size
+ }
+ for _, g := range gids {
+ options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid, HostID: gid + 1, Size: g.Size})
+ gid += g.Size
+ }
+ return &options, 0, 0, nil
+}
+
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []string, subUIDMap, subGIDMap string) (*stypes.IDMappingOptions, error) {
options := stypes.IDMappingOptions{
@@ -415,7 +444,7 @@ func ParseIDMapping(mode namespaces.UsernsMode, uidMapSlice, gidMapSlice []strin
options.AutoUserNsOpts = *opts
return &options, nil
}
- if mode.IsKeepID() {
+ if mode.IsKeepID() || mode.IsNoMap() {
options.HostUIDMapping = false
options.HostGIDMapping = false
return &options, nil