libstore: always canonicalize directory permissions#13526
Conversation
Prior to this patch, mode 0444 is not updated to 0555 for directories. That means for instance 0554 is canonicalized, but not 0444. We don't believe this has any implications for backwards compatibility, because directories do not have permissions in NAR format and so are always 0555 after deserialization, and store paths with wrong permissions can’t be copied to another host. Co-authored-by: Robert Hensing <robert@roberthensing.nl>
32f9a5f to
c38987e
Compare
|
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2025-08-06-nix-team-meeting-minutes-239-240/67694/2 |
|
Nix trying to This change makes it worse, as this problem now appears more often. Specifically this is a problem in artificial testing environments like VMs or containers. Can we just change nix to cc @Mic92 |
|
Bailing is safer than continuing. I'd require an opt-in for such behavior. |
What's the underlying filesystem that doesn't like |
Override the `Nix` version used by `nixos-anywhere` used by the `clan` CLI. Nix 2.31 introduced stricter permission canonicalization that unconditionally chmods directories to 0555 during `nix copy` [^nix-perms] operations. In the nixos test we have the following file overlay file structure `findmnt` (elided and compacted for brevity): ```shell-session ├─/nix/.ro-store nix-store 9p rw,relatime,cache=f,access=client,msize=16384,trans=virtio ├─/nix/.rw-store tmpfs tmpfs rw,relatime,mode=755 ├─/nix/store overlay overlay rw,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on │ └─/nix/store overlay overlay ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on ``` This means that the host store is shared and new paths are written to the writeable layer, but old paths that don't need to be written will be canonicalized, which fails, because we don't have the permissions to change the permissions of the read only layer. The error message we got: ```shell-session copying path '/nix/store/0dqzmxlgkmw057ffz0cpcbszg17yfmrk-publicsuffix-list-0-unstable-2025-08-28' to 'ssh://root@localhost'... error: chmod "/nix/store/0dqzmxlgkmw057ffz0cpcbszg17yfmrk-publicsuffix-list-0-unstable-2025-08-28": Operation not permitted ``` [^nix-perms]: Nix Permission change: NixOS/nix#13526
|
Override the `Nix` version used by `nixos-anywhere` used by the `clan` CLI. Nix 2.31 introduced stricter permission canonicalization that unconditionally chmods directories to 0555 during `nix copy` [^nix-perms] operations. In the nixos test we have the following file overlay file structure `findmnt` (elided and compacted for brevity): ```shell-session ├─/nix/.ro-store nix-store 9p rw,relatime,cache=f,access=client,msize=16384,trans=virtio ├─/nix/.rw-store tmpfs tmpfs rw,relatime,mode=755 ├─/nix/store overlay overlay rw,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on │ └─/nix/store overlay overlay ro,nosuid,nodev,relatime,lowerdir=/mnt-root/nix/.ro-store,upperdir=/mnt-root/nix/.rw-store/upper,workdir=/mnt-root/nix/.rw-store/work,uuid=on ``` This means that the host store is shared and new paths are written to the writeable layer, but old paths that don't need to be written will be canonicalized, which fails, because we don't have the permissions to change the permissions of the read only layer. The error message we got: ```shell-session copying path '/nix/store/0dqzmxlgkmw057ffz0cpcbszg17yfmrk-publicsuffix-list-0-unstable-2025-08-28' to 'ssh://root@localhost'... error: chmod "/nix/store/0dqzmxlgkmw057ffz0cpcbszg17yfmrk-publicsuffix-list-0-unstable-2025-08-28": Operation not permitted ``` [^nix-perms]: Nix Permission change: NixOS/nix#13526
|
What's the configuration of the Nix store in nix.conf or equivalent? I'm still having trouble formulating the setup correctly in my head (and ideally, getting a reproducer in real life.) |
Motivation
Prior to this patch, mode 0444 is not updated to 0555 for directories. That means for instance 0554 is canonicalized, but not 0444.
I don't believe this has any implications for backwards compatibility, because directories do not have permissions in NAR format and so are always 0555 after de-serialization, and store paths with wrong permissions can’t be copied to another host.
This patch was proposed by @roberth in #12786.
I'd love to add a unit test for this, but I saw no existing examples for code in this file.
Context
Fixes #12786.
Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.