diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bindings/libseccomp.nim | 3 | ||||
-rw-r--r-- | src/utils/sandbox.nim | 25 |
2 files changed, 26 insertions, 2 deletions
diff --git a/src/bindings/libseccomp.nim b/src/bindings/libseccomp.nim index 81a6e969..3f02e4d9 100644 --- a/src/bindings/libseccomp.nim +++ b/src/bindings/libseccomp.nim @@ -37,6 +37,9 @@ const SCMP_ACT_KILL_PROCESS* = 0x80000000u32 const SCMP_ACT_ALLOW* = 0x7FFF0000u32 const SCMP_ACT_TRAP* = 0x00030000u32 +template SCMP_ACT_ERRNO*(x: uint16): uint32 = + 0x50000u32 or x + proc seccomp_init*(def_action: uint32): scmp_filter_ctx proc seccomp_reset*(ctx: scmp_filter_ctx; def_action: uint32): cint proc seccomp_syscall_resolve_name*(name: cstring): cint diff --git a/src/utils/sandbox.nim b/src/utils/sandbox.nim index 059bfe4b..a7168408 100644 --- a/src/utils/sandbox.nim +++ b/src/utils/sandbox.nim @@ -128,6 +128,27 @@ elif SandboxMode == stLibSeccomp: # 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 blockStat(ctx: scmp_filter_ctx) = + # glibc calls fstat and its variants on fread, and it's quite hard + # to ensure we never use it. Plus, in older glibc versions (< 2.39), + # fstat is implemented as fstatat, and allowing that would imply + # access to arbitrary paths. So for consistency, we make all of them + # return an error. + # + # The offending function is _IO_file_doallocate; it doesn't actually + # look at errno, so EPERM should work fine. + const err = SCMP_ACT_ERRNO(uint16(EPERM)) + const fstatList = [ + cstring"fstat", + "fstat64", + "fstatat64", + "newfstatat", + "statx" + ] + for it in fstatList: + let syscall = seccomp_syscall_resolve_name(it) + doAssert seccomp_rule_add(ctx, err, syscall, 0) == 0 + proc enterBufferSandbox*(sockPath: string) = onSignal SIGSYS: discard sig @@ -148,7 +169,6 @@ elif SandboxMode == stLibSeccomp: "exit_group", # for quit "fcntl", "fcntl64", # for changing blocking status "fork", # for when fork is really fork - "fstat", # glibc fread seems to call it "getpid", # for determining current PID after we fork "getrlimit", # glibc uses it after fork it seems "getsockname", # Nim needs it for connecting @@ -185,6 +205,7 @@ elif SandboxMode == stLibSeccomp: datum_a: 1 # PF_LOCAL == PF_UNIX == AF_UNIX ) doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscall, 1, arg0) == 0 + ctx.blockStat() when defined(android): ctx.allowBionic() doAssert seccomp_load(ctx) == 0 @@ -204,7 +225,6 @@ elif SandboxMode == stLibSeccomp: "mmap", "mmap2", "mremap", "munmap", "brk", # memory allocation "poll", # curl needs poll "getpid", # used indirectly by OpenSSL EVP_RAND_CTX_new (through drbg) - "fstat", # glibc fread seems to call it # 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", @@ -212,6 +232,7 @@ elif SandboxMode == stLibSeccomp: for it in allowList: doAssert seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_syscall_resolve_name(it), 0) == 0 + ctx.blockStat() when defined(android): ctx.allowBionic() doAssert seccomp_load(ctx) == 0 |