diff options
author | bptato <nincsnevem662@gmail.com> | 2024-07-24 19:45:52 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-07-24 19:46:49 +0200 |
commit | de2a70dc814658a8c72e7da6180ea5e16a8b985b (patch) | |
tree | c089a85e65d0069e2d51b12d1553ada8c2a63ea6 | |
parent | 40122721d3b25d3b7e75f93e64d88853d1c9c0f2 (diff) | |
download | chawan-de2a70dc814658a8c72e7da6180ea5e16a8b985b.tar.gz |
client, sandbox: fix termux build
Still not perfect, because it crashes on missing /tmp dir so you have to manually set it...
-rw-r--r-- | src/local/client.nim | 13 | ||||
-rw-r--r-- | src/utils/sandbox.nim | 54 | ||||
-rw-r--r-- | todo | 1 |
3 files changed, 60 insertions, 8 deletions
diff --git a/src/local/client.nim b/src/local/client.nim index 97390528..1fc5a7f1 100644 --- a/src/local/client.nim +++ b/src/local/client.nim @@ -359,7 +359,8 @@ proc input(client: Client): EmptyPromise = p.resolve() return p -let SIGWINCH {.importc, header: "<signal.h>", nodecl.}: cint +when not defined(android): + let SIGWINCH {.importc, header: "<signal.h>", nodecl.}: cint proc showConsole(client: Client) {.jsfunc.} = let container = client.consoleWrapper.container @@ -546,7 +547,8 @@ proc handleError(client: Client; fd: int) = proc inputLoop(client: Client) = let selector = client.selector selector.registerHandle(int(client.pager.term.istream.fd), {Read}, 0) - let sigwinch = selector.registerSignal(int(SIGWINCH), 0) + when not defined(android): + let sigwinch = selector.registerSignal(int(SIGWINCH), 0) while true: let events = client.selector.select(-1) for event in events: @@ -556,9 +558,10 @@ proc inputLoop(client: Client) = client.handleWrite(event.fd) if Error in event.events: client.handleError(event.fd) - if Signal in event.events: - assert event.fd == sigwinch - client.pager.windowChange() + when not defined(android): + if Signal in event.events: + assert event.fd == sigwinch + client.pager.windowChange() if selectors.Event.Timer in event.events: let r = client.timeouts.runTimeoutFd(event.fd) assert r diff --git a/src/utils/sandbox.nim b/src/utils/sandbox.nim index efc03e49..19e6fd0a 100644 --- a/src/utils/sandbox.nim +++ b/src/utils/sandbox.nim @@ -81,6 +81,53 @@ elif SandboxMode == stLibSeccomp: import std/posix import bindings/libseccomp + when defined(android): + let PR_SET_VMA {.importc, header: "<sys/prctl.h>", nodecl.}: cint + let PR_SET_VMA_ANON_NAME {.importc, header: "<sys/prctl.h>", nodecl.}: cint + + proc allowBionic(ctx: scmp_filter_ctx) = + # Things needed for bionic libc. Tested with Termux. + const androidAllowList = [ + cstring"rt_sigprocmask", + "epoll_pwait", + "futex", + "madvise" + ] + for it in androidAllowList: + let syscall = seccomp_syscall_resolve_name(it) + doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 0) == 0 + # bionic likes to set this very much. In fact, it was added to + # the kernel by Android devs. + block allowAnonVMAName: + let syscall = seccomp_syscall_resolve_name("prctl") + let arg0 = scmp_arg_cmp( + arg: 0, # op + op: SCMP_CMP_EQ, # equals + datum_a: uint64(PR_SET_VMA) + ) + let arg1 = scmp_arg_cmp( + arg: 1, # attr + op: SCMP_CMP_EQ, # equals + datum_a: uint64(PR_SET_VMA_ANON_NAME) + ) + doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 2, arg0, + arg1) == 0 + # We have to be careful with this one; PROT_EXEC will happily set + # memory as executable, which is certainly not what we want. + # Now, bionic seems to be calling this from mutate(), ergo we + # should be fine just allowing PROT_READ and PROT_READ | PROT_WRITE. + block allowMprotect: + let syscall = seccomp_syscall_resolve_name("mprotect") + let arg2 = scmp_arg_cmp( + arg: 2, # attr + op: SCMP_CMP_LE, # less or equals + datum_a: 3 # PROT_READ | PROT_WRITE + ) + # Note that libseccomp can't really express multiple comparisons. + # However, we are lucky, and we only have to "excessively" allow + # PROT_WRITE (w/o PROT_READ) and PROT_NONE, which does no harm. + doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 1, arg2) == 0 + proc enterBufferSandbox*(sockPath: string) = onSignal SIGSYS: discard sig @@ -137,6 +184,8 @@ elif SandboxMode == stLibSeccomp: datum_a: 1 # PF_LOCAL == PF_UNIX == AF_UNIX ) doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 1, arg0) == 0 + when defined(android): + ctx.allowBionic() doAssert seccomp_load(ctx) == 0 seccomp_release(ctx) @@ -155,9 +204,6 @@ elif SandboxMode == stLibSeccomp: "poll", # curl needs poll "getpid", # used indirectly by OpenSSL EVP_RAND_CTX_new (through drbg) "fstat", # glibc fread seems to call it - # maybe it will need epoll too in the future - "epoll_create", "epoll_create1", "epoll_ctl", "epoll_wait", - "ppoll", # or ppoll # we either have to use CURLOPT_NOSIGNAL or allow signals. # do the latter, otherwise the default name resolver will never time out. "signal", "sigaction", "rt_sigaction", @@ -165,6 +211,8 @@ elif SandboxMode == stLibSeccomp: for it in allowList: doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_syscall_resolve_name(it), 0) == 0 + when defined(android): + ctx.allowBionic() doAssert seccomp_load(ctx) == 0 seccomp_release(ctx) else: diff --git a/todo b/todo index 1c924ee4..0f7ee84f 100644 --- a/todo +++ b/todo @@ -13,6 +13,7 @@ display: - dark mode (basically max Y) - override bgcolor ourselves when terminal fails to report it config: +- important: fix crash on missing /tmp dir with default config - important: config editor - completely replace siteconf; the new solution should: * not be based on table arrays |