Skip to content

Optionally restore archived Unix metadata, and accept stale header linknames behind a policy option - #332

Open
Xynnn007 wants to merge 4 commits into
astral-sh:mainfrom
Xynnn007:image-rs-support
Open

Xynnn007 wants to merge 4 commits into
astral-sh:mainfrom
Xynnn007:image-rs-support

Conversation

@Xynnn007

Copy link
Copy Markdown

We downstream (Confidentia Containers) are trying to replace original astrio-tokio-tar crate with this crate to handle OCI image unpacking. However, there are two gaps that we need to jump over

  1. tar-codec now drops the mode, owner, mtime, and extended attributes while decoding, and extraction always normalizes them (Preserve uid/gid/mode/mtime/xattr on extract #308). Those attributes are needed in downstream.
  2. tar-framing also rejects a non-link member that carries a header linkname. Some older Docker layers leave a stale one on regular-file whiteouts, and tokio-tar ignores it before.

For the gaps, this PR

  1. projects the attributes onto MemberMetadata::unix and adds an opt-in MetadataPolicy that restores them during extraction. Default extraction is unchanged.
  2. adds allow_header_linkname_on_non_link_members(), which is disabled by default and ignores only that header field.

With both changes, we downstream can use this crate smoothly.

Closes #308

Xynnn007 and others added 4 commits November 11, 2026 17:54
Projecting member metadata needs to tell local pax records from global
ones, which `effective_record` merges. Add accessors for each source.

- `local_record` and `global_record` return a keyword's record from one
  source, including a deletion.
- `vendor_records` collects `vendor.*` records by name, with local records
  overriding global ones. Global records are skipped unless requested.

Signed-off-by: Xynnn007 <xynnn@linux.alibaba.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Image unpacking needs each member's mode, owner, mtime, and extended
attributes, but decoding drops them. Carry them on `MemberMetadata` as
`UnixMetadata`.

- `mode` is the header value masked to `0o7777`.
- `uid`, `gid`, and `mtime` come from the local pax record, then the
  header. A local deletion clears the value instead of falling back.
- `SCHILY.xattr.*` records become extended attributes and are accepted
  under every vendor policy. Other `SCHILY.*` records still follow it.
- Global records contribute only with `allow_global_pax_member_metadata`.

Extraction does not apply these attributes yet.

Signed-off-by: Xynnn007 <xynnn@linux.alibaba.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Image unpacking needs the archived attributes on disk, but extraction
always normalizes them. Add an opt-in `MetadataPolicy` that writes them
back through the capability that created each member.

- Each setting is off by default, so default extraction is unchanged.
- Ownership is set before the mode, since `chown` clears setuid and
  setgid. The mtime is set last.
- Files are updated after their contents are written and flushed.
- Directory mtimes are deferred until every member has been extracted.
- Symbolic links are updated without being followed, and their mode is
  left alone.
- An owner id that does not fit `uid_t` or `gid_t`, or an mtime that
  does not fit `time_t`, fails with `UnapplicableMetadata`.
- On platforms other than Unix, any enabled setting fails with
  `UnixMetadataUnsupported` before the destination is touched.

Restoring setuid bits and file capabilities is only safe for trusted
archives.

Signed-off-by: Xynnn007 <xynnn@linux.alibaba.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Some older Docker layers leave a stale `linkname` on regular-file
whiteouts, which other readers ignore but tar-framing rejects with
`UnexpectedLinkTarget`. Add an opt-in to ignore that header field.

- `StreamPolicy` and `DecodePolicy` gain
  `allow_header_linkname_on_non_link_members`, off by default.
- Only the ordinary header field is ignored. A pax `linkpath` record or
  GNU long-link extension on a non-link member is still rejected.

Signed-off-by: Xynnn007 <xynnn@linux.alibaba.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preserve uid/gid/mode/mtime/xattr on extract

1 participant