Sandbox Examples
Goals
- Kernel- and user-space process based sandboxing examples for common hosted
runtimes (Windows, Linux, MacOS, BSDs).
- Each hosted runtime must contain assumptions and tests.
- Portable abstractions are defered, but planned for later for a CI library
with CI as use case.
- Make code simple to cross-compile and natively compile.
- Eventual goal is compare with (realtime) OS security model design to
estimate how far off current OS implementations are and have some more
structured designs to use for sel4 based OSes including drivers.
- Tooling, good design and scalability: Library approach.
Status
Windows
- [x] win32k mitigation + others
test/win/main_win32k_mitigation.zig
- [x] explicit handle inheritance
test/win/main_explicit_handle_inheritance.zig
- [x] job object system
link to limit
memory, cpu usage and kill process group
- [ ] file system sandboxing by user account (might need to remove and readd account)
- ignore for now and always use explicit paths for PATH and alike.
- use ntdll calls eventually, because we already have those in Zig libstd
- NetUserAdd, NetUserGetInfo, and NetUserSetInfo; GetFileAttributesExW
- GetNamedSecurityInfoW, SetNamedSecurityInfoW
- AccessCheck, "Verifying Client Access with ACLs in C++"
- GetFileAttributesExW
- [ ] impersonation (setreuid under Windows) https://learn.microsoft.com/en-us/windows/win32/cossdk/client-impersonation-and-delegation
- [ ] network sandboxing (ie block specific user from internet access)
- [ ] user and system setup
- [ ] review for further accessible persistent state
- [ ] security shutdown
- [ ] idea: ETW based tracing + SCL via job unit
- [ ] idea: stub kernel32 and ntdll calls as admin to run own filter code in kernel space
Linux
- [ ] landlock (access control on kernel objects)
- [ ] seccomp-bpf (syscall filtering)
- [ ] parallel process spawn handle leak problem with workarounds
- mutex or only standard handles
- list of to be closed handles does not work, because order of handles
which are inherited is not guaranteed to be stable and may vary during
process lifetime
- [ ] file system sandboxing by user account (chown, chmod, Linux permission system)
- [ ] setreuid, setregid (bounded waiting, fixing libstd child_process errors)
- [ ] cgroups (semantic mismatch, more powerful than job object),
- [ ] network sandboxing, seccomp-bpf
- [ ] what other persistent state may be accessible?
- [ ] minimal system setup, solution?
- [ ] tight system supervision setup, solution?
- [ ] security shutdown, lockdown?
- [ ] more advanced: race-free signaling
MacOS
- [ ] sandbox-exec, look into firefox and chromium sandboxing code
stackoverflow question
some overview
- [ ] how to wait for process group
- kevent NOTE_TRACK needed
- orphaned processes still not cleaned up
- fork bomb unmitigated (applying posix limits needed)
- workaround jobs not finishing in deadline: kill all processes with uid
- [ ] what other persistent state may be accessible?
- [ ] minimal system setup, solution?
- [ ] tight system supervision setup, solution?
- [ ] security shutdown, solution?
Other BSDs and Unixes
- [ ] Kernel API sandboxing works likely very similar to other solutions
- [ ] process API with identical problems
- [ ] network parts unclear
- [ ] other parts are highly configuration dependent
Tests and implementation
Tests are to be found in test/.
General procedure:
-
- Find reasonable short example code
-
- Add testfile.c to test\win\ and build.zig
-
- zig translate-c test\win\testfile.c > test\win\testfile.zig, add it to build.zig
-
- simplify test\win\testfile.zig, implementation, error abstractions
Deviation:
- Follow different example code, ideally with sufficient explanations
- Opaque pointers (Windows) hard to debug/check for correctness of operations
- More than 3 parameter with optional pointer or weird problems
- Standalone C and Zig files as libs, main calls C version and vice versa
- bare bone C pointers in Zig
- identical logic for Zig and C version
- combinations to figure out what went wrong
- view assembly diffs
- record program and inspect fn args structures
- TODO setup Kernel debugging to get logic
- TODO program + procederes to extract underlying in-Kernel structures/code
collection instead of opaque pointers (ntdll trace, ghidra?)
- TODO trace fn args structures => debugger plugin
References