-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
[OS X] Derivation fails with sandbox #4119
Comments
For me the derivation that fails when I try to build with sandbox on macOS is my home-manager config.
|
Bumping because I just experienced this issue with Nix 2.4 (2.4pre20201201_5a6ddb3) when building a home-manager config via nix flakes. error: --- Error ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
builder for '/nix/store/v75p8mffw7l7pg2pxdwqjfzx89rks8b2-home-manager-path.drv' failed with exit code 65; last 1 log lines:
sandbox-exec: pattern serialization length 66460 exceeds maximum (65535)
error: --- Error ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
1 dependencies of derivation '/nix/store/8hpb5b7l19y2267dn11cbi4ilx67ribk-home-manager-generation.drv' failed to build
error: --- Error ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
1 dependencies of derivation '/nix/store/pjjh7a238hwjkvkvhmbmazrzk41jsyz5-user-environment.drv' failed to build
error: --- Error ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
1 dependencies of derivation '/nix/store/vskz1pxb41sv66irwx2689f39b8hnkld-activation-bbuscarino.drv' failed to build
error: --- Error ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
1 dependencies of derivation '/nix/store/ak7vwn1z37ymjv192iyl1v2fc5ibkwnx-darwin-system-21.03.20210209.74335e0+darwin4.dca3806.drv' failed to build |
hashtag me2
|
So it seems the generated sandbox profile has an s-expression exceeding the limit when running with nix --debug
I'm assuming splitting these statements into smaller blocks will fix this. |
@toonn something to put on the list for https://opencollective.com/nix-macos |
@toonn I went through Nix issues concerning macOS sandboxing and this is the only one left reported to fix. It needs research when the limit kicks in and what's the workaround (maybe we have to use |
I'd not be surprised that the limit is 65535, but that's hard to determine from counting the packages, because I think there's one sandbox item entry for every nix store path. I did read a bit about the sandbox specification from osx developer manual, and started attempting to write a fix by batching these in multiple files (which is totally possible, importing .sb files). But my lack of c++ knowledge, and especially modern c++ as is in the nix repo, got the better of me.
|
I marked this as stale due to inactivity. → More info |
Having a sandbox on macOS is still a worthy goal.
For the record, were you able to confirm that importing from multiple files is sufficient to bypass the limit? I tried experimenting a little, and I think the serialization limit is at a lower level. I made two files with ~800 store paths in them, and a top-level file to import them.
If it's not possible to encode the strict nix sandboxing scheme, could we still have a sandbox that prevents access to things outside of the store path? I think this could still help a lot with purity. |
I just ran into this myself. What I find especially interesting/frustrating is that I ran into it while performing a I really want to keep the macOS sandbox. If there's no way to get around this by splitting things up, I wonder if we could do something like generate regexes that match multiple paths with a single pattern. I don't know what regex dialect it is but I've never seen one that doesn't have alternations. At the very we could remove Assuming this works, there is a limit to how much space could be saved this way (and I question whether constructing a massive regex with alternations would affect performance; if it internally converts literals and subpaths into regexes already then there should be no difference), but anything to increase the size would help. And if we can accurately predict the serialization size we could also have a degraded fallback mode where we start allowing extra files if it means writing fewer rules in order to stay under the size. Jumping all the way to |
Incidentally it sounds like older versions of macOS had a command |
Just hit this as well on a
|
Sets `__noChroot = true` on select `buildEnv` derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`.
Sets `__noChroot = true` on select `buildEnv` derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`.
Sets `__noChroot = true` on select `buildEnv` derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`.
Sets `__noChroot = true` on select `buildEnv` derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`.
Sets `__noChroot = true` on select `buildEnv` derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`.
Allows setting `__noChroot = true` on select derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`. I wish there was a way to do something akin to overlays for config, alas there is not afaik, so the only way is to add an option. Since this is opt-in, anyone enabling it thus understands the “risks” of disabling the sandbox, however the risk for these derivations should be fairly low, and this allows enabling the sandbox more generally on Darwin, which is beneficial. I have only added to the derivations that started giving me problems, others may suffer from others but these are definitely likely to have huge dependency lists therefore exposing the problem. Despite this being intended only for use on Darwin, it is left somewhat generic and thus up to the user to do set it to e.g. `stdenv.hostPlatform.isDarwin`.
If anyone is looking to reproduce the error manually, there is likely a better way, but here are my steps:
$ nix build --debug \
/nix/store/8c1h3pifzs3xpfazfvcqbikgd5mf61j9-darwin-system-23.05.20230908.3fbd2a2+darwin4.511177f.drv \
&> sandbox.sb
$ sandbox-exec -f ./sandbox.sb -D _GLOBAL_TMP_DIR=/tmp/foo echo fake
sandbox-exec: pattern serialization length 75123 exceeds maximum (65535) (Would likely replace |
Trying @lilyball's suggestion:
I used the following nvim replacement:
Running the below line count pre and post gives the same result, so it doesn't look like any additional paths can be removed (I thought perhaps there would be multiple binaries from the same package listed):
Afterwards, I get farther(?), so it seems like this is probably a valid temporizing measure:
Rereading the debug output, looks like I'm using the wrong approach for building, but this doesn't work either (even though I have execute permissions for this $ sandbox-exec \
-f ./sandbox.sb \
-D _GLOBAL_TMP_DIR=/tmp/foo \
/nix/store/7avcas47b0g25c9bk7m4xb7p5p636qs7-bash-5.2-p15/bin/bash \
-e /nix/store/6xg259477c90a229xwmb53pdfkn6ig3g-default-builder.sh
sandbox-exec: execvp() of '/nix/store/7avcas47b0g25c9bk7m4xb7p5p636qs7-bash-5.2-p15/bin/bash' failed: Operation not permitted |
Is it possible that this could be fixed with one more layer of indirection? Suppose we were to create a chroot and mount in all the store dependencies, could we reduce the number of store paths in the sandbox profile to only the chroot directory? Edit: I suppose the lack of bind mounts would make this impossible. |
I do wonder how much mileage we could get by doing things like having a single regex that matches multiple store paths (as an extension on the idea of "use a regex to match up to the hash") to save even more characters, but I don't know how the "pattern serialization length" is calculated and it's plausible that it's already basically joining all paths with the same perms into a single pattern internally. |
I found a gist that had some notes on experiments done for this problem which seemed to suggest the patterns were all reduced prior to sending to the kernel. Let me see if I can dig it up... https://gist.github.com/rrbutani/16c7c66202ed47b2a5dd8cb5e916fb0a Their experiments seemed to suggest that I do wonder what might be done with |
That gist is interesting. Mentions:
I quickly patched nix to use
when I try to |
The sandbox format is famously undocumented. As far as I know the best resource is the pdf linked in the bottom of the gist. |
The file exists in the macOS SDK (as provided by Xcode), but it really doesn't have very much in it, just the declarations of the stuff documented in |
I see. Welp. I'm definitely at a loss. Maybe there could be something insome posts about reverse engineering |
Allows setting `__noChroot = true` on select derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`. I wish there was a way to do something akin to overlays for config, alas there is not afaik, so the only way is to add an option. Since this is opt-in, anyone enabling it thus understands the “risks” of disabling the sandbox, however the risk for these derivations should be fairly low, and this allows enabling the sandbox more generally on Darwin, which is beneficial. I have only added to the derivations that started giving me problems, others may suffer from others but these are definitely likely to have huge dependency lists therefore exposing the problem. Despite this being intended only for use on Darwin, it is left somewhat generic and thus up to the user to do set it to e.g. `stdenv.hostPlatform.isDarwin`.
How about something along the lines of:
Builders like This gets us one step closer to enabling the sandbox on by default. It doesn't have to be perfect. Any step we can make towards the sandbox being more usable is a worthy step imo. |
Allows setting `__noChroot = true` on select derivations that assemble large numbers of paths. This may be used to avoid sandbox failures on darwin, see NixOS/nix#4119 and the `sandbox` option in `man nix.conf`. I wish there was a way to do something akin to overlays for config, alas there is not afaik, so the only way is to add an option. Since this is opt-in, anyone enabling it thus understands the “risks” of disabling the sandbox, however the risk for these derivations should be fairly low, and this allows enabling the sandbox more generally on Darwin, which is beneficial. I have only added to the derivations that started giving me problems, others may suffer from others but these are definitely likely to have huge dependency lists therefore exposing the problem. Despite this being intended only for use on Darwin, it is left somewhat generic and thus up to the user to do set it to e.g. `stdenv.hostPlatform.isDarwin`.
I made a little patch to tinker on this, including the below: diff --git a/src/libstore/unix/build/local-derivation-goal.cc b/src/libstore/unix/build/local-derivation-goal.cc
index 72125cb82..0ff9739d0 100644
--- a/src/libstore/unix/build/local-derivation-goal.cc
+++ b/src/libstore/unix/build/local-derivation-goal.cc
@@ -2012,7 +2012,14 @@ void LocalDerivationGoal::runChild()
#if __APPLE__
else {
/* This has to appear before import statements. */
- std::string sandboxProfile = "(version 1)\n";
+ debug("I should be outputting version 3 here");
+ std::string sandboxProfile = "(version 3)\n";
+ sandboxProfile +=
+ #include "system.sb"
+ ;
+ sandboxProfile +=
+ #include "dyld-support.sb"
+ ;
if (useChroot) {
@@ -2045,11 +2052,7 @@ void LocalDerivationGoal::runChild()
}
/* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */
- if (settings.darwinLogSandboxViolations) {
- sandboxProfile += "(deny default)\n";
- } else {
- sandboxProfile += "(deny default (with no-log))\n";
- }
+ sandboxProfile += "(deny default)\n";
sandboxProfile +=
#include "sandbox-defaults.sb" However, when I run I assume it can't be caching some kind of build artifact (because this is nix) but I tried a |
@n8henrie, isn't libstore used by the daemon rather than nix the command? You'd have to replace your daemon, not just invoke the command based on that change. |
Thanks, that's what I was wondering, just confused as the Unfortunately it seems like a dead end; in the interim I copied a "serialization too long" sandbox file changed it to |
Following @lilyball from above:
Might it also be possible / make sense to save the repetition of |
Not a solution to the bigger issue here, but tonight I finally sat down and looked at the sandbox profiles in the I whipped together a little script to try to see if there was a common theme that was making it so big: $ awk -F'"' '/subpath/ { print $2 }' sandbox-three.sb |
awk -F- '{ for (i=2;i<=NF;i++) { print $i }}' |
grep -v -e '^[0-9.]\+$' -e 'rev=' |
sort |
uniq -c |
sort -n |
tail
14 c
14 lib
16 man
32 perl5.38.2
39 framework
40 apple
51 python3.11
278 treesitter
278 vimplugin
559 grammar 559 lines of treesitter grammars (due to using Curiously, I pared this down to about 60 languages that I ever use, and it only brought my sandbox file down to 1067 lines (but seems to have dramatically reduces the number of
Regardless, it made enough of a difference to avoid the sandbox error for now (instead of just using |
Previously, we ran into NixOS/nix#4119 with the homeConfigurations builds. But thanks to comments there, I managed to reduce the “pattern serialization length” enough to allow the builds to succeed.
Previously, we ran into NixOS/nix#4119 with the homeConfigurations builds. But thanks to comments there, I managed to reduce the “pattern serialization length” enough to allow the builds to succeed.
Previously, we ran into NixOS/nix#4119 with the homeConfigurations builds. But thanks to comments there, I managed to reduce the “pattern serialization length” enough to allow the builds to succeed.
Previously, we ran into NixOS/nix#4119 with the homeConfigurations builds. But thanks to comments there, I managed to reduce the “pattern serialization length” enough to allow the builds to succeed.
Describe the bug
When running a sandboxed build on OS X, a derivation fails with
sandbox-exec: pattern serialization length 71710 exceeds maximum (65535)
If you have a problem with a specific package or NixOS,
you probably want to file an issue at https://github.com/NixOS/nixpkgs/issues.
Steps To Reproduce
Create a derivation with a sufficiently large number of inputs, and attempt to build it.
Expected behavior
The derivation builds
nix-env --version
output2.3.7
Additional context
I have done a bit of digging and it seems most likely that this is due to the fact that the OS X sandbox config is created by building a pattern mapping every path in the dependency closure of the derivation to a path in the sandbox individually:
nix/src/libstore/build.cc
Lines 3706 to 3729 in d761485
The text was updated successfully, but these errors were encountered: