libpod: fix --userns=keep-id with big UIDs

when creating a keep-id namespace, we split the original user
namespace in:

inner ns | outer ns  | size:
0        | 1         | ID
ID       | 0         | 1
ID+1     | ID+1      | availableIds - ID

When the user ID is bigger than the number of available
subuids/subgids we fail to create the user namespace because the first
slice is bigger than the available number of IDs and the third one has
a negative size.

Fix it by not using more than the available number of IDs in the first
slice and creating the third one only if there are other IDs left.

When the user ID is bigger than the number of additional IDs, there
will be a gap between the two mappings so the IDs between the maximum
additional ID and the user ID won't be present inside of the
namespace.

Closes: https://github.com/containers/libpod/issues/4838

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2020-01-10 22:22:37 +01:00
parent e1ffac6cc7
commit 7a11ed5a77
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED
1 changed files with 15 additions and 4 deletions

View File

@ -335,6 +335,13 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin
return nil, errors.New("cannot specify subuidmap or subgidmap with --userns=keep-id")
}
if rootless.IsRootless() {
min := func(a, b int) int {
if a < b {
return a
}
return b
}
uid := rootless.GetRootlessUID()
gid := rootless.GetRootlessGID()
@ -352,13 +359,17 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin
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: 0, HostID: 1, Size: min(uid, maxUID)})
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})
if maxUID > uid {
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: 0, HostID: 1, Size: min(gid, maxGID)})
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})
if maxGID > gid {
options.GIDMap = append(options.GIDMap, idtools.IDMap{ContainerID: gid + 1, HostID: gid + 1, Size: maxGID - gid})
}
options.HostUIDMapping = false
options.HostGIDMapping = false