Cannot bind and listen to port with macOS sandbox, even with __darwinAllowLocalNetworking
Describe the bug
See title.
Steps To Reproduce
- Use Nix 2.21.0 or later, on macOS, with the sandbox enabled
-
nix-build --expr 'let pkgs = (import <nixpkgs> {}); in pkgs.runCommand "test" { __darwinAllowLocalNetworking = true; } "${pkgs.lib.getExe pkgs.socat} TCP-LISTEN:12345,bind=127.0.0.1 -"'
Results in E bind(5, {LEN=16 AF=2 127.0.0.1:12345}, 16): Operation not permitted
Expected behavior
To be able to bind and listen to a port, but not receive inbound connections from non-localhost remotes.
nix-env --version output
nix-env (Nix) 2.23.3
Additional context
Broken in d60c3f7f7c83134b5b4470ed84b6d5ed38e28753 (from https://github.com/NixOS/nix/pull/10078).
Adding (allow network-bind) to the sandbox profile seems to get a bit further, but ultimately fails with E listen(5, 5): Operation not permitted. (I did this testing with sandbox-exec and the profile directly to avoid rebuilding Nix.)
I’m not sure if this is actually solvable without opening a hole in the sandbox, though. I’ve experimented a bit with the profile and I can’t see a way to allow binding and listening without also allowing any inbound connection to it. Never mind that arguably even allowing local inbound allows breaking out of the sandbox as it still allows coordination and communication with other local processes. Maybe that’s “acceptable”, though.
One possible alternative would be to require a separate application that uses the macOS Network Extension API to filter based on process. That would complicate the Nix install process, though, and not really sure if it would be able to do what we would want.
So I don’t necessarily expect this bug to be fixed in a “secure” soon, but want to at least document it as many of the uses in nixpkgs of __darwinAllowLocalNetworking = true in nixpkgs likely exist to allow listening to a port. To be honest, I think this bug essentially means __darwinAllowLocalNetworking = true does nothing useful. There are currently 360 uses of it in nixpkgs—I expect them all to fail, sadly, but I haven’t yet tried to build them all.
Finally, Nix could probably really use some automated tests of the macOS sandboxing, especially given how completely undocumented the upstream APIs are.
Priorities
Add :+1: to issues you find important.
Unfortunately, this attribute is not documented, making it hard to triage. I've added it to the team board.
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
https://discourse.nixos.org/t/2024-08-12-nix-team-meeting-minutes-168/50561/1
https://discourse.nixos.org/t/2024-08-12-nix-team-meeting-minutes-168/50561/1
Binding to a port should always work, regardless of this flag.
We don't have a network namespace, so the port might be taken. This does not seem to be the case. Also the number is >1024 so probably not a privileged port.
Not related to the recent GHSA-q82p-44mg-mgh5 (diff) or GHSA-2ffj-w4mj-pg37 (diff)
Operation not permitted should be EPERM, which is not listed on the darwin bind manpage
Can probably be lifted by configuring the sandbox ((allow network-bind) as suggested). Does this have undesirable side effects?
Which version of macOS is this? It could be a regression caused by Apple.
@L-as: do we have a macOS user in the Nix team? Maybe ask on discourse? Most of us have access to macOS, but do not use it daily.
It could be a regression caused by Apple.
That seems unlikely given https://github.com/NixOS/nix/commit/d60c3f7f7c83134b5b4470ed84b6d5ed38e28753? Or do you just mean the failure after (allow network-bind)?
https://github.com/NixOS/nix/pull/11270 seems fine to me as a fix, given that we were apparently allowing arbitrary network communication before and nobody even noticed. Stopping information leaks with the Darwin sandbox is not really a realistic goal.
d60c3f7
:facepalm: :facepalm: :facepalm:
yeah
Closing as https://github.com/NixOS/nix/pull/11270 is merged.