← Back to issue list

Handle ELOOP while copying symlink metadata on virtiofs

View original Github issue

Metadata

Project
craft-parts
Number
#1703
Type
issue
State
open
Author
gcomneno
Labels
Type: Bug
Created
Updated
Closed
—

Current evaluation

file_utils.copy() raises ELOOP on virtiofs because shutil._copyxattr does not suppress it when llistxattr fails on symlinks; narrow fix proposed with tests, contributor ready to PR. Charmcraft-side workaround merged.

Suggested action: keep open

Reason: The report is fully diagnosed down to shutil._copyxattr -> os.listxattr(follow_symlinks=False) -> llistxattr, and I confirmed the vulnerable call site still exists at craft_parts/utils/file_utils.py:196 (`shutil.copy2(source, destination, follow_symlinks=follow_symlinks)`), so the bug is unfixed; `git_log_search ELOOP` in craft-parts returns no commits, confirming no fix landed. It is labeled Type: Bug and cross-confirmed by canonical/charmcraft#2864 (merged commit 430ee59a excluding .venv/.tox) where lengau explicitly asked for a comment referencing this issue as the underlying cause, so it is triaged and valid and must stay open. Impact is moderate rather than high because that charmcraft workaround already unblocks the reported macOS/virtiofs packing failures and only the generic file-copy path is affected; the proposed boundary (split copyfile/copystat only for follow_symlinks=False symlinks, suppress errno.ELOOP from the metadata step only) plus three mock-based test cases keeps the change small, hence low complexity and high actionability.

Evaluated by: mr-cal-bot

Impact: 42 Quick Win: 25 Complexity: 30 Confidence: 85 Actionability: 85

Issue body

## Summary Copying a symlink with `craft_parts.utils.file_utils.copy()` can fail with: OSError: [Errno 40] Too many levels of symbolic links on virtiofs-backed filesystems. This has been observed through Charmcraft when a project contains symlinks inside directories such as `.venv` or `.tox`: - canonical/charmcraft#2661 - canonical/charmcraft#2864 The Charmcraft-side proposal avoids pulling those directories, but the underlying failure appears to be in the generic craft-parts file-copy path. ## Root cause For a symlink copied with `follow_symlinks=False`, `file_utils.copy()` eventually calls: shutil.copy2(...) -> shutil.copyfile(...) -> shutil.copystat(...) -> shutil._copyxattr(...) -> os.listxattr(..., follow_symlinks=False) -> llistxattr() On the affected virtiofs setup, `llistxattr()` returns `ELOOP` for the symlink. Python's `shutil._copyxattr()` suppresses several unsupported-xattr errors, including `ENOTSUP`, `ENODATA`, and `EINVAL`, but not `ELOOP`, so the exception propagates even though the symlink itself can be copied successfully. ## Scope This is not specific to `.venv` or `.tox`. Any symlink copied through this path on a filesystem exhibiting the same `llistxattr()` behavior may trigger the failure. ## Possible narrow handling A possible approach would be to distinguish the symlink-copy operation from the metadata-copy operation when: - `follow_symlinks=False`; and - the source is a symlink. This would allow an `ELOOP` raised specifically while copying symlink metadata to be treated as an unsupported metadata operation, without suppressing an `ELOOP` raised while actually copying the entry. A local proof-of-concept verified these boundaries: - symlink + `copystat()` raising `ELOOP`: symlink remains correctly copied; - symlink + `copyfile()` raising `ELOOP`: `ELOOP` still propagates; - regular file + `copy2()` raising `ELOOP`: `ELOOP` still propagates. ## Test coverage A regression test could simulate the filesystem behavior without requiring virtiofs by mocking the relevant `shutil` operation. Suggested cases: 1. tolerate `ELOOP` from metadata copying for a symlink copied without following it; 2. propagate `ELOOP` from the actual symlink copy; 3. continue propagating `ELOOP` for regular files. This would keep the exception handling limited to the known metadata boundary rather than suppressing `ELOOP` generically.

Evaluation history

Date Model Scores Action Summary
stealth/space-bunny-alpha
Impact: 42
Quick Win: 25
Complexity: 30
Confidence: 85
Actionability: 85
keep open file_utils.copy() raises ELOOP on virtiofs because shutil._copyxattr does not suppress it when llistxattr fails on symlinks; narrow fix proposed with tests, contributor ready to PR. Charmcraft-side workaround merged.
stealth/space-bunny-alpha
Impact: 52
Quick Win: 25
Complexity: 45
Confidence: 90
Actionability: 88
needs triage ELOOP from llistxattr aborts symlink copies on virtiofs; a narrow fix and regression tests are ready, but craft-parts maintainer approval or a PR is still pending.
qwen/qwen3.6-35b-a3b
Impact: 75
Quick Win: 41
Staleness: 10
Complexity: 45
Confidence: 85
Support Request: 0
keep open Bug report to handle ELOOP errors when copying symlink metadata on virtiofs. Root cause identified, fix proposed and tested locally by contributor; awaiting maintainer response.
qwen/qwen3.6-35b-a3b
Impact: 60
Quick Win: 30
Staleness: 40
Complexity: 50
Confidence: 70
Support Request: 10
needs triage Bug report to handle ELOOP errors when copying symlink metadata on virtiofs. Root cause identified, fix proposed and tested locally by contributor; awaiting maintainer response.
qwen3.6-35b-a3b-mtp-q6
Impact: 60
Quick Win: 33
Staleness: 5
Complexity: 45
Confidence: 85
Support Request: 10
needs triage Bug report to handle ELOOP errors when copying symlink metadata on virtiofs. Fresh issue with root cause analysis and proposed fix; no maintainer response yet.

Update history

Date Change
updated
updated
created

Related work

  • Related To: canonical/charmcraft#2864 (confidence 92%)

    Merged as commit 430ee59a, excluding .venv/.tox from source pulls; explicitly framed as a Charmcraft-side workaround for this craft-parts issue per lengau's request for a referencing code comment.

  • Related To: canonical/charmcraft#2661 (confidence 90%)

    Original user-facing report of 'Too many levels of symbolic links' during charm packing, closed by the same workaround PR rather than by a craft-parts fix.

Related issues

No related issues found above the similarity threshold.