← Back to issue list

bash gets built with a /bin/bash that is missing the executable bit

View original Github issue

Metadata

Project
snapcraft
Number
#5114
Type
issue
State
open
Author
basak
Labels
Created
Updated
Closed

Current evaluation

Staging bash+quilt in a classic snap yields a non-executable bin/bash because craft-parts normalize copies the symlink target from the system via shutil.copyfile, dropping the executable bit. Unfixed in craft-parts; reporter has a chmod workaround.

Suggested action: keep open

Reason: A maintainer (lengau) triaged it, pinpointed the exact code (craft_parts/packages/normalize.py _try_copy_local, lines 148-157) and confirmed the root cause: shutil.copyfile copies content but not the file mode, so the executable bit is lost. The current craft-parts HEAD still uses shutil.copyfile at that line, so the bug is unfixed. It is a real, reproducible bug with a clear minimal reproducer, not a support request, so it should stay open.

Impact: 45 Quick Win: 31.5 Staleness: 70 Complexity: 30 Confidence: 70 Support Request: 10

Issue body

### Bug Description If I stage the `bash` and `quilt` packages in a part in a classic snap, then the snap gets built with a `bin/bash` file that is not executable. Subsequent attempts to use it fail. ### To Reproduce On a fresh Noble VM: ``` sudo snap install --classic snapcraft # installs 8.4.3 (12823) mkdir -p demo/snap cat > demo/snap/snapcraft.yaml <<EOT name: demo version: 1 summary: demo description: demo confinement: classic grade: devel base: core24 apps: demo: command: usr/bin/bash parts: demo: build-attributes: [enable-patchelf] plugin: nil stage-packages: [bash, quilt] EOT cd demo snapcraft build --destructive-mode ``` Expected result: `parts/demo/install/bin/bash` is executable, and this passes through to the final snap (if you continue you should also see it in `prime/bin/bash` as executable, etc). Actual result: `parts/demo/install/bin/bash` is not executable and this passes through to the final snap. Then scripts that try to use it fail. ### Environment Ubuntu 24.04 cloud image, snapcraft in destructive mode. Snapcraft snap 8.4.3 (12823). ### snapcraft.yaml ```yaml name: demo version: 1 summary: demo description: demo confinement: classic grade: devel base: core24 apps: demo: command: usr/bin/bash parts: demo: build-attributes: [enable-patchelf] plugin: nil stage-packages: [bash, quilt] ``` ### Relevant log output ```shell 2024-10-13 13:12:26.879 Building demo 2024-10-13 13:12:26.893 execute action demo:Action(part_name='demo', step=Step.BUILD, action_type=ActionType.RUN, reason=None, project_vars=None, properties=ActionProperties(changed_files=None, changed_dirs=None)) 2024-10-13 13:12:26.894 load state file: /home/ubuntu/demo/parts/demo/state/pull 2024-10-13 13:12:28.158 fix artifacts: unpack_dir='/home/ubuntu/demo/parts/demo/install' 2024-10-13 13:12:28.175 fix symlink: path='/home/ubuntu/demo/parts/demo/install/usr/share/quilt/compat/bash', unpack_dir='/home/ubuntu/demo/parts/demo/install', root='/home/ubuntu/demo/parts/demo/install/usr/share/quilt/compat' 2024-10-13 13:12:28.207 fix symlink: target='/home/ubuntu/demo/parts/demo/install/bin/bash' 2024-10-13 13:12:28.207 Copying needed target link from the system: /usr/bin/bash 2024-10-13 13:12:30.039 remove directory /home/ubuntu/demo/parts/demo/build 2024-10-13 13:12:30.041 Executing PosixPath('/home/ubuntu/demo/parts/demo/run/build.sh') ``` ### Additional context The trace output suggests that snapcraft is doing something because `usr/share/quilt/compat/bash` is a symlink. If I drop `quilt` from `stage-packages`, then `bin/bash` isn't created. I found this when trying to move the git-ubuntu snap to core24. That's complex enough so I came up with a minimal reproducer. Workaround: I did this: ``` override-stage: | craftctl default chmod 755 bin/bash ```

Evaluation history

Date Model Scores Action Summary
qwen/qwen3.8-27b
Impact: 45
Quick Win: 31.5
Staleness: 70
Complexity: 30
Confidence: 70
Support Request: 10
keep open Staging bash+quilt in a classic snap yields a non-executable bin/bash because craft-parts normalize copies the symlink target from the system via shutil.copyfile, dropping the executable bit. Unfixed in craft-parts; reporter has a chmod workaround.
qwen/qwen3.6-35b-a3b
Staleness: 88
Complexity: 55
Confidence: 75
Support Request: 10
close stale Staging bash and quilt in a classic snap causes /bin/bash to lose its executable bit due to craft-parts symlink normalization. The issue has been inactive for over a year with a provided workaround but no fix.
qwen3.6-35b-a3b-mtp-q6
Staleness: 95
Complexity: 45
Confidence: 85
Support Request: 15
close stale Staging bash and quilt in a classic snap causes bin/bash to lose its executable bit. Currently inactive for over 630 days with a workaround available.
qwen3.6-35b-a3b-mtp-q6
Staleness: 88
Complexity: 45
Confidence: 60
Support Request: 10
close stale Staging bash in classic snaps strips the executable bit from bin/bash, breaking execution. Discussion centers on whether craft-parts should preserve permissions and rewrite absolute symlinks for quilt. Issue remains open and awaiting triage.

Update history

No update history recorded yet.

Related work

  • Caused By: craft-parts#148 (confidence 40%)

    Root cause is in craft-parts normalize.py _try_copy_local (shutil.copyfile drops the mode bit); the issue links to that file/lines but no specific craft-parts issue number is cited, so the ref is approximate.

Related issues

No related issues found above the similarity threshold.