Repository navigation
Conversation
89c80ea to
5d658c5
Compare
|
The fix looks correct to me, but @thaJeztah's concern is valid: there is one caller in moby that depends on the current behavior. The classic builder's I've opened moby/moby#53859 to fix that on the moby side. Other A few nits for this PR:
|
| rgid, err = toHost(gid, i.GIDMaps) | ||
| ruid, err := toHost(uid, i.UIDMaps) | ||
| if err != nil { | ||
| return ruid, 0, err |
There was a problem hiding this comment.
Better to return -1, -1, err here, consistent with ToContainer (and with what was suggested in #241).
| // ToHost returns the host UID and GID for the container uid, gid. | ||
| // Remapping is only performed if the ids aren't already the remapped root ids | ||
| // | ||
| // Every container id is translated through the id map. The container root | ||
| // (id 0) maps to the host remapped-root base (the ParentID of the map entry | ||
| // covering id 0), because toHost(0) resolves to that base--which is exactly | ||
| // what [IdentityMapping.RootPair] returns, so no special case is needed. | ||
| // An empty (nil) mapping is treated as identity. | ||
| // | ||
| // Callers must pass container-namespace ids. ToHost does not treat an id as | ||
| // "already remapped" based on the host remapped-root value: doing so would | ||
| // incorrectly leave a non-root container uid that happens to equal the host | ||
| // remapped-root base unmapped (and therefore owned by the remapped root inside | ||
| // the container). |
There was a problem hiding this comment.
This does not need to be that long. Something like
| // ToHost returns the host UID and GID for the container uid, gid. | |
| // Remapping is only performed if the ids aren't already the remapped root ids | |
| // | |
| // Every container id is translated through the id map. The container root | |
| // (id 0) maps to the host remapped-root base (the ParentID of the map entry | |
| // covering id 0), because toHost(0) resolves to that base--which is exactly | |
| // what [IdentityMapping.RootPair] returns, so no special case is needed. | |
| // An empty (nil) mapping is treated as identity. | |
| // | |
| // Callers must pass container-namespace ids. ToHost does not treat an id as | |
| // "already remapped" based on the host remapped-root value: doing so would | |
| // incorrectly leave a non-root container uid that happens to equal the host | |
| // remapped-root base unmapped (and therefore owned by the remapped root inside | |
| // the container). | |
| // ToHost returns the host UID and GID for the container uid and gid. | |
| // An empty mapping is treated as identity. |
would do just fine.
Something like this: func TestToHostRemappedRoot(t *testing.T) {
// ToHost expects container IDs. A host ID, such as the remapped root
// one, is not treated as already remapped, and so it is either mapped
// again (if it is in the container range) or results in an error.
idMap := []IDMap{{ID: 0, ParentID: 100000, Count: 65536}}
m := IdentityMapping{UIDMaps: idMap, GIDMaps: idMap}
ruid, rgid := m.RootPair()
uid, gid, err := m.ToHost(ruid, rgid)
if err == nil {
t.Fatalf("expected an error, got uid %d, gid %d", uid, gid)
}
} |
…se unmapped ToHost translated container ids to host ids, but special-cased the container root by skipping the id-map lookup whenever the container uid matched the host remapped-root base (RootPair). That comparison was wrong: the input is a container-namespace id, so it must never be compared against a host value. When the subuid/subgid base is below 65536 (e.g. 'rootless:1000:65536', used to align dind-rootless container uids), a non-root container uid that equals the base (e.g. 1000) was incorrectly left unmapped and therefore appeared as root inside the container. Drop the special case entirely and always translate every id through toHost. toHost(0) already resolves to the host remapped-root base (which is exactly what RootPair returns), so the container root is handled correctly without any guard. An empty (nil) mapping is treated as identity. Add a regression test covering standard, low-base, and empty mappings. Signed-off-by: okhowang(王沛文) <okhowang@tencent.com>
5d658c5 to
66f3976
Compare
kolyshkin
left a comment
There was a problem hiding this comment.
AFAIK this one is ready; PTAL @vvoland @thaJeztah
|
(of course, user release notes should come with an explanation about this one) |
fixes #241
ToHost translated container ids to host ids, but special-cased the
container root by skipping the id-map lookup whenever the container uid
matched the host remapped-root base (RootPair). That comparison was
wrong: the input is a container-namespace id, so it must never be
compared against a host value.
When the subuid/subgid base is below 65536 (e.g. 'rootless:1000:65536',
used to align dind-rootless container uids), a non-root container uid
that equals the base (e.g. 1000) was incorrectly left unmapped and
therefore appeared as root inside the container.
Drop the special case entirely and always translate every id through
toHost. toHost(0) already resolves to the host remapped-root base (which
is exactly what RootPair returns), so the container root is handled
correctly without any guard. An empty (nil) mapping is treated as
identity.
Add a regression test covering standard, low-base, and empty mappings.