Google SAPI: Generate sandboxes for C/C++ libraries automatically
github.com
github.com
P.S. Yeah, I wish we had a better userspace Linux namespace toolkit instead of Docker.
I just want to run my apps with a separate TCP port namespace :)
so the popularity of containers (namespaces) and the entire ecosystem of tools like this (dating all the way back to chroots and bsd jails) basically says to me that maybe a fresh approach to security features in an operating system would lead to less complexity than what has needed to be built on top of good ol' unix.
(And I don't think they were ever intended as a security feature.)
The SAPI solution seems pretty straightforward to me. Jail the particular library into a sandboxed process and IPC with it transparently. Compatibility will be tricky (especially for libraries that is more complicated). But the solution itself is straightforward and I can see it work.
Unfortunately the above then often crosses the line over into "protecting the user from actually accomplishing useful stuff". The file sandboxing approaches I've seen so for e.g. commonly ignore the existence of file formats that don't consist of a single, atomic file.
I think you might want to take a look at https://fuchsia.dev/ - although I haven't worked with it myself so far, the stated goals might be somewhat in line with what you're proposing here.
"Linux kernel with support for UTS, IPC, user, PID and network namespaces"
If you can stomach the perf tradeoffs, compiling to WASM is much easier than this
I've never used this API but the cross process synchronization stuff seems like a difficult nut to crack. I'm curious which bits you think are unnecessarily baroque.
> If you can stomach the perf tradeoffs, compiling to WASM is much easier than this
I'm not super familiar with WASM, but it's unclear to me how compiling to that target addresses the problems that are addressed by this system? Does WASM have built-in security policies and sandboxing? Is it easy to call into a WASM-compiled library from your native C/C++ program? How?
Yes, WebAssembly is sandboxed. https://webassembly.org/docs/security/
This WASM? https://www.theregister.com/2021/11/04/webassembly_stack_can...
The castle walls stand, yet everything burns thanks being able to turn a candle into the table.
This doesn't apply obviously to cases where you design around having a sandbox, and at that point, I think the differences between something like WASM and SAPI or whatever are a lot murkier and more technical.
One thing about WASM that I feel is worth mentioning, which isn't technical so much as social, is that there's a lot of appeal/interest around simply "lift-and-shift" existing native code onto webassembly runtimes. That's good because that existing code is useful, but those apps aren't often designed with such sandbox architectures in mind. They often are designed (or at least consider) having binary-level mitigations applied, though. So I think this natural overlap in the set of use cases people have is what might give people pause. This is similar to the seccomp problem; retrofitting is a very big appeal even though it has some conceptual issues. This isn't some kind of indictment but if you're going to do an honest evaluation of these approaches I feel this background is worth keeping in mind.
I think if you designed an app with a sandbox architecture by default the best sandbox is the one you trust, WASM vs whatever be damned.
The doc claims that it's "almost identical"
> The Sandboxed API project (SAPI) aims to make sandboxing of C/C++ libraries less burdensome: after initial setup of security policies and generation of library interfaces, an almost-identical stub API is generated (using a template-based programming variable hierarchy system), transparently forwarding calls using a custom RPC layer to the real library running inside a sandboxed environment.
Are you claiming that this documentation is misleading?
https://github.com/google/sandboxed-api/blob/main/sandboxed_...
So it adds extra state, that needs to be initialized, adds extra failure points than needed to be handled in the code (sandbox initialization can fail, the RPC layer can fail itself), need to wrap some data structures so they can be passed through (you can't just pass pointers as-is).
I wonder how callbacks can be passed, but maybe that's actually less problematic than data pointers.
capnproto supports passing callacks/interfaces back via its capabilities mechanism.
IIUC the interesting trick behind SAPI is that it generates the wrapper for you based on parsing the library public API. Perhaps I misunderstood something.
The aim of SAPI is a bit different than whole-process sandboxing. It's about retaining the original running speed (and lack of sandboxing constraints) of the main project part, while making sure that only some parts are isolated (sandboxed), and the programming interfaces to the sandboxed parts still look familiar.
I'm not that well-versed into how WASM works when it tries to integrate with the rest of OS. But I'd assume it's some form of whole-process sandboxing, where practically all code is WASMized, and only some kind of loaders and trusted stubs are written in native assemblers (something has to invoke syscalls in the end).
In this case one can use Sandbox2, which is part of SAPI, though not very prominently exposed - https://github.com/google/sandboxed-api/tree/main/sandboxed_.... It's a full-featured Linux sandbox in its own rights, with C++ API. Examples might be englightning: https://github.com/google/sandboxed-api/tree/main/sandboxed_...
Any plans to create more sandboxes like this for other platforms like Windows and Mac?
Not the same software, but "almost" the same underlying tech is used (e.g. SAPI/Sandbox2 used ptrace for process tracking and debugging, and to my knowledge Chrome Linux sandboxes don't).
> Any plans to create more sandboxes like this for other platforms like Windows and Mac?
Linux is so far a priority, but it might be technically possible to make the actual software isolation layer modularized, so it would support various underlying tech (various OSes, or even different tech under a single OS).
Can this log the RPC calls around the target C library? Or potentially even replay calls in isolation? The latter could be expensive for non-trivial programs (require saving all synchronized memory state?), but might be more viable with binary diffs of the shared state if the client side doesn't modify the synchronized memory too much.
The zlib example is a bit baffling to be honest. If zlib goes in to an infinite 100% CPU loop, perhaps due to a zip bomb, you're still screwed as far as I can tell
A full RPC abstraction also gives you the opportunity to change out the backend implementation that this doesn't.
You can set CPU and wall time limits and the sandbox will be killed if it runs for longer.
> A full RPC abstraction also gives you the opportunity to change out the backend implementation that this doesn't.
Absolutely, but the RPC mechanism in SAPI is an implementation detail and ideally not something you should have to care about. You can of course just use the Sandbox2 part of Sandboxed API and implement an RPC layer yourself.