-
-
Notifications
You must be signed in to change notification settings - Fork 159
[RFC 0097] Unset read permission bit on /nix/store for other users #97
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
8328598
[RFC 0097] Unset read permission bit on /nix/store for other users
L-as 2ecb1fc
fixup! [RFC 0097] Unset read permission bit on /nix/store for other u…
L-as 3333ded
fixup! fixup! [RFC 0097] Unset read permission bit on /nix/store for …
L-as f35e0c9
fixup! fixup! fixup! [RFC 0097] Unset read permission bit on /nix/sto…
L-as 78a5b82
fixup! fixup! fixup! fixup! [RFC 0097] Unset read permission bit on /…
L-as 82b553f
fixup! fixup! fixup! fixup! fixup! [RFC 0097] Unset read permission b…
L-as 3428565
fixup! fixup! fixup! fixup! fixup! fixup! [RFC 0097] Unset read permi…
L-as 1f78c9a
fixup! fixup! fixup! fixup! fixup! fixup! fixup! [RFC 0097] Unset rea…
L-as 5d26444
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! [RFC 0097] Un…
L-as fc5a0da
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! [RFC 0…
L-as 31ecff2
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
L-as a1a85dd
fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup!…
L-as File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| --- | ||
| feature: no-read-store-dir | ||
| start-date: 2021-07-04 | ||
| author: Las Safin | ||
| co-authors: | ||
| shepherd-team: @kevincox @7c6f434c @edolstra | ||
| shepherd-leader: @edolstra | ||
| related-issues: | ||
| --- | ||
|
|
||
| # Summary | ||
| [summary]: #summary | ||
|
|
||
| Set the permissions for `/nix/store`, `/nix/store/.links` and `/nix/store/trash` to 1771 instead of 1775, disabling reading the directory for other users. | ||
|
|
||
| # Motivation | ||
| [motivation]: #motivation | ||
|
|
||
| This is a simple change that acts as an extra layer of security by making | ||
| it harder to access store paths that programs don't need to access. | ||
|
|
||
| For a directory, being able to execute without being able to read it means | ||
| that you can access paths inside the directory, if and only if you know the path beforehand, | ||
| since you can not list the directory entries. | ||
|
|
||
| In our case, with this change, all users that are not root and are not part of nixbld, | ||
| will only be able to directly access paths inside `/nix/store` which they already know, | ||
| i.e. the hash and the name. | ||
| If you run some program that does not have access to the nix daemon under such | ||
| a user, it will not be able to search the store for built system configurations, | ||
| but will instead have to find the path to one through e.g. `/nix/var/nix/profiles/system` (if accessible). | ||
|
|
||
| For tight sandboxes under NixOS, where only the store paths needed are mounted, | ||
| this is not very important, since they can already only access the ones they need, | ||
| however, this feature is useful for making sandboxes that have access to the entirety | ||
| of `/nix/store`, where you want to be sure that any store path encountered inside the sandbox | ||
| can be accessed. This will often happen when you want a quick sandbox with bubblewrap where | ||
| it's too much of a pain to manually find all store paths you need. | ||
| This type of sandbox can still be secure, granted that you are careful not to "leak" store paths | ||
| into the sandbox, which is not trivial but not impossible either. Specifics are discussed in [Drawbacks](#drawbacks). | ||
|
|
||
| NB: While this change is simple, it is not possible for end-users to do without changing Nix, since at the moment any | ||
| `nix` command will reset the permissions back to 1775. | ||
|
|
||
| # Detailed design | ||
L-as marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| [design]: #detailed-design | ||
|
|
||
| Set the 1775 | ||
| in [nixpkgs/nixos/modules/system/boot/stage-2-init.sh](https://github.com/NixOS/nixpkgs/blob/8284fc30c84ea47e63209d1a892aca1dfcd6bdf3/nixos/modules/system/boot/stage-2-init.sh#L62), | ||
| in [nix/scripts/install-multi-user.sh](https://github.com/NixOS/nix/blob/cf1d4299a8fa8906f62271dcd878018cef84cc30/scripts/install-multi-user.sh#L577), | ||
| in [nix/src/libstore/globals.hh](https://github.com/NixOS/nix/blob/ba8b39c13003c8ddafb6bec308997e09b9851c46/src/libstore/globals.hh#L278), | ||
| in [nix/src/libstore/build/local-derivation-goal.cc](https://github.com/NixOS/nix/blob/6182ae689826554d915b4ed72e07f7978dc1d13c/src/libstore/build/local-derivation-goal.cc#L641), and | ||
| in [nix/src/libstore/local-store.cc](https://github.com/NixOS/nix/blob/0a535dd5ac93576f7152d786464e330ae3d46b50/src/libstore/local-store.cc#L181) | ||
| to 1771. | ||
|
|
||
| `/nix/store/trash` and `/nix/store/.links` will also have to have their read bit removed, resulting in 0751. | ||
|
|
||
| Various parts of NixOS also ought have their permissions fixed, which is beneficial with and without this change. | ||
| Specifically, the permissions for these things ought to be looked at again: | ||
| - `/proc/cmdline` | ||
| - `/proc/sys` | ||
| - `/proc/config.gz` | ||
| - The other `/proc/*` stuff | ||
| - `dmesg` | ||
| - The nix daemon | ||
|
|
||
| Sandboxes should preferably not have access to the above in any case. | ||
|
|
||
| Nothing else has to be done likely, since setting the store permissions to `1771` manually doesn't break | ||
| anything other than what is mentioned in this document (though it is undone if you run a `nix` command). | ||
|
|
||
| # Examples and Interactions | ||
| [examples-and-interactions]: #examples-and-interactions | ||
|
|
||
| Losing the read (r) bit means that you can't list the files inside the store. | ||
| The execute (x) bit allows us to `cd` to it and also access paths inside the store. | ||
|
|
||
| E.g. `ls "$(readlink /nix/var/nix/profiles/system)"` will still work, since this is a directory | ||
| inside the store, and not the store itself, but an unprivileged user can't `ls /nix/store` to find the system configuration. | ||
|
|
||
| # Drawbacks | ||
L-as marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| [drawbacks]: #drawbacks | ||
|
|
||
| It might be a slight annoyance since shell completion won't work in the `/nix/store` anymore, e.g. | ||
| if you have some hash 48914, you wouldn't be able to type `/nix/store/48914<tab>` to get the full path anymore. | ||
| This is likely the biggest drawback. | ||
|
|
||
L-as marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| External tooling that does a traversal of the nix store (`find`, `du -s`, `ncdu`) would need `sudo` or explicitly given permissions. | ||
|
|
||
| A sandboxed program could still have some idea of how the host machine is used by checking each store path that Hydra has ever built, | ||
| then it could estimate whether the host machine has e.g. Tor on it. | ||
|
|
||
| Attempting to have security comparable to bind-mounting each necessary store path inside a sandbox is not easy, | ||
| since you need to be careful not to leak paths to the sandbox through global state, for example `/proc/cmdline`. | ||
| There is no easy way to know whether some path is readable from inside the sandbox, since the problem is | ||
| essentially proving that the sandbox doesn't have access to some secret that in this case is the store path itself. | ||
| Since Unix software has not traditionally treated paths as secrets, this is a bit problematic if you're | ||
| trying to make sure your sandbox can't access some path. We also can not know how future kernel interfaces and such | ||
| will be, and they will likely not have the same considerations for "paths as secrets" as us. | ||
| Essentially, you have to consider the store paths as encodings of their contents wrt. sandboxes. | ||
|
|
||
| The above points about sandboxed programs are not negative effects of changing the permissions of /nix/store and such, | ||
| but rather considerations for making use of this change in the context of sandboxes. | ||
|
|
||
| # Alternatives | ||
| [alternatives]: #alternatives | ||
|
|
||
| If Nix was made to not reset the permissions of /nix/store back to 1775, users who want this change could | ||
L-as marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| do it themselves by simply putting this into their configuration.nix: | ||
| ```nix | ||
| { | ||
| system.activationScripts.chmod-store.text = '' | ||
| ${pkgs.util-linux}/bin/unshare -m ${pkgs.bash}/bin/sh -c '${pkgs.util-linux}/bin/mount -o remount,rw /nix/store ; ${pkgs.coreutils}/bin/chmod 1771 /nix/store ; ...' | ||
| ''; | ||
| } | ||
| ``` | ||
|
|
||
| Traditional sandboxing could be seen as an alternative to this, however, they are not mutually exclusive, | ||
| since this change is fundamentally just changing some permissions. | ||
| Improving the permissions for /nix/store will not decrease security for traditional sandboxes. | ||
|
|
||
| # Unresolved questions | ||
L-as marked this conversation as resolved.
Show resolved
Hide resolved
L-as marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| [unresolved]: #unresolved-questions | ||
|
|
||
| There doesn't seem to be any. | ||
|
|
||
| # Future work | ||
| [future]: #future-work | ||
|
|
||
| Future work includes fixing the permissions of global state in NixOS, notably access to the nix daemon, much of the kernel API, such as `/proc`. | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.