Skip to content

Build1 publisher3 min readPublished

Podman 5.4.2 exports keep-id containers with every file owner shifted by the ID map

Rootless podman 5.4.2 exports keep-id containers with every file owner shifted and exits 0, a Raspberry Pi reproduction shows. Restored images lock the user out of its own home, so the author routes exports through podman commit first.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying Podman 5.4.2 exports keep-id containers with every file owner shifted by the ID map
Generated illustration

What happened

  • Copying the root filesystem out with podman cp ctr:/ - produced the same owner shift as podman export on the same container.
  • The shifted tarball imports without complaint, but in the new image the user gets Permission denied writing to its own home and /etc/shadow belongs to UID 1.
  • According to the author, committing the container, creating a plain container from that image and exporting that one brings the owners back.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • exposure Backups and migrations of keep-id containers built on export or cp restore with su and passwd owned by daemon, and the fault appears later, on restore, as what looks like a bad image.
  • constraint A backup job cannot rely on exit status or stderr to catch this; verification has to read the owner numbers inside the archive or run the author's check script.
  • decision Until #29856 is fixed, keep-id containers need the commit path before export, at the cost of an extra image and container per backup run.

The explanation starts in podman inspect. The plain rootless container reports IDMappings null [8]. The keep-id container reports UsernsMode private and a UidMap of 0:1:1000, 1000:0:1 and 1001:1001:64536 [8]. According to the author, a keep-id container gets its own user namespace inside rootless podman's namespace, where container UID 0 maps to 1 and container UID 1000 maps to 0, the host user [9].

Put that map next to the archives. The user's home, 1000/1000 inside the container, is 0/0 in the export [2]. The plain export counts 3257 entries at 0/0, 7 at 0/42, 5 at 1000/1000, 3 at 0/43 and 1 at 0/8. The keep-id export counts 3257 at 1/1, 7 at 1/43, 5 at 0/0, 3 at 1/44 and 1 at 1/9 [17]. All 3,273 counted entries moved [1]. Every ID below 1000 went up by one and 1000 became 0, exactly the first two lines of the UidMap, applied and never reversed [2].

The author traces this to the export code, which passes no ID mapping to its tar writer in 5.4.2 and in current main [6]. The main-branch part is a code reading. The reproduction ran on Debian's podman 5.4.2, rootless as UID 1000 with subuids 100000:65536, on a Raspberry Pi 4B running arm64 Debian 13 [7]. The post does not report a run on a newer build.

Nothing in the normal output flags it. The export exits 0 and writes nothing to stderr [3]. File names, sizes and permission bits are right, and only the owner numbers are wrong [13]. The man page does not mention owners, user namespaces or ID mappings [12], so at least the documentation and the code agree. The author wrote that "hardly anyone lists a backup tarball with tar tv to read that column" [20].

Running podman import on the archive succeeds [10]. In the resulting image, /etc/passwd is 1:1, /etc/shadow is 1:43 and the setuid /usr/bin/su is 1:1 [10]. The user gets Permission denied creating a file in its own home [10]. The same command works in the original image [10]. UID 1 is daemon, so su and passwd no longer do their jobs [11]. All eight setuid files moved from 0/0 to 1/1 [18].

Two conditions have to hold for this to reach a given host: rootless podman, and a container created with --userns=keep-id. The plain container in the same test exported with its owners intact [17]. The upstream report, #29856, came from podman inside another container on an EL8 kernel [16][14]. The author notes that setting made the bug easy to read as a nested-container edge case, then got the same result on an ordinary host with the stock subuid range [14].

The reproduction is careful work. The upstream report showed only the home/ lines, and the author counted owners across the whole archive [19].

The author's workaround is to commit the container, create a plain container from that image, and export the plain one [5]. According to the author, commit maps the owners back [5]. Each export then costs an extra image and an extra container [3]. The post also ships check-podman-export-idmap.sh, which lists the containers at risk and checks an export without writing it [15]. I'd put keep-id backups on the commit path now and read the owner column of any archive already on disk before restoring from it.

What to watch

  • A fix for podman-container-tools/podman#29856 that passes the container's ID mapping to the export tar writer, and which podman release ships it.
  • Whether Debian's podman 5.4.2 package picks up a backport of that fix.
  • Whether the podman export man page adds a note on owners and user namespaces.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories