Accidentally mutated an input when building an output

Hello, this is my first post here.

As a nix newbie I made a mistake involving $src and $sourceRoot because I did not understand what I was doing. It looked like this:

sourceRoot = "${src}/someSubFolder";
patches = [ ... ];

I know, this is outrageous…
However, in retrospect, I’m surprised that this did not cause my build to fail with some permission error. It failed when I built it again with slight changes (same src, sourceRoot and patches), though, because the patch had already been applied. It means that nix-build has modified the content of an already existing output. In doing so, it has even modified the access rights of some of the directories in that output.

Note: Since I am on Linux and did not configure anything, I believe my builds are sandboxed.

I though that nix was taking care of only giving write access to the outputs, am I wrong? I can’t find any reference about that, though and could only find the following in the nix 1.2 release notes:

Nix no longer sets the immutable bit on files in the Nix store. Instead, the recommended way to guard the Nix store against accidental modification on Linux is to make it a read-only bind mount, like this:

$ mount --bind /nix/store /nix/store
$ mount -o remount,ro,bind /nix/store

Nix will automatically make /nix/store writable as needed (using a private mount namespace) to allow modifications.

It seems that the advice above would not have prevented my mistake to mutate the store, though. Am I missing something? Should I make a bug report or is this “undefined behaviour”?

PS: it is an instance of the “odd uses of $src” listed in Odd uses of $src in packages but seemed more “plain wrong” that “odd”, so I settled for creating a new thread.

2 Likes

Can you show the output of nix-info -m please?
Usually this can only happen when the sandbox is disabled.

Here it is:

 - system: `"x86_64-linux"`
 - host os: `Linux 4.18.16-300.fc29.x86_64, Fedora, 29 (Workstation Edition)`
 - multi-user?: `no`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.3.4`
 - channels(deubeuliou): `"nixpkgs-20.09pre221814.10100a97c89"`
 - nixpkgs: `/home/deubeuliou/.nix-defexpr/channels/nixpkgs`

I had a similar case when substitute would overwrite the files in a store [1].

@deubeuliou Does unshare -m or unshare -U work for your user?

[1] substitute() can overwrite existing files in store if Nix is ran without sandboxing · Issue #31547 · NixOS/nixpkgs · GitHub

1 Like

From what I understand, sandboxing is not compatible with single-user. I think I installed Nix without the --no-daemon option but my distribution has SELinux which in turn is said not to be compatible with multi-user.

There seems to have been an effort to support SELinux: Workgroup:SELinux - NixOS Wiki and it looks daunting.

@veprbl: unshare -U doesn’t but unshare -m does. I suppose the latter would at least help preventing accidental changes, sandboxing notwithstanding?

Actually, it should work without the user namespaces [1], try setting sandbox-fallback to false [2].

[1] https://github.com/NixOS/nix/blob/90b3b31dc27f31e9b11653a636025d29ddb087a3/src/libstore/build.cc#L2362-L2369
[2] https://github.com/NixOS/nix/blob/90b3b31dc27f31e9b11653a636025d29ddb087a3/src/libstore/globals.hh#L217-L218