Skip to content

storage: ID-map hardlink reconstruction changes directory mtimes #1172

Description

@bbartels

Problem

Creating a mapped container from an image changes the modification times of
directories containing hardlinks to the current time. The archived timestamps
are correct. Integer-second timestamps reproduce the problem, so this is not
fractional timestamp rounding.

Reproduction

Use the script below on a disposable rootful Podman host. It imports
a scratch filesystem with hardlinks in two directories and fixed mtimes, then
creates a container with --uidmap 0:1:65535 --gidmap 0:1:65535 and inspects it
through podman mount. No container execution or image download is required.

Expected: both directory mtimes remain 1700000000; hardlinks and contents
remain intact.

Actual: directory mtimes change during materialization, while hardlinks and
contents remain intact.

#!/usr/bin/env bash
set -euo pipefail

# Run as root on a disposable Linux Podman host. No image pull or execution.
test "$(id -u)" -eq 0
engine="${PODMAN:-podman}"
work="$(mktemp -d)"
name="directory-mtime-$(basename "$work")"
name="${name,,}"
image="localhost/$name:test"
cleanup() {
    "$engine" rm -f "$name" >/dev/null 2>&1 || true
    "$engine" rmi "$image" >/dev/null 2>&1 || true
    rm -rf "$work"
}
trap cleanup EXIT
mkdir -p "$work/tree/a" "$work/tree/b"
printf 'contents\n' > "$work/tree/a/one"
ln "$work/tree/a/one" "$work/tree/a/two"
ln "$work/tree/a/one" "$work/tree/b/one"
ln "$work/tree/a/one" "$work/tree/b/two"
touch -d @1700000000 "$work/tree/a/one" "$work/tree/a" "$work/tree/b" "$work/tree"
tar --format=pax --numeric-owner --owner=0 --group=0 -C "$work/tree" -cf "$work/rootfs.tar" .
"$engine" import "$work/rootfs.tar" "$image"
"$engine" create --name "$name" --network=none --pull=never \
    --uidmap 0:1:65535 --gidmap 0:1:65535 "$image" /unused
root="$("$engine" mount "$name")"
stat -c '%n mtime=%Y owner=%u:%g inode=%i links=%h' "$root/a" "$root/b" "$root/a/one" "$root/b/two"
test "$(stat -c %i "$root/a/one")" = "$(stat -c %i "$root/b/two")"
test "$(cat "$root/a/one")" = contents
test "$(stat -c %Y "$root/a")" = 1700000000
test "$(stat -c %Y "$root/b")" = 1700000000
echo 'Directory mtimes preserved'

Diagnosis

storage/drivers/chown_unix.go reconstructs duplicate hardlinks by removing and
recreating their entries. Those operations change the destination directory's
mtime. This also happens for unchanged IDs. A direct filesystem regression
reproduces the same defect without archive extraction.

Version and evidence

  • Source assessed: container-libs 49fe7190f3ecd16fe4dcfd9e749ae480d4021a6c.
  • Consumer context: Podman 6.1.1, storage 1.64.0, rootful native overlay on XFS.
  • Direct root regression: five tests fail on the base implementation and pass
    for 25 race-enabled repetitions with the patch, without skips.
  • Minimal Podman reproducer: exits 1 before and 0 after the candidate.
  • A broader probe also observes /a retaining host owner 0:0 in both stock
    and candidate. That separate ownership assertion remains failing; the positive
    engine result here is specifically directory-mtime preservation.
  • Attach the final relevant results from verification.md and add your own
    sanitized podman version / podman info --debug output.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions