about summary refs log tree commit diff stats
path: root/src/utils/sandbox.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-04-03 18:54:07 +0200
committerbptato <nincsnevem662@gmail.com>2024-04-03 19:08:34 +0200
commit5cf524958fc73d6912aef4866500b0cc46fa1bc6 (patch)
treeacc298fe143f5f9cfd9eff591fd52e5fb1e3866b /src/utils/sandbox.nim
parentaf92dd1711181586a58843216e5fdd9c48876e59 (diff)
downloadchawan-5cf524958fc73d6912aef4866500b0cc46fa1bc6.tar.gz
sandbox: add OpenBSD pledge/unveil support
pledge is a bit more fine-grained than Capsicum's capability mode,
so the buffer & http ("network") sandboxes are now split up into
two parts.

I applied the same hack as in FreeBSD for overriding the buffer
selector kqueue, because a) I didn't want to request sysctl promise
b) I'm not sure if it would even work and c) if it breaks on OpenBSD,
then it's broken on FreeBSD too, so there's a greater chance of
discovering the bug.
Diffstat (limited to 'src/utils/sandbox.nim')
-rw-r--r--src/utils/sandbox.nim29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/utils/sandbox.nim b/src/utils/sandbox.nim
index 88fc5c10..70e592d6 100644
--- a/src/utils/sandbox.nim
+++ b/src/utils/sandbox.nim
@@ -1,13 +1,36 @@
 when defined(freebsd):
   import bindings/capsicum
 
-when defined(freebsd):
-  proc enterSandbox*() =
+  proc enterBufferSandbox*(sockPath: string) =
     # per man:cap_enter(2), it may return ENOSYS if the kernel was compiled
     # without CAPABILITY_MODE. So it seems better not to panic in this case.
     # (But TODO: when we get enough sandboxing coverage it should print a
     # warning or something.)
     discard cap_enter()
+
+  proc enterNetworkSandbox*() =
+    # no difference between buffer; Capsicum is quite straightforward
+    # to use in this regard.
+    discard cap_enter()
+elif defined(openbsd):
+  import bindings/pledge
+
+  proc enterBufferSandbox*(sockPath: string) =
+    # take whatever we need to
+    # * fork
+    # * create/use UNIX domain sockets in sockPath
+    # * take FDs from the main process
+    # cw is the minimum for being able to make sockets
+    doAssert unveil(cstring(sockPath), "cw") == 0
+    # note: ordering is important; pledge now removes the unveil promise.
+    doAssert pledge("unix stdio sendfd recvfd proc cpath", nil) == 0
+
+  proc enterNetworkSandbox*() =
+    # we don't need much to write out data from sockets to stdout.
+    doAssert pledge("stdio", nil) == 0
 else:
-  proc enterSandbox*() =
+  proc enterBufferSandbox*(sockPath: string) =
+    discard
+
+  proc enterNetworkSandbox*() =
     discard