I'm attempting to create an application that uses a System Extension / Network Extension to implement a PacketTunnelProvider.
After creating and configuring the packet device, I want to spawn a child process to do the actual reading and writing of network packets. I want to do this because the child is written in Go (it uses wireguard-go and my company's Go-SDK).
When I call posix_spawn
from within the System Extension, I get "Operation not permitted" as the error, and sandboxd
drops a log with
Violation: deny(1) process-exec* /private/var/root/Library/Containers/<my system extension>/Data/Documents/<my-child-binary>
Is it possible to execute other processes from within the System Extension sandbox? Do the binaries have to be stored in a particular place, and if so, where?
I attempted to build with the App Sandbox removed from the System Extension capabilities, and this seemed to fail before even executing my Network Extension code, so I'm guessing System Extensions are required to be sandboxed, but it would be nice to have that confirmed.
First off, following up on myself...
I'm not sure if this is something I'd rely on or not, but I've pinged the network extension team for their thoughts...
The answer from the network extension team is basically, yes, this will work on macOS. It isn't something they specifically designed for or recommend, but the need to support preexisting VPN solutions meant that they used a much broader sandbox configuration on macOS than they do on iOS. You shouldn't assume this will work in all extension points, but it does work in this case for the reasons below.
I'm sorry, but again, are you sure that's the case, or is this another instance of what you "expect" to be?
Call it a complicated mix of all three. More specifically:
-Extension point hosts are in full control of their extensions sandbox. If you're curious, you can actually see the definition in the Info.plist of any framework which defines an extension point. Look for a dictionary called "NSExtensionSDK" and you'll find key "NSExtensionSandboxProfile". You can look at the Quicklook framework as a more "complete" example.
-Some extension points (including NetworkExtension) don't define the key on macOS. That means they end up falling back to the "default" sandbox... which is currently "application.sb".
With all that context, let me jump back to your original message here:
When I call posix_spawn from within the System Extension, I get "Operation not permitted" as the error, and sandboxd drops a log with
-
Are you actually testing with the network extension "installed" (meaning, inside "/Applications/") or are you running it from "inside" Xcode's directories?
-
Is the tool you're trying to run embedded in your extensions bundle or is it located "somewhere" else?
I'd expect the embedded case to "just work, but if it's inside your extension and it's still failing, then I think you're hitting a weird edge case caused by the the interactions between who launched you (the hosting process), the user context ("root") you're running in, and the sandbox system.
However, that won't be an issue when the app is actually installed in "/Applications/". I didn't go into this in my previous message, but the reason this works:
I've been continuing to experiment, and I've found I can exec binaries located in /Library/, so I don't believe this information is accurate.
...is that the default sandbox allows read access to a number of system wide directories, which includes "/Applications/".
In my testing, I'm able to exec files in /var/root/Downloads if I set Downloads to read/write in the signing capabilities for my System Extension, and unable to exec if I don't set this permission.
Yes, that comes from application.sb. However, just to be clear, I would not use "/var/root" (or the root user's home directory) as a data storage location. Two somewhat contradictory issues:
-
It basically exists because the system/OpenDirectory "expects" users to have home directories and it was easier to provide a home directory than to try and provide a special case solution for "root". To the extent it's "useful", it should be used for root's "user" (for example, shell configuration) data, not system wide data.
-
It is a true "home directory", which means there isn't any guarantee that it's actually in "/var/root". I'm sure it's not common but it is possible to relocate that directory, creating a whole new layer of complication.
I'd really like someone from the network extension team to weigh in, if possible.
My answer above came directly from them.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware