diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/pledge.nim | 6 | ||||
-rw-r--r-- | src/server/buffer.nim | 9 | ||||
-rw-r--r-- | src/server/forkserver.nim | 3 | ||||
-rw-r--r-- | src/utils/sandbox.nim | 29 |
4 files changed, 39 insertions, 8 deletions
diff --git a/src/bindings/pledge.nim b/src/bindings/pledge.nim new file mode 100644 index 00000000..8d265fe6 --- /dev/null +++ b/src/bindings/pledge.nim @@ -0,0 +1,6 @@ +{.push header: "<unistd.h>", importc.} + +proc pledge*(promises, execpromises: cstring): cint +proc unveil*(path, permissions: cstring): cint + +{.pop.} diff --git a/src/server/buffer.nim b/src/server/buffer.nim index 87926c11..df1e3e9b 100644 --- a/src/server/buffer.nim +++ b/src/server/buffer.nim @@ -904,7 +904,7 @@ const bsdPlatform = defined(macosx) or defined(freebsd) or defined(netbsd) or proc onload(buffer: Buffer) -when defined(freebsd): +when defined(freebsd) or defined(openbsd): # necessary for an ugly hack we will do later import std/kqueue @@ -936,9 +936,10 @@ proc clone*(buffer: Buffer, newurl: URL): int {.proxy.} = # Closing seems to suffice here. when not bsdPlatform: buffer.selector.close() - when defined(freebsd): - # hack necessary because newSelector calls sysctl, but capsicum really - # dislikes that. + when defined(freebsd) or defined(openbsd): + # hack necessary because newSelector calls sysctl, but Capsicum really + # dislikes that and we don't want to request systctl capabilities + # from pledge either. let fd = kqueue() doAssert fd != -1 cast[ptr cint](buffer.selector)[] = fd diff --git a/src/server/forkserver.nim b/src/server/forkserver.nim index d972958a..a5a9ff64 100644 --- a/src/server/forkserver.nim +++ b/src/server/forkserver.nim @@ -153,8 +153,9 @@ proc forkBuffer(ctx: var ForkServerContext; r: var BufferedReader): int = closeStdout() # must call before entering the sandbox, or capsicum cries because of Nim # calling sysctl + # also lets us deny sysctl call with pledge let selector = newSelector[int]() - enterSandbox() + enterBufferSandbox(sockDir) let pid = getCurrentProcessId() let ssock = initServerSocket(sockDir, sockDirFd, pid) gssock = ssock 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 |