Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permission denied error when building symlink derivation #9579

Closed
rvl opened this issue Dec 10, 2023 · 13 comments · Fixed by #10456
Closed

Permission denied error when building symlink derivation #9579

rvl opened this issue Dec 10, 2023 · 13 comments · Fixed by #10456
Assignees
Labels
bug regression Something doesn't work anymore

Comments

@rvl
Copy link
Contributor

rvl commented Dec 10, 2023

Describe the bug

My apologies if this is already fixed on master branch, but I couldn't identify any particular issue or PR which describes this issue.

Nix 1.19.2 fails to build a derivation containing a symlink to store path.

# test-symlink.nix
{ local ? "/home/rodney/ops/nixpkgs"
, pkgs ? import local {}
}: rec {
  direct-symlink = pkgs.runCommand "direct-symlink" {} ''
    ln -vs ${local}/.version $out
  '';
  indirect-symlink = pkgs.runCommand "indirect-symlink" {} ''
    ln -vs ${direct-symlink} $out
  '';
}

Steps To Reproduce

The error message is:

rodney@tethys:~/ops/nixpkgs % nix build --experimental-features "nix-command" -f test-symlink.nix && readlink -f result*
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
warning: Ignoring setting 'auto-allocate-uids' because experimental feature 'auto-allocate-uids' is not enabled
warning: Ignoring setting 'impure-env' because experimental feature 'configurable-impure-env' is not enabled
error:
       … while setting up the build environment

       error: getting attributes of path '/nix/store/ws9yl6ph10v79gx4p9ilhyxg214xf7i7-direct-symlink': Permission denied

Expected behavior

I expected both derivations to build and for the resulting store paths to be resolvable symlinks.

This is what happens with nix-2.18.1:

rodney@tethys:~/ops/nixpkgs % nix build --experimental-features "nix-command" -f test-symlink.nix && readlink -f result*
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
/home/rodney/ops/nixpkgs/.version
/home/rodney/ops/nixpkgs/.version

nix-env --version output

This is the nixUnstable package, corresponding to revision 2c7f3c0fb7c08a0814627611d9d7d45ab6d75335 of nixpkgs.

nix (Nix) 2.19.2

Additional context

Introduced by

You might ask, why build such a silly derivation? Well, it's how mkOutOfStoreSymlink works under home-manager.

See: nix-community/home-manager#4692

Priorities

Add 👍 to issues you find important.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2023-12-18-nix-team-meeting-minutes-113/37050/1

vlaci added a commit to vlaci/nixos-config that referenced this issue Dec 20, 2023
@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/home-manager-mkoutofstoresymlink-and-nixunstable/37241/1

@infinisil
Copy link
Member

I tried to reproduce this, but struggled. I wrote a NixOS test for this that shows no problems:

# nixos-test.nix
let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/d6863cbcbbb80e71cecfc03356db1cda38919523";
  pkgs = import nixpkgs {
    config = {};
    overlays = [];
    system = "x86_64-linux";
  };
in
pkgs.nixosTest {
  name = "test";
  skipTypeCheck = true;
  nodes.machine = {
    environment.etc.nixpkgs.source = nixpkgs;
    system.extraDependencies = [
      (pkgs.closureInfo {
        rootPaths = [ pkgs.stdenvNoCC.drvPath ];
      })
    ];
    nix.package = pkgs.nixUnstable;
    environment.etc."test-symlink.nix".text = ''
      # test-symlink.nix
      { local ? "/etc/nixpkgs"
      , pkgs ? import local {}
      }: rec {
        direct-symlink = pkgs.runCommand "direct-symlink" {} '''
          ln -vs ''${local}/.version $out
        ''';
        indirect-symlink = pkgs.runCommand "indirect-symlink" {} '''
          ln -vs ''${direct-symlink} $out
        ''';
      }
    '';
  };

  testScript = ''
    start_all()
    machine.succeed('nix-build /etc/test-symlink.nix')
    print(machine.succeed('nix-env --version'))
    print(machine.succeed('readlink -f result*'))
  '';
}

Run with

$ nix-build nixos-test.nix
[...]
machine # these 2 derivations will be built:
machine #   /nix/store/lqh27yh50v8zyv57cwk4l5zz2yg8046q-direct-symlink.drv
machine #   /nix/store/4p887hcx1bks8h65p0j3ghfnximkddyf-indirect-symlink.drv
machine # warning: Ignoring setting 'auto-allocate-uids' because experimental feature 'auto-allocate-uids' is not enabled
machine # warning: Ignoring setting 'impure-env' because experimental feature 'configurable-impure-env' is not enabled
machine # building '/nix/store/lqh27yh50v8zyv57cwk4l5zz2yg8046q-direct-symlink.drv'...
machine # '/nix/store/96664m3zyjnw2xyhpkyipxcmf5s7vv3w-direct-symlink' -> '/etc/nixpkgs/.version'
machine # building '/nix/store/4p887hcx1bks8h65p0j3ghfnximkddyf-indirect-symlink.drv'...
machine # '/nix/store/hq63b5zkir3ibsas5w9rkyp8gllgs6jx-indirect-symlink' -> '/nix/store
/96664m3zyjnw2xyhpkyipxcmf5s7vv3w-direct-symlink'
(finished: must succeed: nix-build /etc/test-symlink.nix, in 11.68 seconds)
machine: must succeed: nix-env --version
(finished: must succeed: nix-env --version, in 0.06 seconds)
nix-env (Nix) 2.19.2

machine: must succeed: readlink -f result*
(finished: must succeed: readlink -f result*, in 0.02 seconds)
/nix/store/61gw1axgxrvx0bnxv2dla6zhkgwv45zr-source/.version
/nix/store/61gw1axgxrvx0bnxv2dla6zhkgwv45zr-source/.version

(finished: run the VM test script, in 11.93 seconds)
test script finished in 11.96s
cleanup
kill machine (pid 7)
machine # qemu-kvm: terminating on signal 15 from pid 4 (/nix/store/5k91mg4qjylxbfvrv748smfh51ppjq0g-python3-3.11.6/bin/python3.11)
(finished: cleanup, in 0.05 seconds)
kill vlan (pid 5)
/nix/store/7dwclnxw0xdvmqvrmi19qyyxqs1xwv03-vm-test-run-test

I don't have more time right now, but if somebody could adjust this NixOS test to show the problem, that would be great!

@rvl
Copy link
Contributor Author

rvl commented Dec 24, 2023

I don't have more time right now, but if somebody could adjust this NixOS test to show the problem, that would be great!

Here @infinisil, try this one:

# nixos-test.nix
let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/d6863cbcbbb80e71cecfc03356db1cda38919523";
  pkgs = import nixpkgs {
    config = {};
    overlays = [];
    system = "x86_64-linux";
  };

  user = "alice";
  target = "/home/${user}/file";
in
pkgs.nixosTest {
  name = "test";
  skipTypeCheck = true;
  nodes.machine = {
    system.extraDependencies = [
      (pkgs.closureInfo {
        rootPaths = [ pkgs.stdenvNoCC.drvPath ];
      })
    ];
    nix.package = pkgs.nixUnstable;
    nix.nixPath = ["nixpkgs=${nixpkgs}"];
    environment.etc."test-symlink.nix".text = ''
      { pkgs ? import <nixpkgs> {} }: let
        direct-symlink = pkgs.runCommand "direct-symlink" {} '''
          ln -vs ${target} $out
        ''';
        indirect-symlink = pkgs.runCommand "indirect-symlink" {} '''
          ln -vs ''${direct-symlink} $out
        ''';
      in
        indirect-symlink
    '';
    users.users.${user}.isNormalUser = true;
    systemd.tmpfiles.rules = ["f ${target} 0644 ${user} ${user} - test"];
  };

  testScript = ''
    start_all()
    print(machine.succeed('nix --version'))
    machine.succeed("su -l ${user} -c 'nix-build /etc/test-symlink.nix'")
    machine.succeed("su -l ${user} -c 'readlink -f result'")
    machine.succeed("su -l ${user} -c 'test `readlink -f result` = ${target}'")
  '';
}

I believe that the three necessary conditions for failure are:

  1. Symlink target is outside of /nix/store
  2. nix-build is invoked from a normal user, not root.
  3. nix.package = pkgs.nixUnstable;

@infinisil
Copy link
Member

Thanks, using bisection I was able to confirm that #8965 (as already suspected by @cole-h) indeed is the culprit for this regression.

@Ericson2314
Copy link
Member

When it does work like, what do the references look like? Is it possible the hardlinking was incorrectly following the symlink so we referencing paths not in our closure?!

@Artturin
Copy link
Member

Artturin commented Jan 8, 2024

Rudimentary workaround/fix #9723

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2024-01-08-nix-team-meeting-minutes-114/38156/1

dyfrgi added a commit to dyfrgi/dotfiles that referenced this issue Mar 8, 2024
This is very anti-Nix, but duplicates my old dotfile setup. From here it
will be possible to incrementally move configuration into Home Manager.

Note that as of today, this requires using nix version 2.18, which can
be installed with `sudo nix-env -i nix-2.18.1`. It may also be necessary
to explicitly restart the nix-daemon service with `sudo systemctl
daemon-reload` and `sudo systemctl restart nix-daemon.service`. This is
needed due to NixOS/nix#9579, which unfortunately is also not fixed in
nix 2.20.5, which is the new version in nixpkgs. It looks like
NixOS/nix#9723 will fix this and will hopefully land before nix 2.21.
nekowinston added a commit to nekowinston/dotfiles that referenced this issue Mar 11, 2024
@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/an-additional-nix-installed-by-home-manager/42298/1

@sdht0
Copy link

sdht0 commented Mar 31, 2024

I was just wondering: is this bug not considered a breaking change critical enough to be prioritized? Stable nix releases > 2.18 breaks home-manager users as per this bug.

Does the behavior being relied upon by home-manager not come under stability guarantees? Asking because the discourse report marked this as Annoying but not critical.

otavio added a commit to otavio/nix-config that referenced this issue Mar 31, 2024
Nix 1.19.2 fails to build a derivation containing a symlink to store path.

```nix
{ local ? "/home/rodney/ops/nixpkgs"
, pkgs ? import local {}
}: rec {
  direct-symlink = pkgs.runCommand "direct-symlink" {} ''
    ln -vs ${local}/.version $out
  '';
  indirect-symlink = pkgs.runCommand "indirect-symlink" {} ''
    ln -vs ${direct-symlink} $out
  '';
}
```

So we had to comment out the code below:

```nix
home.file."home-config" = {
  target = ".config/home-manager";
  source = config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/src/nix-config";
};
```

Refs:
- nix-community/home-manager#4692
- NixOS/nix#9579

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
otavio added a commit to otavio/nix-config that referenced this issue Mar 31, 2024
Nix 1.19.2 fails to build a derivation containing a symlink to store path.

```nix
{ local ? "/home/rodney/ops/nixpkgs"
, pkgs ? import local {}
}: rec {
  direct-symlink = pkgs.runCommand "direct-symlink" {} ''
    ln -vs ${local}/.version $out
  '';
  indirect-symlink = pkgs.runCommand "indirect-symlink" {} ''
    ln -vs ${direct-symlink} $out
  '';
}
```

Refs:
- nix-community/home-manager#4692
- NixOS/nix#9579

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
otavio added a commit to otavio/nix-config that referenced this issue Mar 31, 2024
Nix 1.19.2 fails to build a derivation containing a symlink to store path.

```nix
{ local ? "/home/rodney/ops/nixpkgs"
, pkgs ? import local {}
}: rec {
  direct-symlink = pkgs.runCommand "direct-symlink" {} ''
    ln -vs ${local}/.version $out
  '';
  indirect-symlink = pkgs.runCommand "indirect-symlink" {} ''
    ln -vs ${direct-symlink} $out
  '';
}
```

Refs:
- nix-community/home-manager#4692
- NixOS/nix#9579

Signed-off-by: Otavio Salvador <otavio@ossystems.com.br>
@rvl
Copy link
Contributor Author

rvl commented Apr 1, 2024

For me personally, it's a critical issue because my home-manager config which used to work nicely is now broken.

However I think home-manager could work around the issue by building symlinks within a nix store path directory, rather than as top-level nix store paths. So from that perspective it's "annoying but not critical."

For stability guarantees I guess we would need to know which behaviours (if not all) should be stable, and what does correct behaviour look like. Perhaps this is the more important issue. What is the meaning of a symlink at the top level of a nix store?

@alois31
Copy link
Contributor

alois31 commented Apr 9, 2024

Not only does this lead to "permission denied" errors when the symlink target is not accessible to the build user, it also introduces a huge impurity when it is.

@SrEstegosaurio
Copy link

I don't know but impermanence is pretty broken for me right now and by being in a root-on-tmpfs system this is quite critical.

roosemberth added a commit to roosemberth/dotfiles that referenced this issue Apr 10, 2024
NixOS/nix#9579 is still unresolved, as the
offending commit
(NixOS/nix@622191c)
is only present starting version 2.19.0, we can update to 2.18.x; this
way we can remove the insecure package rule.

Signed-off-by: Roosembert Palacios <roosemberth@posteo.ch>
thufschmitt pushed a commit to tweag/nix that referenced this issue Apr 10, 2024
Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix NixOS#9579
thufschmitt pushed a commit to tweag/nix that referenced this issue Apr 10, 2024
thufschmitt pushed a commit to tweag/nix that referenced this issue Apr 10, 2024
…o a symlink out of the store

Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix NixOS#9579

Co-authored-by: Artturin <Artturin@artturin.com>
@github-project-automation github-project-automation bot moved this from 🏁 Review to Done in Nix team Apr 11, 2024
@thufschmitt thufschmitt added backport 2.19-maintenance Automatically creates a PR against the branch backport 2.20-maintenance Automatically creates a PR against the branch backport 2.21-maintenance Automatically creates a PR against the branch backport 2.18-maintenance Automatically creates a PR against the branch and removed backport 2.18-maintenance Automatically creates a PR against the branch backport 2.19-maintenance Automatically creates a PR against the branch backport 2.20-maintenance Automatically creates a PR against the branch backport 2.21-maintenance Automatically creates a PR against the branch labels Apr 11, 2024
github-actions bot pushed a commit that referenced this issue Apr 11, 2024
Regression test for #9579

(cherry picked from commit 872d93e)
github-actions bot pushed a commit that referenced this issue Apr 11, 2024
…o a symlink out of the store

Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix #9579

Co-authored-by: Artturin <Artturin@artturin.com>
(cherry picked from commit 913db9f)
github-actions bot pushed a commit that referenced this issue Apr 11, 2024
Regression test for #9579

(cherry picked from commit 872d93e)
github-actions bot pushed a commit that referenced this issue Apr 11, 2024
…o a symlink out of the store

Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix #9579

Co-authored-by: Artturin <Artturin@artturin.com>
(cherry picked from commit 913db9f)
github-actions bot pushed a commit that referenced this issue Apr 11, 2024
Regression test for #9579

(cherry picked from commit 872d93e)
github-actions bot pushed a commit that referenced this issue Apr 11, 2024
…o a symlink out of the store

Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix #9579

Co-authored-by: Artturin <Artturin@artturin.com>
(cherry picked from commit 913db9f)
domenkozar pushed a commit to domenkozar/nix that referenced this issue Jun 14, 2024
Regression test for NixOS#9579

(cherry picked from commit 872d93e)
domenkozar pushed a commit to domenkozar/nix that referenced this issue Jun 14, 2024
…o a symlink out of the store

Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix NixOS#9579

Co-authored-by: Artturin <Artturin@artturin.com>
(cherry picked from commit 913db9f)
domenkozar pushed a commit to domenkozar/nix that referenced this issue Jul 5, 2024
Regression test for NixOS#9579

(cherry picked from commit 872d93e)
domenkozar pushed a commit to domenkozar/nix that referenced this issue Jul 5, 2024
…o a symlink out of the store

Bind-mounting symlinks is apparently not possible, which is why the
thing was failing.

Fortunately, symlinks are small, so we can fallback to copy them at no cost.

Fix NixOS#9579

Co-authored-by: Artturin <Artturin@artturin.com>
(cherry picked from commit 913db9f)
rnhmjoj added a commit to rnhmjoj/nixpkgs that referenced this issue Oct 13, 2024
Another attempt to bring ae48df3 while avoiding the Nix symlink bug[1].

[1]: NixOS/nix#9579
rnhmjoj added a commit to rnhmjoj/nixpkgs that referenced this issue Oct 13, 2024
Another attempt to bring ae48df3 while avoiding the Nix symlink bug[1].
I guess the bug was triggered by the sbin -> bin symlink in util-linux.

[1]: NixOS/nix#9579
rnhmjoj added a commit to rnhmjoj/nixpkgs that referenced this issue Oct 13, 2024
Another attempt to bring ae48df3 while avoiding the Nix symlink bug[1].
I guess the bug was triggered by the sbin -> bin symlink in util-linux.

[1]: NixOS/nix#9579
peterhoeg pushed a commit to peterhoeg/nixpkgs that referenced this issue Oct 24, 2024
Another attempt to bring ae48df3 while avoiding the Nix symlink bug[1].
I guess the bug was triggered by the sbin -> bin symlink in util-linux.

[1]: NixOS/nix#9579
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug regression Something doesn't work anymore
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

10 participants