oki
oki applies pledge(2) and unveil(2) restrictions to a target program on
OpenBSD, reducing the blast radius of a security vulnerability in that program.
Inspiration
Why you built oki: the program you wanted to contain, and what made wrapping pledge and unveil from the outside the right approach.
How it works
Calling pledge on a program restricts the set of system calls it is allowed to make. Each set of permitted calls is a promise, and promises can be combined. If the program makes a call outside its promises, the kernel terminates it immediately and delivers a core file if it can.
oki applies promises through pledge’s execpromises argument. That is the piece
that makes this work from the outside: execpromises applies to the newly
executed process rather than the current one, so oki can restrict a program it
launches without restricting itself.
unveil works on the filesystem instead of syscalls. It hides the entire
filesystem from a program except for the paths you name, with permissions that
apply to a directory’s whole subtree. oki calls unveil once for each
-u permission:path flag it is given; those restrictions are inherited by the
target program when oki executes it. The target’s own executable is unveiled
automatically.
Features
- Apply specified promise strings to
pledge(2)on the target program - Apply specified paths and permissions to
unveil(2)on the target program - Pass through only
HOMEandPATHby default, with an option to forward specific environment variables - Autogenerate unveil rules for the target program’s imported libraries and write them to standard out, which makes wrapper scripts much easier to write
Usage
Run git with three promises and two unveiled paths: /tmp readable, /foo
readable and create/removable:
$ oki -p "stdio" -p "inet" -p + "error" -u "r:/tmp" -u "rc:/foo" -- git
Generate the unveil rules a program’s libraries need:
$ oki -R /usr/local/bin/rizin
-u 'r:/usr/local/lib/librz_util.so.0.7' \
-u 'r:/usr/lib/libm.so.10.1' \
-u 'r:/usr/lib/libutil.so.16.0' \
(...)
The -d flag logs the promises, unveil rules, and environment variables that
were applied. Pledge violations show up in /var/log/messages.
Requirements
An OpenBSD system and Go. Install with
go install github.com/SeungKang/oki@latest.
Challenges
The hard parts: working out which promises a program actually needs, or tracking down a violation from a core dump.
What I learned
What this taught you about OpenBSD’s security model, syscall sandboxing, or least privilege in practice.
What’s next
Features or fixes you have in mind.