Skip to content

fix: listed mode of copied paths - #336

Open
lczyk wants to merge 3 commits into
canonical:mainfrom
lczyk:fix/copy-mode
Open

lczyk wants to merge 3 commits into
canonical:mainfrom
lczyk:fix/copy-mode

Conversation

@lczyk

@lczyk lczyk commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor
  • Have you signed the CLA?

did some formal verification (fizzbee, my specs are here and here) of the cut path and found 7 minor bugs:

cut the following slice:

# slices/test-package.yaml
package: test-package
slices:
  myslice:
    contents:
      /dir/file: {mode: 0600}
$ chisel cut --release ./ --arch amd64 --root $rootfs test-package_myslice
Extracting files from package "test-package"...
$ stat -c '%a' $rootfs/dir/file
644

the listed mode is parsed and validated but never reaches the extraction, so copied files and directories keep the mode from the deb. text, make and symlink entries do honour it. rabbitmq-server lists two such entries on every chisel-releases branch since 22.04. ( <- @zhijie-yang fyi, since you're the rabbit expert )

repro using chisel-proxy:

$ alias chisel-proxy='go run github.com/lczyk/chisel-proxy/cmd/chisel-proxy@v0.3.0'
$ mkdir -p test-package/dir
$ echo data > test-package/dir/file
$ chisel-proxy cut --arch amd64 ./test-package ./test-package.yaml \
    -- --root ./rootfs test-package_myslice
Extracting files from package "test-package"...
$ stat -c '%a' ./rootfs/dir/file
644

with the fix both print 600.

fix

the mode is passed along in the extraction request. a hard link with a listed mode shares its target's inode when the modes agree and is otherwise extracted as a file of its own with that mode; pending links to the same target are grouped by mode the same way. a mode listed for one destination of a source no longer leaks into another destination of the same source. one consequence: a mode on a path that a glob of the same package also matches now fails the cut with requested twice with diverging mode (the extraction's existing contract, pinned by its "Entries for same destination must have the same mode" test); pinned here in a slicer case rather than relaxed. no slice on any ubuntu-* branch has that overlap.

The "mode" of a copy path was parsed and validated but never handed to
the extraction, so a copied file or directory always kept the mode from
the tarball. Generated content (text, make, symlink) did honour it.

The mode is now passed along with the extraction request. A mode on a
path that a glob of the same package also matches is a diverging mode
for the tarball extraction and fails the cut, as the tarball package
already specifies.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Hard-link modes and per-destination mode handling still have unresolved issues.

2 open findings
What changed in this PR

Fixes listed modes for copied files and directories during extraction.

Changes:

  • Propagates listed modes to tarball extraction.
  • Adds regression tests for mode application and conflicting glob matches.
File Summary
internal/​slicer/​slicer.go Passes listed modes to tarball extraction.
internal/​slicer/​slicer_test.go Adds mode and conflict regression tests.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/slicer/slicer.go
Comment thread internal/slicer/slicer.go
@lczyk lczyk added the Bug An undesired feature ;-) label Oct 10, 2026
The tar header mode set for one destination of a source leaked into
the next destination of the same source, so a destination without a
listed mode could take another one. Each destination now starts from
the mode in the tarball.

A hard link extracted on its own takes its listed mode; one created
against its target shares the inode, so a mode of its own is an error.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A mode can still leak from an earlier hard-link destination to a later destination without an explicit mode.

1 open finding
2 resolved since last review

🧠 Review effort: Lite

Comment on lines +362 to +364
if mode != 0 {
return fmt.Errorf("path %s is a hard link and cannot have its own mode 0%03o", link.path, mode)
}
A hard link with a listed mode shares the inode of its target when the
modes agree, special bits included, and is otherwise extracted as a
file of its own with that mode. Pending links to the same target are
grouped by listed mode the same way instead of erroring, and the second
pass creates missing parent directories as the first one does.
@upils

upils commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

@lczyk as stated in the docs, this mode can only be used on path Chisel creates, so in combination with copy, make, text or symlink. It is not intended to be used to change the mode of a path actually coming from the package. I think the real bug here is that Chisel does not check that. So I would lean toward being more strict for now when validating the YAMLs to make sure mode is always used with the other keys.

@lczyk

lczyk commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@upils hmmm.. if "permission bits for any path chisel creates ... can only be used with copy, make and text" then chisel should enforce that. having said that, i've checked chisel-releases and atm there is a use for this: rabbitmq-server has /var/lib/rabbitmq/mnesia/: { mode: 0750 } on 22.04, 24.04, 26.04 and 26.10. the deb ships that dir as 0755 root:root and the postinst does chmod 750 + chown -R rabbitmq:rabbitmq, so the slice copies half of the postinst.

@zhijie-yang looping you in since its about 🐰

@upils

upils commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Isn't the deb doing something wrong here? What it could do instead is:

  • ship the dir with the proper mode. In that case nothing to do on our side (I am putting aside the ownership issue on purpose)
  • Also use make: true but this might slightly misleading if the package keep shipping the dir.

This may be a bit late to change these packages though... But I think this is an abuse of a bug we missed. I think we should push for packages to behave as best as they can and only tweak as few things as we can in chisel-releases. I know this is not possible in all cases and mutation scripts are here to bridge the gap, but the feature set is limited on purpose.

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

Labels

Bug An undesired feature ;-)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants