about summary refs log tree commit diff stats
path: root/src/io/serversocket.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-28 01:36:29 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-28 01:36:29 +0100
commitb530ccc899a8cc8c63bad29abe1e479eb999b167 (patch)
tree07062947dfda3ac4356b0ce26de1cbe4e4c87ebd /src/io/serversocket.nim
parent52c415762fda7b9369ed4cf88783a6639574e3ea (diff)
downloadchawan-b530ccc899a8cc8c63bad29abe1e479eb999b167.tar.gz
Add capsicum support
It's the sandboxing system of FreeBSD. Quite pleasant to work with.

(Just trying to figure out the basics with this one before tackling the
abomination that is seccomp.)

Indeed, the only non-trivial part was getting newSelector to work with
Capsicum. Long story short it doesn't, so we use an ugly pointer cast +
assignment. But even that is stdlib's "fault", not Capsicum's.

This also gets rid of that ugly SocketPath global.
Diffstat (limited to 'src/io/serversocket.nim')
-rw-r--r--src/io/serversocket.nim38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/io/serversocket.nim b/src/io/serversocket.nim
index a6acc555..ea5bc97d 100644
--- a/src/io/serversocket.nim
+++ b/src/io/serversocket.nim
@@ -9,26 +9,44 @@ type ServerSocket* = object
   sock*: Socket
   path*: string
 
-var SocketDirectory* = "/tmp/cha"
 const SocketPathPrefix = "cha_sock_"
-proc getSocketPath*(pid: int): string =
-  SocketDirectory / SocketPathPrefix & $pid
+proc getSocketName*(pid: int): string =
+  SocketPathPrefix & $pid
+
+proc getSocketPath*(socketDir: string; pid: int): string =
+  socketDir / getSocketName(pid)
 
 # The way stdlib does bindUnix is utterly broken at least on FreeBSD.
 # It seems that just writing it in C is the easiest solution.
 {.compile: "bind_unix.c".}
-proc bind_unix_from_c(fd: cint, path: cstring, pathlen: cint): cint {.importc.}
+proc bind_unix_from_c(fd: cint; path: cstring; pathlen: cint): cint
+  {.importc.}
+
+when defined(freebsd):
+  # capsicum stuff
+  proc unlinkat(dfd: cint; path: cstring; flag: cint): cint
+    {.importc, header: "<unistd.h>".}
+  proc bindat_unix_from_c(dfd, sock: cint; path: cstring; pathlen: cint): cint
+    {.importc.}
 
-proc initServerSocket*(pid: int; blocking = true): ServerSocket =
-  createDir(SocketDirectory)
+proc initServerSocket*(sockDir: string; sockDirFd, pid: int; blocking = true):
+    ServerSocket =
   let sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM,
     Protocol.IPPROTO_IP, buffered = false)
   if not blocking:
     sock.getFd().setBlocking(false)
-  let path = getSocketPath(pid)
-  discard unlink(cstring(path))
-  if bind_unix_from_c(cint(sock.getFd()), cstring(path), cint(path.len)) != 0:
-    raiseOSError(osLastError())
+  let path = getSocketPath(sockDir, pid)
+  if sockDirFd == -1:
+    discard unlink(cstring(path))
+    if bind_unix_from_c(cint(sock.getFd()), cstring(path), cint(path.len)) != 0:
+      raiseOSError(osLastError())
+  else:
+    when defined(freebsd):
+      let name = getSocketName(pid)
+      discard unlinkat(cint(sockDirFd), cstring(name), 0)
+      if bindat_unix_from_c(cint(sockDirFd), cint(sock.getFd()), cstring(name),
+          cint(name.len)) != 0:
+        raiseOSError(osLastError())
   listen(sock)
   return ServerSocket(sock: sock, path: path)