about summary refs log tree commit diff stats
path: root/src/io/serversocket.nim
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-04-18 18:30:53 +0200
committerbptato <nincsnevem662@gmail.com>2024-04-18 18:30:53 +0200
commit38db6ab5be80b255fe40df715adc3b5852875cdd (patch)
tree328eada3b571e475903be0df61c5abf09c022d8b /src/io/serversocket.nim
parent5bb9542045ff6dbb6c357eb4dd0a7616dba33a9a (diff)
downloadchawan-38db6ab5be80b255fe40df715adc3b5852875cdd.tar.gz
sandbox: seccomp support on Linux
We use libseccomp, which is now a semi-mandatory dependency on Linux.
(You can still build without it, but only if you pass a scary long flag
to make.)

For this to work I had to disable getTimezoneOffset, which would
otherwise call localtime_r which in turn reads in some files from
/usr/share/zoneinfo.  To allow this we would have to give unrestricted
openat(2) access to buffer processes, which is unacceptable.

(Giving websites access to the local timezone is a fingerprinting vector
so if this ever gets fixed then it should be an opt-in config setting.)

This patch also includes misc fixes to buffer cloning, and fixes the
LIBEXECDIR override in the makefile so that it is actually useful.
Diffstat (limited to 'src/io/serversocket.nim')
-rw-r--r--src/io/serversocket.nim26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/io/serversocket.nim b/src/io/serversocket.nim
index ea5bc97d..dff6de70 100644
--- a/src/io/serversocket.nim
+++ b/src/io/serversocket.nim
@@ -5,9 +5,10 @@ import std/os
 when defined(posix):
   import std/posix
 
-type ServerSocket* = object
+type ServerSocket* = ref object
   sock*: Socket
   path*: string
+  dfd: int
 
 const SocketPathPrefix = "cha_sock_"
 proc getSocketName*(pid: int): string =
@@ -29,6 +30,13 @@ when defined(freebsd):
   proc bindat_unix_from_c(dfd, sock: cint; path: cstring; pathlen: cint): cint
     {.importc.}
 
+proc initServerSocket*(fd: SocketHandle; sockDir: string; pid, sockDirFd: int):
+    ServerSocket =
+  let sock = newSocket(fd, Domain.AF_UNIX, SockType.SOCK_STREAM,
+    Protocol.IPPROTO_IP, buffered = false)
+  let path = getSocketPath(sockDir, pid)
+  return ServerSocket(sock: sock, path: path, dfd: sockDirFd)
+
 proc initServerSocket*(sockDir: string; sockDirFd, pid: int; blocking = true):
     ServerSocket =
   let sock = newSocket(Domain.AF_UNIX, SockType.SOCK_STREAM,
@@ -37,7 +45,7 @@ proc initServerSocket*(sockDir: string; sockDirFd, pid: int; blocking = true):
     sock.getFd().setBlocking(false)
   let path = getSocketPath(sockDir, pid)
   if sockDirFd == -1:
-    discard unlink(cstring(path))
+    discard tryRemoveFile(path)
     if bind_unix_from_c(cint(sock.getFd()), cstring(path), cint(path.len)) != 0:
       raiseOSError(osLastError())
   else:
@@ -47,9 +55,17 @@ proc initServerSocket*(sockDir: string; sockDirFd, pid: int; blocking = true):
       if bindat_unix_from_c(cint(sockDirFd), cint(sock.getFd()), cstring(name),
           cint(name.len)) != 0:
         raiseOSError(osLastError())
+    else:
+      # shouldn't have sockDirFd on other architectures
+      doAssert false
   listen(sock)
-  return ServerSocket(sock: sock, path: path)
+  return ServerSocket(sock: sock, path: path, dfd: sockDirFd)
 
-proc close*(ssock: ServerSocket) =
+proc close*(ssock: ServerSocket; unlink = true) =
   close(ssock.sock)
-  discard unlink(cstring(ssock.path))
+  if unlink:
+    when defined(freebsd):
+      if ssock.dfd != -1:
+        discard unlinkat(cint(ssock.dfd), cstring(ssock.path), 0)
+        return
+    discard tryRemoveFile(ssock.path)