From 5a132f96525ff78fa18d0db61c2dd5cd77bd3a9c Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Mon, 18 Apr 2022 08:54:42 -0700 Subject: [PATCH] Add seccomp bpf sandboxing to redbean It's now possible to pass the `-S` or `-SS` flags to sandbox redbean worker proecsses after they've been forked. The first `-S` flag is intended to be a permissive builtin policy that limits system calls to only that which the various parts of redbean serving need. The second `-SS` flag is intended to be more restrictive, preventing things like the Lua extensions you download off the web from using the HTTP client or sockets APIs. In upcoming changes you'll be able to implement your own Berkeley Packet Filter sandbox programs and load them via Lua. --- libc/calls/issandboxed.h | 10 - libc/calls/prctl.c | 17 +- libc/calls/readv.c | 20 +- libc/calls/seccomp.c | 22 +- libc/calls/strace.internal.h | 2 + .../strace_iov.greg.c} | 28 +- libc/calls/struct/bpf.h | 1341 +++++++++++++++++ libc/calls/struct/filter.h | 59 + libc/calls/struct/hog.py | 23 + libc/calls/struct/seccomp.h | 48 +- libc/calls/writev.c | 17 +- libc/intrin/isdebuggerpresent.greg.c | 3 +- libc/intrin/{issandboxed.c => isworker.c} | 10 +- libc/intrin/kprintf.greg.c | 33 +- libc/log/backtrace2.c | 3 +- libc/log/checkfail.c | 57 +- libc/log/oncrash.c | 10 +- libc/log/restoretty.c | 3 +- libc/log/startfatal.c | 2 +- libc/runtime/getsymboltable.c | 3 +- libc/runtime/mmap.c | 8 +- libc/runtime/runtime.h | 1 + libc/sock/asanmsghdr.c | 31 + libc/sock/internal.h | 1 + libc/sock/recvmsg.c | 58 +- libc/sock/sendmsg.c | 73 +- libc/sock/syslog.c | 19 +- libc/sock/syslog.h | 4 +- libc/sysv/consts.sh | 38 - libc/sysv/consts/LOG_ALERT.S | 2 - libc/sysv/consts/LOG_AUTH.S | 2 - libc/sysv/consts/LOG_CONS.S | 2 - libc/sysv/consts/LOG_CRIT.S | 2 - libc/sysv/consts/LOG_CRON.S | 2 - libc/sysv/consts/LOG_DAEMON.S | 2 - libc/sysv/consts/LOG_DEBUG.S | 2 - libc/sysv/consts/LOG_EMERG.S | 2 - libc/sysv/consts/LOG_ERR.S | 2 - libc/sysv/consts/LOG_FACMASK.S | 2 - libc/sysv/consts/LOG_INFO.S | 2 - libc/sysv/consts/LOG_KERN.S | 2 - libc/sysv/consts/LOG_LOCAL0.S | 2 - libc/sysv/consts/LOG_LOCAL1.S | 2 - libc/sysv/consts/LOG_LOCAL2.S | 2 - libc/sysv/consts/LOG_LOCAL3.S | 2 - libc/sysv/consts/LOG_LOCAL4.S | 2 - libc/sysv/consts/LOG_LOCAL5.S | 2 - libc/sysv/consts/LOG_LOCAL6.S | 2 - libc/sysv/consts/LOG_LOCAL7.S | 2 - libc/sysv/consts/LOG_LPR.S | 2 - libc/sysv/consts/LOG_MAIL.S | 2 - libc/sysv/consts/LOG_NDELAY.S | 2 - libc/sysv/consts/LOG_NEWS.S | 2 - libc/sysv/consts/LOG_NFACILITIES.S | 2 - libc/sysv/consts/LOG_NOTICE.S | 2 - libc/sysv/consts/LOG_NOWAIT.S | 2 - libc/sysv/consts/LOG_ODELAY.S | 2 - libc/sysv/consts/LOG_PERROR.S | 2 - libc/sysv/consts/LOG_PID.S | 2 - libc/sysv/consts/LOG_PRIMASK.S | 2 - libc/sysv/consts/LOG_SELECT.S | 2 - libc/sysv/consts/LOG_SENSE.S | 2 - libc/sysv/consts/LOG_SYSLOG.S | 2 - libc/sysv/consts/LOG_USER.S | 2 - libc/sysv/consts/LOG_UUCP.S | 2 - libc/sysv/consts/LOG_WARNING.S | 2 - libc/sysv/consts/audit.h | 13 + libc/sysv/consts/log.h | 126 +- libc/sysv/consts/pr.h | 5 +- libc/sysv/consts/seccomp.h | 29 - libc/sysv/syscalls.sh | 2 +- libc/testlib/showerror.c | 5 +- test/libc/calls/seccomp_test.c | 57 +- test/libc/intrin/kprintf_test.c | 3 +- third_party/lua/lauxlib.c | 8 +- tool/net/help.txt | 206 ++- tool/net/lunix.c | 260 ++-- tool/net/redbean.c | 167 +- tool/net/sandbox.h | 23 + 79 files changed, 2271 insertions(+), 651 deletions(-) delete mode 100644 libc/calls/issandboxed.h rename libc/{intrin/describeseccompoperationflags.greg.c => calls/strace_iov.greg.c} (74%) create mode 100644 libc/calls/struct/bpf.h create mode 100644 libc/calls/struct/filter.h create mode 100644 libc/calls/struct/hog.py rename libc/intrin/{issandboxed.c => isworker.c} (86%) create mode 100644 libc/sock/asanmsghdr.c delete mode 100644 libc/sysv/consts/LOG_ALERT.S delete mode 100644 libc/sysv/consts/LOG_AUTH.S delete mode 100644 libc/sysv/consts/LOG_CONS.S delete mode 100644 libc/sysv/consts/LOG_CRIT.S delete mode 100644 libc/sysv/consts/LOG_CRON.S delete mode 100644 libc/sysv/consts/LOG_DAEMON.S delete mode 100644 libc/sysv/consts/LOG_DEBUG.S delete mode 100644 libc/sysv/consts/LOG_EMERG.S delete mode 100644 libc/sysv/consts/LOG_ERR.S delete mode 100644 libc/sysv/consts/LOG_FACMASK.S delete mode 100644 libc/sysv/consts/LOG_INFO.S delete mode 100644 libc/sysv/consts/LOG_KERN.S delete mode 100644 libc/sysv/consts/LOG_LOCAL0.S delete mode 100644 libc/sysv/consts/LOG_LOCAL1.S delete mode 100644 libc/sysv/consts/LOG_LOCAL2.S delete mode 100644 libc/sysv/consts/LOG_LOCAL3.S delete mode 100644 libc/sysv/consts/LOG_LOCAL4.S delete mode 100644 libc/sysv/consts/LOG_LOCAL5.S delete mode 100644 libc/sysv/consts/LOG_LOCAL6.S delete mode 100644 libc/sysv/consts/LOG_LOCAL7.S delete mode 100644 libc/sysv/consts/LOG_LPR.S delete mode 100644 libc/sysv/consts/LOG_MAIL.S delete mode 100644 libc/sysv/consts/LOG_NDELAY.S delete mode 100644 libc/sysv/consts/LOG_NEWS.S delete mode 100644 libc/sysv/consts/LOG_NFACILITIES.S delete mode 100644 libc/sysv/consts/LOG_NOTICE.S delete mode 100644 libc/sysv/consts/LOG_NOWAIT.S delete mode 100644 libc/sysv/consts/LOG_ODELAY.S delete mode 100644 libc/sysv/consts/LOG_PERROR.S delete mode 100644 libc/sysv/consts/LOG_PID.S delete mode 100644 libc/sysv/consts/LOG_PRIMASK.S delete mode 100644 libc/sysv/consts/LOG_SELECT.S delete mode 100644 libc/sysv/consts/LOG_SENSE.S delete mode 100644 libc/sysv/consts/LOG_SYSLOG.S delete mode 100644 libc/sysv/consts/LOG_USER.S delete mode 100644 libc/sysv/consts/LOG_UUCP.S delete mode 100644 libc/sysv/consts/LOG_WARNING.S create mode 100644 libc/sysv/consts/audit.h delete mode 100644 libc/sysv/consts/seccomp.h create mode 100644 tool/net/sandbox.h diff --git a/libc/calls/issandboxed.h b/libc/calls/issandboxed.h deleted file mode 100644 index c97f9ce59..000000000 --- a/libc/calls/issandboxed.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_ISSANDBOXED_INTERNAL_H_ -#define COSMOPOLITAN_LIBC_CALLS_ISSANDBOXED_INTERNAL_H_ -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern bool __issandboxed; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_ISSANDBOXED_INTERNAL_H_ */ diff --git a/libc/calls/prctl.c b/libc/calls/prctl.c index ed82bcf45..71681273b 100644 --- a/libc/calls/prctl.c +++ b/libc/calls/prctl.c @@ -19,8 +19,22 @@ #include "libc/calls/calls.h" #include "libc/calls/strace.internal.h" #include "libc/errno.h" +#include "libc/sysv/consts/pr.h" #include "libc/sysv/errfuns.h" +static const char *DescribePrctlOperation(int x) { + switch (x) { + case PR_SET_NO_NEW_PRIVS: + return "PR_SET_NO_NEW_PRIVS"; + case PR_SET_SECCOMP: + return "PR_SET_SECCOMP"; + case PR_GET_SECCOMP: + return "PR_GET_SECCOMP"; + default: + return "PRCTL_???"; + } +} + /** * Tunes process on Linux. * @@ -47,6 +61,7 @@ int prctl(int operation, ...) { } else { rc = enosys(); } - STRACE("seccomp(%d, %p, %p, %p, %p) → %d% m", operation, a, b, c, d, rc); + STRACE("prctl(%s, %p, %p, %p, %p) → %d% m", DescribePrctlOperation(operation), + a, b, c, d, rc); return rc; } diff --git a/libc/calls/readv.c b/libc/calls/readv.c index 47492ffcf..287641fd9 100644 --- a/libc/calls/readv.c +++ b/libc/calls/readv.c @@ -42,8 +42,7 @@ */ ssize_t readv(int fd, const struct iovec *iov, int iovlen) { int i; - ssize_t rc, rem; - + ssize_t rc; if (fd >= 0 && iovlen >= 0) { if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) { rc = efault(); @@ -66,27 +65,16 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) { } else { rc = einval(); } - #if defined(SYSDEBUG) && _DATATRACE if (__strace > 0) { if (rc == -1 && errno == EFAULT) { STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc); } else { - rem = rc != -1 ? rc : 0; - kprintf(STRACE_PROLOGUE "readv(%d, [{", fd); - for (i = 0; i < MIN(5, iovlen); ++i) { - kprintf("%s{%#.*hhs%s, %'zu}", i ? ", " : "", - MAX(0, MIN(40, MIN(rem, iov[i].iov_len))), iov[i].iov_base, - MAX(0, MIN(40, MIN(rem, iov[i].iov_len))) < iov[i].iov_len - ? "..." - : "", - iov[i].iov_len); - rem -= iov[i].iov_len; - } - kprintf("%s}], %d) → %'ld% m%n", iovlen > 5 ? "..." : "", iovlen, rc); + kprintf(STRACE_PROLOGUE "readv(%d, [", fd); + __strace_iov(iov, iovlen, rc != -1 ? rc : 0); + kprintf("], %d) → %'ld% m%n", iovlen, rc); } } #endif - return rc; } diff --git a/libc/calls/seccomp.c b/libc/calls/seccomp.c index 5f3a7d4a6..9f0e3c0a1 100644 --- a/libc/calls/seccomp.c +++ b/libc/calls/seccomp.c @@ -17,15 +17,29 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/issandboxed.h" #include "libc/calls/strace.internal.h" +#include "libc/calls/struct/seccomp.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/describeflags.internal.h" #include "libc/sysv/consts/pr.h" -#include "libc/sysv/consts/seccomp.h" #include "libc/sysv/errfuns.h" +static const char *DescribeSeccompOperation(int x) { + switch (x) { + case SECCOMP_SET_MODE_STRICT: + return "SECCOMP_SET_MODE_STRICT"; + case SECCOMP_SET_MODE_FILTER: + return "SECCOMP_SET_MODE_FILTER"; + case SECCOMP_GET_ACTION_AVAIL: + return "SECCOMP_GET_ACTION_AVAIL"; + case SECCOMP_GET_NOTIF_SIZES: + return "SECCOMP_GET_NOTIF_SIZES"; + default: + return "SECCOMP_???"; + } +} + /** * Tunes Linux security policy. * @@ -63,7 +77,7 @@ int seccomp(unsigned operation, unsigned flags, void *args) { } else { rc = enosys(); } - STRACE("seccomp(%s, %#x, %p) → %d% m", - DescribeSeccompOperationFlags(operation), flags, args, rc); + STRACE("seccomp(%s, %#x, %p) → %d% m", DescribeSeccompOperation(operation), + flags, args, rc); return rc; } diff --git a/libc/calls/strace.internal.h b/libc/calls/strace.internal.h index f3c86ab48..222967edc 100644 --- a/libc/calls/strace.internal.h +++ b/libc/calls/strace.internal.h @@ -1,5 +1,6 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ #define COSMOPOLITAN_LIBC_CALLS_STRACE_INTERNAL_H_ +#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/rlimit.h" #include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/stat.h" @@ -53,6 +54,7 @@ COSMOPOLITAN_C_START_ extern int __strace; void __stracef(const char *, ...); +void __strace_iov(const struct iovec *, int, ssize_t); const char *__strace_stat(int, const struct stat *); const char *__strace_sigaction(char *, size_t, int, const struct sigaction *); const char *__strace_sigset(char[41], size_t, int, const sigset_t *); diff --git a/libc/intrin/describeseccompoperationflags.greg.c b/libc/calls/strace_iov.greg.c similarity index 74% rename from libc/intrin/describeseccompoperationflags.greg.c rename to libc/calls/strace_iov.greg.c index 841fdad2e..7c37fe0f0 100644 --- a/libc/intrin/describeseccompoperationflags.greg.c +++ b/libc/calls/strace_iov.greg.c @@ -16,20 +16,20 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/intrin/describeflags.internal.h" +#include "libc/calls/strace.internal.h" +#include "libc/intrin/kprintf.h" #include "libc/macros.internal.h" -#include "libc/sysv/consts/seccomp.h" -const struct DescribeFlags kSeccompOperationFlags[] = { - {SECCOMP_GET_NOTIF_SIZES, "GET_NOTIF_SIZES"}, // order matters - {SECCOMP_GET_ACTION_AVAIL, "GET_ACTION_AVAIL"}, // - {SECCOMP_SET_MODE_FILTER, "SET_MODE_FILTER"}, // - {SECCOMP_SET_MODE_STRICT, "SET_MODE_STRICT"}, // -}; - -const char *DescribeSeccompOperationFlags(int x) { - static char seccompflags[128]; - return DescribeFlags(seccompflags, sizeof(seccompflags), - kSeccompOperationFlags, ARRAYLEN(kSeccompOperationFlags), - "SECCOMP_", x); +void __strace_iov(const struct iovec *iov, int iovlen, ssize_t rem) { + int i; + kprintf("{"); + for (i = 0; rem && i < MIN(5, iovlen); ++i) { + kprintf( + "%s{%#.*hhs%s, %'zu}", i ? ", " : "", + MAX(0, MIN(40, MIN(rem, iov[i].iov_len))), iov[i].iov_base, + MAX(0, MIN(40, MIN(rem, iov[i].iov_len))) < iov[i].iov_len ? "..." : "", + iov[i].iov_len); + rem -= iov[i].iov_len; + } + kprintf("%s}", iovlen > 5 ? "..." : ""); } diff --git a/libc/calls/struct/bpf.h b/libc/calls/struct/bpf.h new file mode 100644 index 000000000..56355628d --- /dev/null +++ b/libc/calls/struct/bpf.h @@ -0,0 +1,1341 @@ +#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_BPF_H_ +#define COSMOPOLITAN_LIBC_CALLS_STRUCT_BPF_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +#define BPF_MAXINSNS 4096 + +#define BPF_CLASS(code) ((code)&0x07) +#define BPF_LD 0x00 /* load ops */ +#define BPF_LDX 0x01 /* load into register */ +#define BPF_ST 0x02 /* store from immediate */ +#define BPF_STX 0x03 /* store from register */ +#define BPF_ALU 0x04 /* 32-bit arithmetic */ +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +#define BPF_SIZE(code) ((code)&0x18) +#define BPF_W 0x00 /* 32-bit */ +#define BPF_H 0x08 /* 16-bit */ +#define BPF_B 0x10 /* 8-bit */ + +#define BPF_MODE(code) ((code)&0xe0) +#define BPF_IMM 0x00 /* 64-bit immediate */ +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +#define BPF_OP(code) ((code)&0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_MOD 0x90 +#define BPF_XOR 0xa0 + +#define BPF_SRC(code) ((code)&0x08) +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_K 0x00 +#define BPF_X 0x08 + +#define BPF_JMP32 0x06 +#define BPF_ALU64 0x07 +#define BPF_DW 0x18 +#define BPF_ATOMIC 0xc0 +#define BPF_XADD 0xc0 +#define BPF_MOV 0xb0 +#define BPF_ARSH 0xc0 +#define BPF_END 0xd0 +#define BPF_TO_LE 0x00 +#define BPF_TO_BE 0x08 +#define BPF_FROM_LE BPF_TO_LE +#define BPF_FROM_BE BPF_TO_BE +#define BPF_JNE 0x50 +#define BPF_JLT 0xa0 +#define BPF_JLE 0xb0 +#define BPF_JSGT 0x60 +#define BPF_JSGE 0x70 +#define BPF_JSLT 0xc0 +#define BPF_JSLE 0xd0 +#define BPF_CALL 0x80 +#define BPF_EXIT 0x90 +#define BPF_FETCH 0x01 +#define BPF_XCHG (0xe0 | BPF_FETCH) +#define BPF_CMPXCHG (0xf0 | BPF_FETCH) +#define MAX_BPF_REG __MAX_BPF_REG + +#define BPF_REG_0 0 +#define BPF_REG_1 1 +#define BPF_REG_2 2 +#define BPF_REG_3 3 +#define BPF_REG_4 4 +#define BPF_REG_5 5 +#define BPF_REG_6 6 +#define BPF_REG_7 7 +#define BPF_REG_8 8 +#define BPF_REG_9 9 +#define BPF_REG_10 10 +#define __MAX_BPF_REG 11 + +#define BPF_MAP_CREATE 0 +#define BPF_MAP_LOOKUP_ELEM 1 +#define BPF_MAP_UPDATE_ELEM 2 +#define BPF_MAP_DELETE_ELEM 3 +#define BPF_MAP_GET_NEXT_KEY 4 +#define BPF_PROG_LOAD 5 +#define BPF_OBJ_PIN 6 +#define BPF_OBJ_GET 7 +#define BPF_PROG_ATTACH 8 +#define BPF_PROG_DETACH 9 +#define BPF_PROG_TEST_RUN 10 +#define BPF_PROG_GET_NEXT_ID 11 +#define BPF_MAP_GET_NEXT_ID 12 +#define BPF_PROG_GET_FD_BY_ID 13 +#define BPF_MAP_GET_FD_BY_ID 14 +#define BPF_OBJ_GET_INFO_BY_FD 15 +#define BPF_PROG_QUERY 16 +#define BPF_RAW_TRACEPOINT_OPEN 17 +#define BPF_BTF_LOAD 18 +#define BPF_BTF_GET_FD_BY_ID 19 +#define BPF_TASK_FD_QUERY 20 +#define BPF_MAP_LOOKUP_AND_DELETE_ELEM 21 +#define BPF_MAP_FREEZE 22 +#define BPF_BTF_GET_NEXT_ID 23 +#define BPF_MAP_LOOKUP_BATCH 24 +#define BPF_MAP_LOOKUP_AND_DELETE_BATCH 25 +#define BPF_MAP_UPDATE_BATCH 26 +#define BPF_MAP_DELETE_BATCH 27 +#define BPF_LINK_CREATE 28 +#define BPF_LINK_UPDATE 29 +#define BPF_LINK_GET_FD_BY_ID 30 +#define BPF_LINK_GET_NEXT_ID 31 +#define BPF_ENABLE_STATS 32 +#define BPF_ITER_CREATE 33 +#define BPF_LINK_DETACH 34 +#define BPF_PROG_BIND_MAP 35 +#define BPF_PROG_RUN BPF_PROG_TEST_RUN + +#define BPF_MAP_TYPE_UNSPEC 0 +#define BPF_MAP_TYPE_HASH 1 +#define BPF_MAP_TYPE_ARRAY 2 +#define BPF_MAP_TYPE_PROG_ARRAY 3 +#define BPF_MAP_TYPE_PERF_EVENT_ARRAY 4 +#define BPF_MAP_TYPE_PERCPU_HASH 5 +#define BPF_MAP_TYPE_PERCPU_ARRAY 6 +#define BPF_MAP_TYPE_STACK_TRACE 7 +#define BPF_MAP_TYPE_CGROUP_ARRAY 8 +#define BPF_MAP_TYPE_LRU_HASH 9 +#define BPF_MAP_TYPE_LRU_PERCPU_HASH 10 +#define BPF_MAP_TYPE_LPM_TRIE 11 +#define BPF_MAP_TYPE_ARRAY_OF_MAPS 12 +#define BPF_MAP_TYPE_HASH_OF_MAPS 13 +#define BPF_MAP_TYPE_DEVMAP 14 +#define BPF_MAP_TYPE_SOCKMAP 15 +#define BPF_MAP_TYPE_CPUMAP 16 +#define BPF_MAP_TYPE_XSKMAP 17 +#define BPF_MAP_TYPE_SOCKHASH 18 +#define BPF_MAP_TYPE_CGROUP_STORAGE 19 +#define BPF_MAP_TYPE_REUSEPORT_SOCKARRAY 20 +#define BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE 21 +#define BPF_MAP_TYPE_QUEUE 22 +#define BPF_MAP_TYPE_STACK 23 +#define BPF_MAP_TYPE_SK_STORAGE 24 +#define BPF_MAP_TYPE_DEVMAP_HASH 25 +#define BPF_MAP_TYPE_STRUCT_OPS 26 +#define BPF_MAP_TYPE_RINGBUF 27 +#define BPF_MAP_TYPE_INODE_STORAGE 28 +#define BPF_MAP_TYPE_TASK_STORAGE 29 + +#define BPF_PROG_TYPE_UNSPEC 0 +#define BPF_PROG_TYPE_SOCKET_FILTER 1 +#define BPF_PROG_TYPE_KPROBE 2 +#define BPF_PROG_TYPE_SCHED_CLS 3 +#define BPF_PROG_TYPE_SCHED_ACT 4 +#define BPF_PROG_TYPE_TRACEPOINT 5 +#define BPF_PROG_TYPE_XDP 6 +#define BPF_PROG_TYPE_PERF_EVENT 7 +#define BPF_PROG_TYPE_CGROUP_SKB 8 +#define BPF_PROG_TYPE_CGROUP_SOCK 9 +#define BPF_PROG_TYPE_LWT_IN 10 +#define BPF_PROG_TYPE_LWT_OUT 11 +#define BPF_PROG_TYPE_LWT_XMIT 12 +#define BPF_PROG_TYPE_SOCK_OPS 13 +#define BPF_PROG_TYPE_SK_SKB 14 +#define BPF_PROG_TYPE_CGROUP_DEVICE 15 +#define BPF_PROG_TYPE_SK_MSG 16 +#define BPF_PROG_TYPE_RAW_TRACEPOINT 17 +#define BPF_PROG_TYPE_CGROUP_SOCK_ADDR 18 +#define BPF_PROG_TYPE_LWT_SEG6LOCAL 19 +#define BPF_PROG_TYPE_LIRC_MODE2 20 +#define BPF_PROG_TYPE_SK_REUSEPORT 21 +#define BPF_PROG_TYPE_FLOW_DISSECTOR 22 +#define BPF_PROG_TYPE_CGROUP_SYSCTL 23 +#define BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE 24 +#define BPF_PROG_TYPE_CGROUP_SOCKOPT 25 +#define BPF_PROG_TYPE_TRACING 26 +#define BPF_PROG_TYPE_STRUCT_OPS 27 +#define BPF_PROG_TYPE_EXT 28 +#define BPF_PROG_TYPE_LSM 29 +#define BPF_PROG_TYPE_SK_LOOKUP 30 +#define BPF_PROG_TYPE_SYSCALL 31 + +#define BPF_CGROUP_INET_INGRESS 0 +#define BPF_CGROUP_INET_EGRESS 1 +#define BPF_CGROUP_INET_SOCK_CREATE 2 +#define BPF_CGROUP_SOCK_OPS 3 +#define BPF_SK_SKB_STREAM_PARSER 4 +#define BPF_SK_SKB_STREAM_VERDICT 5 +#define BPF_CGROUP_DEVICE 6 +#define BPF_SK_MSG_VERDICT 7 +#define BPF_CGROUP_INET4_BIND 8 +#define BPF_CGROUP_INET6_BIND 9 +#define BPF_CGROUP_INET4_CONNECT 10 +#define BPF_CGROUP_INET6_CONNECT 11 +#define BPF_CGROUP_INET4_POST_BIND 12 +#define BPF_CGROUP_INET6_POST_BIND 13 +#define BPF_CGROUP_UDP4_SENDMSG 14 +#define BPF_CGROUP_UDP6_SENDMSG 15 +#define BPF_LIRC_MODE2 16 +#define BPF_FLOW_DISSECTOR 17 +#define BPF_CGROUP_SYSCTL 18 +#define BPF_CGROUP_UDP4_RECVMSG 19 +#define BPF_CGROUP_UDP6_RECVMSG 20 +#define BPF_CGROUP_GETSOCKOPT 21 +#define BPF_CGROUP_SETSOCKOPT 22 +#define BPF_TRACE_RAW_TP 23 +#define BPF_TRACE_FENTRY 24 +#define BPF_TRACE_FEXIT 25 +#define BPF_MODIFY_RETURN 26 +#define BPF_LSM_MAC 27 +#define BPF_TRACE_ITER 28 +#define BPF_CGROUP_INET4_GETPEERNAME 29 +#define BPF_CGROUP_INET6_GETPEERNAME 30 +#define BPF_CGROUP_INET4_GETSOCKNAME 31 +#define BPF_CGROUP_INET6_GETSOCKNAME 32 +#define BPF_XDP_DEVMAP 33 +#define BPF_CGROUP_INET_SOCK_RELEASE 34 +#define BPF_XDP_CPUMAP 35 +#define BPF_SK_LOOKUP 36 +#define BPF_XDP 37 +#define BPF_SK_SKB_VERDICT 38 +#define BPF_SK_REUSEPORT_SELECT 39 +#define BPF_SK_REUSEPORT_SELECT_OR_MIGRATE 40 +#define __MAX_BPF_ATTACH_TYPE 41 + +#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE + +#define BPF_LINK_TYPE_UNSPEC 0 +#define BPF_LINK_TYPE_RAW_TRACEPOINT 1 +#define BPF_LINK_TYPE_TRACING 2 +#define BPF_LINK_TYPE_CGROUP 3 +#define BPF_LINK_TYPE_ITER 4 +#define BPF_LINK_TYPE_NETNS 5 +#define BPF_LINK_TYPE_XDP 6 +#define MAX_BPF_LINK_TYPE 7 + +#define BPF_F_ALLOW_OVERRIDE (1U << 0) +#define BPF_F_ALLOW_MULTI (1U << 1) +#define BPF_F_REPLACE (1U << 2) +#define BPF_F_STRICT_ALIGNMENT (1U << 0) +#define BPF_F_ANY_ALIGNMENT (1U << 1) +#define BPF_F_TEST_RND_HI32 (1U << 2) +#define BPF_F_TEST_STATE_FREQ (1U << 3) +#define BPF_F_SLEEPABLE (1U << 4) +#define BPF_PSEUDO_MAP_FD 1 +#define BPF_PSEUDO_MAP_IDX 5 +#define BPF_PSEUDO_MAP_VALUE 2 +#define BPF_PSEUDO_MAP_IDX_VALUE 6 +#define BPF_PSEUDO_BTF_ID 3 +#define BPF_PSEUDO_FUNC 4 +#define BPF_PSEUDO_CALL 1 +#define BPF_PSEUDO_KFUNC_CALL 2 + +#define BPF_ANY 0 +#define BPF_NOEXIST 1 +#define BPF_EXIST 2 +#define BPF_F_LOCK 4 +#define BPF_F_NO_PREALLOC (1U << 0) +#define BPF_F_NO_COMMON_LRU (1U << 1) +#define BPF_F_NUMA_NODE (1U << 2) +#define BPF_F_RDONLY (1U << 3) +#define BPF_F_WRONLY (1U << 4) +#define BPF_F_STACK_BUILD_ID (1U << 5) +#define BPF_F_ZERO_SEED (1U << 6) +#define BPF_F_RDONLY_PROG (1U << 7) +#define BPF_F_WRONLY_PROG (1U << 8) +#define BPF_F_CLONE (1U << 9) +#define BPF_F_MMAPABLE (1U << 10) +#define BPF_F_PRESERVE_ELEMS (1U << 11) +#define BPF_F_INNER_MAP (1U << 12) +#define BPF_F_QUERY_EFFECTIVE (1U << 0) +#define BPF_F_TEST_RUN_ON_CPU (1U << 0) + +#define BPF_STATS_RUN_TIME 0 +#define BPF_STACK_BUILD_ID_EMPTY 0 +#define BPF_STACK_BUILD_ID_VALID 1 +#define BPF_STACK_BUILD_ID_IP 2 +#define BPF_BUILD_ID_SIZE 20 +#define BPF_OBJ_NAME_LEN 16U + +#define BPF_F_RECOMPUTE_CSUM (1ULL << 0) +#define BPF_F_INVALIDATE_HASH (1ULL << 1) +#define BPF_F_HDR_FIELD_MASK 0xfULL +#define BPF_F_PSEUDO_HDR (1ULL << 4) +#define BPF_F_MARK_MANGLED_0 (1ULL << 5) +#define BPF_F_MARK_ENFORCE (1ULL << 6) +#define BPF_F_INGRESS (1ULL << 0) +#define BPF_F_TUNINFO_IPV6 (1ULL << 0) +#define BPF_F_SKIP_FIELD_MASK 0xffULL +#define BPF_F_USER_STACK (1ULL << 8) +#define BPF_F_FAST_STACK_CMP (1ULL << 9) +#define BPF_F_REUSE_STACKID (1ULL << 10) +#define BPF_F_USER_BUILD_ID (1ULL << 11) +#define BPF_F_ZERO_CSUM_TX (1ULL << 1) +#define BPF_F_DONT_FRAGMENT (1ULL << 2) +#define BPF_F_SEQ_NUMBER (1ULL << 3) +#define BPF_F_INDEX_MASK 0xffffffffULL +#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK +#define BPF_F_CTXLEN_MASK (0xfffffULL << 32) +#define BPF_F_CURRENT_NETNS (-1L) + +#define BPF_CSUM_LEVEL_QUERY 0 +#define BPF_CSUM_LEVEL_INC 1 +#define BPF_CSUM_LEVEL_DEC 2 +#define BPF_CSUM_LEVEL_RESET 3 + +#define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0) +#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1) +#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2) +#define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3) +#define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4) +#define BPF_F_ADJ_ROOM_NO_CSUM_RESET (1ULL << 5) +#define BPF_F_ADJ_ROOM_ENCAP_L2_ETH (1ULL << 6) +#define BPF_ADJ_ROOM_ENCAP_L2_MASK 0xff +#define BPF_ADJ_ROOM_ENCAP_L2_SHIFT 56 + +#define BPF_F_SYSCTL_BASE_NAME (1ULL << 0) +#define BPF_LOCAL_STORAGE_GET_F_CREATE (1ULL << 0) +#define BPF_SK_STORAGE_GET_F_CREATE BPF_LOCAL_STORAGE_GET_F_CREATE +#define BPF_F_GET_BRANCH_RECORDS_SIZE (1ULL << 0) +#define BPF_RB_NO_WAKEUP (1ULL << 0) +#define BPF_RB_FORCE_WAKEUP (1ULL << 1) +#define BPF_RB_AVAIL_DATA 0 +#define BPF_RB_RING_SIZE 1 +#define BPF_RB_CONS_POS 2 +#define BPF_RB_PROD_POS 3 +#define BPF_RINGBUF_BUSY_BIT (1U << 31) +#define BPF_RINGBUF_DISCARD_BIT (1U << 30) +#define BPF_RINGBUF_HDR_SZ 8 +#define BPF_SK_LOOKUP_F_REPLACE (1ULL << 0) +#define BPF_SK_LOOKUP_F_NO_REUSEPORT (1ULL << 1) + +#define BPF_ADJ_ROOM_NET 0 +#define BPF_ADJ_ROOM_MAC 1 +#define BPF_HDR_START_MAC 0 +#define BPF_HDR_START_NET 1 +#define BPF_LWT_ENCAP_SEG6 0 +#define BPF_LWT_ENCAP_SEG6_INLINE 1 +#define BPF_LWT_ENCAP_IP 2 +#define BPF_F_BPRM_SECUREEXEC (1ULL << 0) +#define BPF_F_BROADCAST (1ULL << 3) +#define BPF_F_EXCLUDE_INGRESS (1ULL << 4) + +#define BPF_TAG_SIZE 8 + +#define BPF_SOCK_OPS_RTO_CB_FLAG (1 << 0) +#define BPF_SOCK_OPS_RETRANS_CB_FLAG (1 << 1) +#define BPF_SOCK_OPS_STATE_CB_FLAG (1 << 2) +#define BPF_SOCK_OPS_RTT_CB_FLAG (1 << 3) +#define BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG (1 << 4) +#define BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG (1 << 5) +#define BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG (1 << 6) +#define BPF_SOCK_OPS_ALL_CB_FLAGS 0x7F + +#define BPF_SOCK_OPS_VOID 0 +#define BPF_SOCK_OPS_TIMEOUT_INIT 1 +#define BPF_SOCK_OPS_RWND_INIT 2 +#define BPF_SOCK_OPS_TCP_CONNECT_CB 3 +#define BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB 4 +#define BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB 5 +#define BPF_SOCK_OPS_NEEDS_ECN 6 +#define BPF_SOCK_OPS_BASE_RTT 7 +#define BPF_SOCK_OPS_RTO_CB 8 +#define BPF_SOCK_OPS_RETRANS_CB 9 +#define BPF_SOCK_OPS_STATE_CB 10 +#define BPF_SOCK_OPS_TCP_LISTEN_CB 11 +#define BPF_SOCK_OPS_RTT_CB 12 +#define BPF_SOCK_OPS_PARSE_HDR_OPT_CB 13 +#define BPF_SOCK_OPS_HDR_OPT_LEN_CB 14 +#define BPF_SOCK_OPS_WRITE_HDR_OPT_CB 15 + +#define BPF_TCP_ESTABLISHED 1 +#define BPF_TCP_SYN_SENT 2 +#define BPF_TCP_SYN_RECV 3 +#define BPF_TCP_FIN_WAIT1 4 +#define BPF_TCP_FIN_WAIT2 5 +#define BPF_TCP_TIME_WAIT 6 +#define BPF_TCP_CLOSE 7 +#define BPF_TCP_CLOSE_WAIT 8 +#define BPF_TCP_LAST_ACK 9 +#define BPF_TCP_LISTEN 10 +#define BPF_TCP_CLOSING 11 +#define BPF_TCP_NEW_SYN_RECV 12 +#define BPF_TCP_MAX_STATES 13 + +#define TCP_BPF_IW 1001 +#define TCP_BPF_SNDCWND_CLAMP 1002 +#define TCP_BPF_DELACK_MAX 1003 +#define TCP_BPF_RTO_MIN 1004 +#define TCP_BPF_SYN 1005 +#define TCP_BPF_SYN_IP 1006 +#define TCP_BPF_SYN_MAC 1007 +#define BPF_LOAD_HDR_OPT_TCP_SYN (1ULL << 0) +#define BPF_WRITE_HDR_TCP_CURRENT_MSS 1 +#define BPF_WRITE_HDR_TCP_SYNACK_COOKIE 2 + +#define BPF_DEVCG_ACC_MKNOD (1ULL << 0) +#define BPF_DEVCG_ACC_READ (1ULL << 1) +#define BPF_DEVCG_ACC_WRITE (1ULL << 2) +#define BPF_DEVCG_DEV_BLOCK (1ULL << 0) +#define BPF_DEVCG_DEV_CHAR (1ULL << 1) + +#define BPF_FIB_LOOKUP_DIRECT (1U << 0) +#define BPF_FIB_LOOKUP_OUTPUT (1U << 1) + +#define BPF_FIB_LKUP_RET_SUCCESS 0 +#define BPF_FIB_LKUP_RET_BLACKHOLE 1 +#define BPF_FIB_LKUP_RET_UNREACHABLE 2 +#define BPF_FIB_LKUP_RET_PROHIBIT 3 +#define BPF_FIB_LKUP_RET_NOT_FWDED 4 +#define BPF_FIB_LKUP_RET_FWD_DISABLED 5 +#define BPF_FIB_LKUP_RET_UNSUPP_LWT 6 +#define BPF_FIB_LKUP_RET_NO_NEIGH 7 +#define BPF_FIB_LKUP_RET_FRAG_NEEDED 8 + +#define BPF_MTU_CHK_SEGS (1U << 0) +#define BPF_MTU_CHK_RET_SUCCESS 0 +#define BPF_MTU_CHK_RET_FRAG_NEEDED 1 +#define BPF_MTU_CHK_RET_SEGS_TOOBIG 2 +#define BPF_FD_TYPE_RAW_TRACEPOINT 0 +#define BPF_FD_TYPE_TRACEPOINT 1 +#define BPF_FD_TYPE_KPROBE 2 +#define BPF_FD_TYPE_KRETPROBE 3 +#define BPF_FD_TYPE_UPROBE 4 +#define BPF_FD_TYPE_URETPROBE 5 +#define BPF_FLOW_DISSECTOR_F_PARSE_1ST_FRAG (1U << 0) +#define BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL (1U << 1) +#define BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP (1U << 2) + +#define BPF_LINE_INFO_LINE_NUM(line_col) ((line_col) >> 10) +#define BPF_LINE_INFO_LINE_COL(line_col) ((line_col)&0x3ff) + +#define BTF_F_COMPACT (1ULL << 0) +#define BTF_F_NONAME (1ULL << 1) +#define BTF_F_PTR_RAW (1ULL << 2) +#define BTF_F_ZERO (1ULL << 3) + +#define BPF_OK 0 +#define BPF_DROP 2 +#define BPF_REDIRECT 7 +#define BPF_LWT_REROUTE 128 + +#define XDP_PACKET_HEADROOM 256 + +#define BPF_F_ADJ_ROOM_ENCAP_L2(len) \ + (((uint64_t)len & BPF_ADJ_ROOM_ENCAP_L2_MASK) << BPF_ADJ_ROOM_ENCAP_L2_SHIFT) + +#define __bpf_md_ptr(type, name) \ + union { \ + type name; \ + uint64_t : 64; \ + } forcealign(8) + +struct bpf_insn { + uint8_t code; + uint8_t dst_reg : 4; + uint8_t src_reg : 4; + int16_t off; + int32_t imm; +}; + +struct bpf_lpm_trie_key { + uint32_t prefixlen; + uint8_t data[0]; +}; + +struct bpf_cgroup_storage_key { + uint64_t cgroup_inode_id; + uint32_t attach_type; +}; + +union bpf_iter_link_info { + struct { + uint32_t map_fd; + } map; +}; + +struct bpf_stack_build_id { + int32_t status; + unsigned char build_id[BPF_BUILD_ID_SIZE]; + union { + uint64_t offset; + uint64_t ip; + }; +}; + +union bpf_attr { + struct { + uint32_t map_type; + uint32_t key_size; + uint32_t value_size; + uint32_t max_entries; + uint32_t map_flags; + uint32_t inner_map_fd; + uint32_t numa_node; + char map_name[BPF_OBJ_NAME_LEN]; + uint32_t map_ifindex; + uint32_t btf_fd; + uint32_t btf_key_type_id; + uint32_t btf_value_type_id; + uint32_t btf_vmlinux_value_type_id; + }; + struct { + uint32_t map_fd; + uint64_t key; + union { + uint64_t value; + uint64_t next_key; + }; + uint64_t flags; + }; + struct { + uint64_t in_batch; + uint64_t out_batch; + uint64_t keys; + uint64_t values; + uint32_t count; + uint32_t map_fd; + uint64_t elem_flags; + uint64_t flags; + } batch; + struct { + uint32_t prog_type; + uint32_t insn_cnt; + uint64_t insns; + uint64_t license; + uint32_t log_level; + uint32_t log_size; + uint64_t log_buf; + uint32_t kern_version; + uint32_t prog_flags; + char prog_name[BPF_OBJ_NAME_LEN]; + uint32_t prog_ifindex; + uint32_t expected_attach_type; + uint32_t prog_btf_fd; + uint32_t func_info_rec_size; + uint64_t func_info; + uint32_t func_info_cnt; + uint32_t line_info_rec_size; + uint64_t line_info; + uint32_t line_info_cnt; + uint32_t attach_btf_id; + union { + uint32_t attach_prog_fd; + uint32_t attach_btf_obj_fd; + }; + uint32_t : 32; + uint64_t fd_array; + }; + struct { + uint64_t pathname; + uint32_t bpf_fd; + uint32_t file_flags; + }; + struct { + uint32_t target_fd; + uint32_t attach_bpf_fd; + uint32_t attach_type; + uint32_t attach_flags; + uint32_t replace_bpf_fd; + }; + struct { + uint32_t prog_fd; + uint32_t retval; + uint32_t data_size_in; + uint32_t data_size_out; + uint64_t data_in; + uint64_t data_out; + uint32_t repeat; + uint32_t duration; + uint32_t ctx_size_in; + uint32_t ctx_size_out; + uint64_t ctx_in; + uint64_t ctx_out; + uint32_t flags; + uint32_t cpu; + } test; + struct { + union { + uint32_t start_id; + uint32_t prog_id; + uint32_t map_id; + uint32_t btf_id; + uint32_t link_id; + }; + uint32_t next_id; + uint32_t open_flags; + }; + struct { + uint32_t bpf_fd; + uint32_t info_len; + uint64_t info; + } info; + struct { + uint32_t target_fd; + uint32_t attach_type; + uint32_t query_flags; + uint32_t attach_flags; + uint64_t prog_ids; + uint32_t prog_cnt; + } query; + struct { + uint64_t name; + uint32_t prog_fd; + } raw_tracepoint; + struct { + uint64_t btf; + uint64_t btf_log_buf; + uint32_t btf_size; + uint32_t btf_log_size; + uint32_t btf_log_level; + }; + struct { + uint32_t pid; + uint32_t fd; + uint32_t flags; + uint32_t buf_len; + uint64_t buf; + uint32_t prog_id; + uint32_t fd_type; + uint64_t probe_offset; + uint64_t probe_addr; + } task_fd_query; + struct { + uint32_t prog_fd; + union { + uint32_t target_fd; + uint32_t target_ifindex; + }; + uint32_t attach_type; + uint32_t flags; + union { + uint32_t target_btf_id; + struct { + uint64_t iter_info; + uint32_t iter_info_len; + }; + }; + } link_create; + struct { + uint32_t link_fd; + uint32_t new_prog_fd; + uint32_t flags; + uint32_t old_prog_fd; + } link_update; + struct { + uint32_t link_fd; + } link_detach; + struct { + uint32_t type; + } enable_stats; + struct { + uint32_t link_fd; + uint32_t flags; + } iter_create; + struct { + uint32_t prog_fd; + uint32_t map_fd; + uint32_t flags; + } prog_bind_map; +} forcealign(8); + +struct __sk_buff { + uint32_t len; + uint32_t pkt_type; + uint32_t mark; + uint32_t queue_mapping; + uint32_t protocol; + uint32_t vlan_present; + uint32_t vlan_tci; + uint32_t vlan_proto; + uint32_t priority; + uint32_t ingress_ifindex; + uint32_t ifindex; + uint32_t tc_index; + uint32_t cb[5]; + uint32_t hash; + uint32_t tc_classid; + uint32_t data; + uint32_t data_end; + uint32_t napi_id; + uint32_t family; + uint32_t remote_ip4; + uint32_t local_ip4; + uint32_t remote_ip6[4]; + uint32_t local_ip6[4]; + uint32_t remote_port; + uint32_t local_port; + uint32_t data_meta; + __bpf_md_ptr(struct bpf_flow_keys *, flow_keys); + uint64_t tstamp; + uint32_t wire_len; + uint32_t gso_segs; + __bpf_md_ptr(struct bpf_sock *, sk); + uint32_t gso_size; +}; + +struct bpf_tunnel_key { + uint32_t tunnel_id; + union { + uint32_t remote_ipv4; + uint32_t remote_ipv6[4]; + }; + uint8_t tunnel_tos; + uint8_t tunnel_ttl; + uint16_t tunnel_ext; + uint32_t tunnel_label; +}; + +struct bpf_xfrm_state { + uint32_t reqid; + uint32_t spi; + uint16_t family; + uint16_t ext; + union { + uint32_t remote_ipv4; + uint32_t remote_ipv6[4]; + }; +}; + +struct bpf_sock { + uint32_t bound_dev_if; + uint32_t family; + uint32_t type; + uint32_t protocol; + uint32_t mark; + uint32_t priority; + uint32_t src_ip4; + uint32_t src_ip6[4]; + uint32_t src_port; + uint32_t dst_port; + uint32_t dst_ip4; + uint32_t dst_ip6[4]; + uint32_t state; + int32_t rx_queue_mapping; +}; + +struct bpf_tcp_sock { + uint32_t snd_cwnd; + uint32_t srtt_us; + uint32_t rtt_min; + uint32_t snd_ssthresh; + uint32_t rcv_nxt; + uint32_t snd_nxt; + uint32_t snd_una; + uint32_t mss_cache; + uint32_t ecn_flags; + uint32_t rate_delivered; + uint32_t rate_interval_us; + uint32_t packets_out; + uint32_t retrans_out; + uint32_t total_retrans; + uint32_t segs_in; + uint32_t data_segs_in; + uint32_t segs_out; + uint32_t data_segs_out; + uint32_t lost_out; + uint32_t sacked_out; + uint64_t bytes_received; + uint64_t bytes_acked; + uint32_t dsack_dups; + uint32_t delivered; + uint32_t delivered_ce; + uint32_t icsk_retransmits; +}; + +struct bpf_sock_tuple { + union { + struct { + uint32_t saddr; /* big endian */ + uint32_t daddr; /* big endian */ + uint16_t sport; /* big endian */ + uint16_t dport; /* big endian */ + } ipv4; + struct { + uint32_t saddr[4]; /* big endian */ + uint32_t daddr[4]; /* big endian */ + uint16_t sport; /* big endian */ + uint16_t dport; /* big endian */ + } ipv6; + }; +}; + +struct bpf_xdp_sock { + uint32_t queue_id; +}; + +enum xdp_action { + XDP_ABORTED = 0, + XDP_DROP, + XDP_PASS, + XDP_TX, + XDP_REDIRECT, +}; + +struct xdp_md { + uint32_t data; + uint32_t data_end; + uint32_t data_meta; + uint32_t ingress_ifindex; + uint32_t rx_queue_index; + uint32_t egress_ifindex; +}; + +struct bpf_devmap_val { + uint32_t ifindex; + union { + int fd; + uint32_t id; + } bpf_prog; +}; + +struct bpf_cpumap_val { + uint32_t qsize; + union { + int fd; + uint32_t id; + } bpf_prog; +}; + +enum sk_action { + SK_DROP = 0, + SK_PASS, +}; + +struct sk_msg_md { + __bpf_md_ptr(void *, data); + __bpf_md_ptr(void *, data_end); + uint32_t family; + uint32_t remote_ip4; + uint32_t local_ip4; + uint32_t remote_ip6[4]; + uint32_t local_ip6[4]; + uint32_t remote_port; + uint32_t local_port; + uint32_t size; + __bpf_md_ptr(struct bpf_sock *, sk); +}; + +struct sk_reuseport_md { + __bpf_md_ptr(void *, data); + __bpf_md_ptr(void *, data_end); + uint32_t len; + uint32_t eth_protocol; + uint32_t ip_protocol; + uint32_t bind_inany; + uint32_t hash; + __bpf_md_ptr(struct bpf_sock *, sk); + __bpf_md_ptr(struct bpf_sock *, migrating_sk); +}; + +struct bpf_prog_info { + uint32_t type; + uint32_t id; + uint8_t tag[BPF_TAG_SIZE]; + uint32_t jited_prog_len; + uint32_t xlated_prog_len; + uint64_t jited_prog_insns; + uint64_t xlated_prog_insns; + uint64_t load_time; + uint32_t created_by_uid; + uint32_t nr_map_ids; + uint64_t map_ids; + char name[BPF_OBJ_NAME_LEN]; + uint32_t ifindex; + uint32_t gpl_compatible : 1; + uint32_t : 31; + uint64_t netns_dev; + uint64_t netns_ino; + uint32_t nr_jited_ksyms; + uint32_t nr_jited_func_lens; + uint64_t jited_ksyms; + uint64_t jited_func_lens; + uint32_t btf_id; + uint32_t func_info_rec_size; + uint64_t func_info; + uint32_t nr_func_info; + uint32_t nr_line_info; + uint64_t line_info; + uint64_t jited_line_info; + uint32_t nr_jited_line_info; + uint32_t line_info_rec_size; + uint32_t jited_line_info_rec_size; + uint32_t nr_prog_tags; + uint64_t prog_tags; + uint64_t run_time_ns; + uint64_t run_cnt; + uint64_t recursion_misses; +} forcealign(8); + +struct bpf_map_info { + uint32_t type; + uint32_t id; + uint32_t key_size; + uint32_t value_size; + uint32_t max_entries; + uint32_t map_flags; + char name[BPF_OBJ_NAME_LEN]; + uint32_t ifindex; + uint32_t btf_vmlinux_value_type_id; + uint64_t netns_dev; + uint64_t netns_ino; + uint32_t btf_id; + uint32_t btf_key_type_id; + uint32_t btf_value_type_id; +} forcealign(8); + +struct bpf_btf_info { + uint64_t btf; + uint32_t btf_size; + uint32_t id; + uint64_t name; + uint32_t name_len; + uint32_t kernel_btf; +} forcealign(8); + +struct bpf_link_info { + uint32_t type; + uint32_t id; + uint32_t prog_id; + union { + struct { + uint64_t tp_name; + uint32_t tp_name_len; + } raw_tracepoint; + struct { + uint32_t attach_type; + uint32_t target_obj_id; + uint32_t target_btf_id; + } tracing; + struct { + uint64_t cgroup_id; + uint32_t attach_type; + } cgroup; + struct { + uint64_t target_name; + uint32_t target_name_len; + union { + struct { + uint32_t map_id; + } map; + }; + } iter; + struct { + uint32_t netns_ino; + uint32_t attach_type; + } netns; + struct { + uint32_t ifindex; + } xdp; + }; +} forcealign(8); + +struct bpf_sock_addr { + uint32_t user_family; + uint32_t user_ip4; + uint32_t user_ip6[4]; + uint32_t user_port; + uint32_t family; + uint32_t type; + uint32_t protocol; + uint32_t msg_src_ip4; + uint32_t msg_src_ip6[4]; + __bpf_md_ptr(struct bpf_sock *, sk); +}; + +struct bpf_sock_ops { + uint32_t op; + union { + uint32_t args[4]; + uint32_t reply; + uint32_t replylong[4]; + }; + uint32_t family; + uint32_t remote_ip4; + uint32_t local_ip4; + uint32_t remote_ip6[4]; + uint32_t local_ip6[4]; + uint32_t remote_port; + uint32_t local_port; + uint32_t is_fullsock; + uint32_t snd_cwnd; + uint32_t srtt_us; + uint32_t bpf_sock_ops_cb_flags; + uint32_t state; + uint32_t rtt_min; + uint32_t snd_ssthresh; + uint32_t rcv_nxt; + uint32_t snd_nxt; + uint32_t snd_una; + uint32_t mss_cache; + uint32_t ecn_flags; + uint32_t rate_delivered; + uint32_t rate_interval_us; + uint32_t packets_out; + uint32_t retrans_out; + uint32_t total_retrans; + uint32_t segs_in; + uint32_t data_segs_in; + uint32_t segs_out; + uint32_t data_segs_out; + uint32_t lost_out; + uint32_t sacked_out; + uint32_t sk_txhash; + uint64_t bytes_received; + uint64_t bytes_acked; + __bpf_md_ptr(struct bpf_sock *, sk); + __bpf_md_ptr(void *, skb_data); + __bpf_md_ptr(void *, skb_data_end); + uint32_t skb_len; + uint32_t skb_tcp_flags; +}; + +struct bpf_perf_event_value { + uint64_t counter; + uint64_t enabled; + uint64_t running; +}; + +struct bpf_cgroup_dev_ctx { + uint32_t access_type; + uint32_t major; + uint32_t minor; +}; + +struct bpf_raw_tracepoint_args { + uint64_t args[0]; +}; + +struct bpf_fib_lookup { + uint8_t family; + uint8_t l4_protocol; + uint16_t sport; /* big endian */ + uint16_t dport; /* big endian */ + union { + uint16_t tot_len; + uint16_t mtu_result; + }; + uint32_t ifindex; + union { + uint8_t tos; + uint32_t flowinfo; /* big endian */ + uint32_t rt_metric; + }; + union { + uint32_t ipv4_src; /* big endian */ + uint32_t ipv6_src[4]; + }; + union { + uint32_t ipv4_dst; /* big endian */ + uint32_t ipv6_dst[4]; + }; + uint16_t h_vlan_proto; /* big endian */ + uint16_t h_vlan_TCI; /* big endian */ + uint8_t smac[6]; + uint8_t dmac[6]; +}; + +struct bpf_redir_neigh { + uint32_t nh_family; + union { + uint32_t ipv4_nh; /* big endian */ + uint32_t ipv6_nh[4]; + }; +}; + +struct bpf_flow_keys { + uint16_t nhoff; + uint16_t thoff; + uint16_t addr_proto; + uint8_t is_frag; + uint8_t is_first_frag; + uint8_t is_encap; + uint8_t ip_proto; + uint16_t n_proto; /* big endian */ + uint16_t sport; /* big endian */ + uint16_t dport; /* big endian */ + union { + struct { + uint32_t ipv4_src; /* big endian */ + uint32_t ipv4_dst; /* big endian */ + }; + struct { + uint32_t ipv6_src[4]; + uint32_t ipv6_dst[4]; + }; + }; + uint32_t flags; + uint32_t flow_label; +}; + +struct bpf_func_info { + uint32_t insn_off; + uint32_t type_id; +}; + +struct bpf_line_info { + uint32_t insn_off; + uint32_t file_name_off; + uint32_t line_off; + uint32_t line_col; +}; + +struct bpf_spin_lock { + uint32_t val; +}; + +struct bpf_sysctl { + uint32_t write; + uint32_t file_pos; +}; + +struct bpf_sockopt { + __bpf_md_ptr(struct bpf_sock *, sk); + __bpf_md_ptr(void *, optval); + __bpf_md_ptr(void *, optval_end); + int32_t level; + int32_t optname; + int32_t optlen; + int32_t retval; +}; + +struct bpf_pidns_info { + uint32_t pid; + uint32_t tgid; +}; + +struct bpf_sk_lookup { + union { + __bpf_md_ptr(struct bpf_sock *, sk); + uint64_t cookie; + }; + uint32_t family; + uint32_t protocol; + uint32_t remote_ip4; + uint32_t remote_ip6[4]; + uint32_t remote_port; + uint32_t local_ip4; + uint32_t local_ip6[4]; + uint32_t local_port; +}; + +struct btf_ptr { + void *ptr; + uint32_t type_id; + uint32_t flags; +}; + +/* clang-format off */ +#define __BPF_FUNC_MAPPER(FN) \ + FN(unspec), \ + FN(map_lookup_elem), \ + FN(map_update_elem), \ + FN(map_delete_elem), \ + FN(probe_read), \ + FN(ktime_get_ns), \ + FN(trace_printk), \ + FN(get_prandom_u32), \ + FN(get_smp_processor_id), \ + FN(skb_store_bytes), \ + FN(l3_csum_replace), \ + FN(l4_csum_replace), \ + FN(tail_call), \ + FN(clone_redirect), \ + FN(get_current_pid_tgid), \ + FN(get_current_uid_gid), \ + FN(get_current_comm), \ + FN(get_cgroup_classid), \ + FN(skb_vlan_push), \ + FN(skb_vlan_pop), \ + FN(skb_get_tunnel_key), \ + FN(skb_set_tunnel_key), \ + FN(perf_event_read), \ + FN(redirect), \ + FN(get_route_realm), \ + FN(perf_event_output), \ + FN(skb_load_bytes), \ + FN(get_stackid), \ + FN(csum_diff), \ + FN(skb_get_tunnel_opt), \ + FN(skb_set_tunnel_opt), \ + FN(skb_change_proto), \ + FN(skb_change_type), \ + FN(skb_under_cgroup), \ + FN(get_hash_recalc), \ + FN(get_current_task), \ + FN(probe_write_user), \ + FN(current_task_under_cgroup), \ + FN(skb_change_tail), \ + FN(skb_pull_data), \ + FN(csum_update), \ + FN(set_hash_invalid), \ + FN(get_numa_node_id), \ + FN(skb_change_head), \ + FN(xdp_adjust_head), \ + FN(probe_read_str), \ + FN(get_socket_cookie), \ + FN(get_socket_uid), \ + FN(set_hash), \ + FN(setsockopt), \ + FN(skb_adjust_room), \ + FN(redirect_map), \ + FN(sk_redirect_map), \ + FN(sock_map_update), \ + FN(xdp_adjust_meta), \ + FN(perf_event_read_value), \ + FN(perf_prog_read_value), \ + FN(getsockopt), \ + FN(override_return), \ + FN(sock_ops_cb_flags_set), \ + FN(msg_redirect_map), \ + FN(msg_apply_bytes), \ + FN(msg_cork_bytes), \ + FN(msg_pull_data), \ + FN(bind), \ + FN(xdp_adjust_tail), \ + FN(skb_get_xfrm_state), \ + FN(get_stack), \ + FN(skb_load_bytes_relative), \ + FN(fib_lookup), \ + FN(sock_hash_update), \ + FN(msg_redirect_hash), \ + FN(sk_redirect_hash), \ + FN(lwt_push_encap), \ + FN(lwt_seg6_store_bytes), \ + FN(lwt_seg6_adjust_srh), \ + FN(lwt_seg6_action), \ + FN(rc_repeat), \ + FN(rc_keydown), \ + FN(skb_cgroup_id), \ + FN(get_current_cgroup_id), \ + FN(get_local_storage), \ + FN(sk_select_reuseport), \ + FN(skb_ancestor_cgroup_id), \ + FN(sk_lookup_tcp), \ + FN(sk_lookup_udp), \ + FN(sk_release), \ + FN(map_push_elem), \ + FN(map_pop_elem), \ + FN(map_peek_elem), \ + FN(msg_push_data), \ + FN(msg_pop_data), \ + FN(rc_pointer_rel), \ + FN(spin_lock), \ + FN(spin_unlock), \ + FN(sk_fullsock), \ + FN(tcp_sock), \ + FN(skb_ecn_set_ce), \ + FN(get_listener_sock), \ + FN(skc_lookup_tcp), \ + FN(tcp_check_syncookie), \ + FN(sysctl_get_name), \ + FN(sysctl_get_current_value), \ + FN(sysctl_get_new_value), \ + FN(sysctl_set_new_value), \ + FN(strtol), \ + FN(strtoul), \ + FN(sk_storage_get), \ + FN(sk_storage_delete), \ + FN(send_signal), \ + FN(tcp_gen_syncookie), \ + FN(skb_output), \ + FN(probe_read_user), \ + FN(probe_read_kernel), \ + FN(probe_read_user_str), \ + FN(probe_read_kernel_str), \ + FN(tcp_send_ack), \ + FN(send_signal_thread), \ + FN(jiffies64), \ + FN(read_branch_records), \ + FN(get_ns_current_pid_tgid), \ + FN(xdp_output), \ + FN(get_netns_cookie), \ + FN(get_current_ancestor_cgroup_id), \ + FN(sk_assign), \ + FN(ktime_get_boot_ns), \ + FN(seq_printf), \ + FN(seq_write), \ + FN(sk_cgroup_id), \ + FN(sk_ancestor_cgroup_id), \ + FN(ringbuf_output), \ + FN(ringbuf_reserve), \ + FN(ringbuf_submit), \ + FN(ringbuf_discard), \ + FN(ringbuf_query), \ + FN(csum_level), \ + FN(skc_to_tcp6_sock), \ + FN(skc_to_tcp_sock), \ + FN(skc_to_tcp_timewait_sock), \ + FN(skc_to_tcp_request_sock), \ + FN(skc_to_udp6_sock), \ + FN(get_task_stack), \ + FN(load_hdr_opt), \ + FN(store_hdr_opt), \ + FN(reserve_hdr_opt), \ + FN(inode_storage_get), \ + FN(inode_storage_delete), \ + FN(d_path), \ + FN(copy_from_user), \ + FN(snprintf_btf), \ + FN(seq_printf_btf), \ + FN(skb_cgroup_classid), \ + FN(redirect_neigh), \ + FN(per_cpu_ptr), \ + FN(this_cpu_ptr), \ + FN(redirect_peer), \ + FN(task_storage_get), \ + FN(task_storage_delete), \ + FN(get_current_task_btf), \ + FN(bprm_opts_set), \ + FN(ktime_get_coarse_ns), \ + FN(ima_inode_hash), \ + FN(sock_from_file), \ + FN(check_mtu), \ + FN(for_each_map_elem), \ + FN(snprintf), \ + FN(sys_bpf), \ + FN(btf_find_by_name_kind), \ + FN(sys_close), \ +/* clang-format on */ + +#define __BPF_ENUM_FN(x) BPF_FUNC_##x +enum bpf_func_id { + __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID, +}; +#undef __BPF_ENUM_FN + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_BPF_H_ */ diff --git a/libc/calls/struct/filter.h b/libc/calls/struct/filter.h new file mode 100644 index 000000000..5814b4c1c --- /dev/null +++ b/libc/calls/struct/filter.h @@ -0,0 +1,59 @@ +#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_FILTER_H_ +#define COSMOPOLITAN_LIBC_CALLS_STRUCT_FILTER_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +struct sock_filter { + uint16_t code; + uint8_t jt; + uint8_t jf; + uint32_t k; +}; + +struct sock_fprog { + unsigned short len; + struct sock_filter *filter; +}; + +#define BPF_RVAL(code) ((code)&0x18) +#define BPF_A 0x10 +#define BPF_MISCOP(code) ((code)&0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +#define BPF_STMT(code, k) \ + { (unsigned short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) \ + { (unsigned short)(code), jt, jf, k } + +#define BPF_MEMWORDS 16 + +#define SKF_AD_OFF (-0x1000) +#define SKF_AD_PROTOCOL 0 +#define SKF_AD_PKTTYPE 4 +#define SKF_AD_IFINDEX 8 +#define SKF_AD_NLATTR 12 +#define SKF_AD_NLATTR_NEST 16 +#define SKF_AD_MARK 20 +#define SKF_AD_QUEUE 24 +#define SKF_AD_HATYPE 28 +#define SKF_AD_RXHASH 32 +#define SKF_AD_CPU 36 +#define SKF_AD_ALU_XOR_X 40 +#define SKF_AD_VLAN_TAG 44 +#define SKF_AD_VLAN_TAG_PRESENT 48 +#define SKF_AD_PAY_OFFSET 52 +#define SKF_AD_RANDOM 56 +#define SKF_AD_VLAN_TPID 60 +#define SKF_AD_MAX 64 +#define SKF_NET_OFF (-0x100000) +#define SKF_LL_OFF (-0x200000) +#define BPF_NET_OFF SKF_NET_OFF +#define BPF_LL_OFF SKF_LL_OFF + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_FILTER_H_ */ diff --git a/libc/calls/struct/hog.py b/libc/calls/struct/hog.py new file mode 100644 index 000000000..bc69e809d --- /dev/null +++ b/libc/calls/struct/hog.py @@ -0,0 +1,23 @@ +s=""" + BPF_SOCK_OPS_VOID, + BPF_SOCK_OPS_TIMEOUT_INIT, + BPF_SOCK_OPS_RWND_INIT, + BPF_SOCK_OPS_TCP_CONNECT_CB, + BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB, + BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, + BPF_SOCK_OPS_NEEDS_ECN, + BPF_SOCK_OPS_BASE_RTT, + BPF_SOCK_OPS_RTO_CB, + BPF_SOCK_OPS_RETRANS_CB, + BPF_SOCK_OPS_STATE_CB, + BPF_SOCK_OPS_TCP_LISTEN_CB, + BPF_SOCK_OPS_RTT_CB, + BPF_SOCK_OPS_PARSE_HDR_OPT_CB, + BPF_SOCK_OPS_HDR_OPT_LEN_CB, + BPF_SOCK_OPS_WRITE_HDR_OPT_CB, +""" + +i = 0 +for x in s.replace(',','').split(): + print("#define %s %d" % (x, i)) + i += 1 diff --git a/libc/calls/struct/seccomp.h b/libc/calls/struct/seccomp.h index b5e57e9ef..0e5cc8f8c 100644 --- a/libc/calls/struct/seccomp.h +++ b/libc/calls/struct/seccomp.h @@ -1,8 +1,45 @@ #ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SECCOMP_H_ #define COSMOPOLITAN_LIBC_CALLS_STRUCT_SECCOMP_H_ + +#define SECCOMP_SET_MODE_STRICT 0 +#define SECCOMP_SET_MODE_FILTER 1 +#define SECCOMP_GET_ACTION_AVAIL 2 +#define SECCOMP_GET_NOTIF_SIZES 3 +#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0) +#define SECCOMP_FILTER_FLAG_LOG (1UL << 1) +#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2) +#define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3) +#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4) +#define SECCOMP_RET_KILL_PROCESS 0x80000000U +#define SECCOMP_RET_KILL_THREAD 0x00000000U +#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD +#define SECCOMP_RET_TRAP 0x00030000U +#define SECCOMP_RET_ERRNO 0x00050000U +#define SECCOMP_RET_USER_NOTIF 0x7fc00000U +#define SECCOMP_RET_TRACE 0x7ff00000U +#define SECCOMP_RET_LOG 0x7ffc0000U +#define SECCOMP_RET_ALLOW 0x7fff0000U +#define SECCOMP_RET_ACTION_FULL 0xffff0000U +#define SECCOMP_RET_ACTION 0x7fff0000U +#define SECCOMP_RET_DATA 0x0000ffffU +#define SECCOMP_USER_NOTIF_FLAG_CONTINUE (1UL << 0) +#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0) +#define SECCOMP_ADDFD_FLAG_SEND (1UL << 1) + #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +#define SECCOMP_IOC_MAGIC '!' +#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr) +#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type) +#define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type) +#define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type) + +#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif) +#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp) +#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64) +#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, struct seccomp_notif_addfd) + struct seccomp_data { int32_t nr; uint32_t arch; @@ -38,17 +75,6 @@ struct seccomp_notif_addfd { uint32_t newfd_flags; }; -#define SECCOMP_IOC_MAGIC '!' -#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr) -#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type) -#define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type) -#define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type) - -#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif) -#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp) -#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64) -#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, struct seccomp_notif_addfd) - COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SECCOMP_H_ */ diff --git a/libc/calls/writev.c b/libc/calls/writev.c index fe17ab97a..7a32ddf6d 100644 --- a/libc/calls/writev.c +++ b/libc/calls/writev.c @@ -47,7 +47,7 @@ */ ssize_t writev(int fd, const struct iovec *iov, int iovlen) { int i; - ssize_t rc, rem; + ssize_t rc; if (fd >= 0 && iovlen >= 0) { if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) { @@ -77,18 +77,9 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) { if (rc == -1 && errno == EFAULT) { STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc); } else { - rem = rc != -1 ? rc : 0; - kprintf(STRACE_PROLOGUE "writev(%d, {", fd); - for (i = 0; i < MIN(5, iovlen); ++i) { - kprintf("%s{%#.*hhs%s, %'zu}", i ? ", " : "", - MAX(0, MIN(40, MIN(rem, iov[i].iov_len))), iov[i].iov_base, - MAX(0, MIN(40, MIN(rem, iov[i].iov_len))) < iov[i].iov_len - ? "..." - : "", - iov[i].iov_len); - rem -= iov[i].iov_len; - } - kprintf("%s}, %d) → %'ld% m%n", iovlen > 5 ? "..." : "", iovlen, rc); + kprintf(STRACE_PROLOGUE "readv(%d, ", fd); + __strace_iov(iov, iovlen, rc != -1 ? rc : 0); + kprintf(", %d) → %'ld% m%n", iovlen, rc); } } #endif diff --git a/libc/intrin/isdebuggerpresent.greg.c b/libc/intrin/isdebuggerpresent.greg.c index b248d88ec..4332ae24c 100644 --- a/libc/intrin/isdebuggerpresent.greg.c +++ b/libc/intrin/isdebuggerpresent.greg.c @@ -16,7 +16,6 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/issandboxed.h" #include "libc/dce.h" #include "libc/log/libfatal.internal.h" #include "libc/log/log.h" @@ -39,7 +38,7 @@ noasan noubsan int IsDebuggerPresent(bool force) { if (!force && IsGenuineCosmo()) return 0; if (!force && getenv("HEISENDEBUG")) return 0; if (IsWindows()) return NtGetPeb()->BeingDebugged; /* needs noasan */ - if (__issandboxed) return false; + if (__isworker) return false; res = 0; if ((fd = __sysv_open("/proc/self/status", O_RDONLY, 0)) >= 0) { if ((got = __sysv_read(fd, buf, sizeof(buf) - 1)) > 0) { diff --git a/libc/intrin/issandboxed.c b/libc/intrin/isworker.c similarity index 86% rename from libc/intrin/issandboxed.c rename to libc/intrin/isworker.c index 85fb44282..a2913c1e6 100644 --- a/libc/intrin/issandboxed.c +++ b/libc/intrin/isworker.c @@ -18,5 +18,11 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -// SECCOMP_SET_MODE_STRICT -bool __issandboxed; +/** + * Indicates if current execution context is a worker task. + * + * Setting this to true on things like the forked process of a web + * server is a good idea since it'll ask the C runtime to not pull + * magical stunts like attaching GDB to the process on crash. + */ +bool __isworker; diff --git a/libc/intrin/kprintf.greg.c b/libc/intrin/kprintf.greg.c index e3456b9fc..89a57c9bd 100644 --- a/libc/intrin/kprintf.greg.c +++ b/libc/intrin/kprintf.greg.c @@ -246,7 +246,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, const char *s, *f; unsigned long long x; unsigned i, j, m, rem, sign, hash, cols, prec; - char c, *p, *e, pdot, zero, flip, dang, base, quot, z[128]; + char c, *p, *e, pdot, zero, flip, dang, base, quot, uppr, z[128]; if (kistextpointer(b) || kisdangerous(b)) n = 0; if (!kistextpointer(fmt)) fmt = "!!WONTFMT"; p = b; @@ -270,6 +270,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, type = 0; cols = 0; zero = 0; + uppr = 0; abet = "0123456789abcdef"; for (;;) { switch ((c = *f++)) { @@ -302,6 +303,10 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, sign = c; continue; + case '^': + uppr = c; + continue; + case 'h': --type; continue; @@ -507,6 +512,12 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, type = 0; goto FormatString; } else { + if (p + 4 <= e) { + *p++ = 'e'; + *p++ = 'r'; + *p++ = 'r'; + *p++ = '='; + } type = 0; x = unixerr; goto FormatDecimal; @@ -558,10 +569,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, goto FormatString; } - case 'S': - c = 's'; - type = 1; - // fallthrough case 's': if (!(s = va_arg(va, const void *))) { s = sign != ' ' ? "NULL" : ""; @@ -598,6 +605,9 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, if ((t & 0300) == 0200) goto ActuallyEmitByte; ++i; EmitByte: + if (uppr && 'a' <= t && t <= 'z') { + t -= 'a' - 'A'; + } if (UNLIKELY(quot) && (t == '\\' || ((t == '"' && c == 's') || (t == '\'' && c == 'c')))) { if (p + 2 <= e) { @@ -671,9 +681,15 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va, if (!t) break; ++i; EmitChar: - if (t <= 0x7f) { - goto EmitByte; - } else if (t <= 0x7ff) { + if (t <= 0x7f) goto EmitByte; + if (uppr) { + if (weaken(towupper)) { + t = weaken(towupper)(t); + } else if (uppr && 'a' <= t && t <= 'z') { + t -= 'a' - 'A'; + } + } + if (t <= 0x7ff) { if (p + 2 <= e) { p[0] = 0300 | (t >> 6); p[1] = 0200 | (t & 077); @@ -886,6 +902,7 @@ privileged void kvprintf(const char *fmt, va_list v) { * - `+` plus leftpad if positive (aligns w/ negatives) * - ` ` space leftpad if positive (aligns w/ negatives) * - `#` represent value with literal syntax, e.g. 0x, 0b, quotes + * - `^` uppercasing w/ towupper() if linked, otherwise toupper() * * Error numbers: * diff --git a/libc/log/backtrace2.c b/libc/log/backtrace2.c index 97f73a2c6..5cdcd7f91 100644 --- a/libc/log/backtrace2.c +++ b/libc/log/backtrace2.c @@ -21,7 +21,6 @@ #include "libc/bits/safemacros.internal.h" #include "libc/bits/weaken.h" #include "libc/calls/calls.h" -#include "libc/calls/issandboxed.h" #include "libc/calls/sigbits.h" #include "libc/calls/strace.internal.h" #include "libc/dce.h" @@ -160,7 +159,7 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) { } static int PrintBacktrace(int fd, const struct StackFrame *bp) { - if (!IsTiny() && !__issandboxed) { + if (!IsTiny() && !__isworker) { if (PrintBacktraceUsingAddr2line(fd, bp) != -1) { return 0; } diff --git a/libc/log/checkfail.c b/libc/log/checkfail.c index 9709215d9..4944b53e9 100644 --- a/libc/log/checkfail.c +++ b/libc/log/checkfail.c @@ -21,6 +21,7 @@ #include "libc/calls/strace.internal.h" #include "libc/errno.h" #include "libc/fmt/fmt.h" +#include "libc/intrin/kprintf.h" #include "libc/log/check.h" #include "libc/log/color.internal.h" #include "libc/log/internal.h" @@ -28,6 +29,9 @@ #include "libc/log/log.h" #include "libc/runtime/memtrack.internal.h" #include "libc/runtime/runtime.h" +#include "libc/stdio/stdio.h" + +STATIC_YOINK("strerror_wr"); /** * Handles failure of CHECK_xx() macros. @@ -44,59 +48,26 @@ relegated void __check_fail(const char *suffix, const char *opstr, __strace = 0; g_ftrace = 0; e = errno; - p = __fatalbuf; __start_fatal(file, line); __stpcpy(hostname, "unknown"); gethostname(hostname, sizeof(hostname)); - p = __stpcpy(p, "check failed on "); - p = __stpcpy(p, hostname); - p = __stpcpy(p, " pid "); - p = __intcpy(p, __getpid()); - p = __stpcpy(p, "\n"); - p = __stpcpy(p, "\tCHECK_"); - for (; *suffix; ++suffix) { - *p++ = *suffix - ('a' <= *suffix && *suffix <= 'z') * 32; - } - p = __stpcpy(p, "("); - p = __stpcpy(p, wantstr); - p = __stpcpy(p, ", "); - p = __stpcpy(p, gotstr); - p = __stpcpy(p, ");\n\t\t → 0x"); - p = __hexcpy(p, want); - p = __stpcpy(p, " ("); - p = __stpcpy(p, wantstr); - p = __stpcpy(p, ")\n\t\t"); - p = __stpcpy(p, opstr); - p = __stpcpy(p, " 0x"); - p = __hexcpy(p, got); - p = __stpcpy(p, " ("); - p = __stpcpy(p, gotstr); - p = __stpcpy(p, ")\n"); + kprintf("check failed on %s pid %d%n", hostname, getpid()); + kprintf("\tCHECK_%^s(%s, %s);%n", suffix, wantstr, gotstr); + kprintf("\t\t → %p (%s)%n", want, wantstr); + kprintf("\t\t%s %p (%s)%n", opstr, got, gotstr); if (!isempty(fmt)) { - *p++ = '\t'; + kprintf("\t"); va_start(va, fmt); - p += (vsprintf)(p, fmt, va); + kvprintf(fmt, va); va_end(va); - *p++ = '\n'; + kprintf("%n"); } - p = __stpcpy(p, "\t"); - p = __stpcpy(p, strerror(e)); - p = __stpcpy(p, "\n\t"); - p = __stpcpy(p, SUBTLE); - p = __stpcpy(p, program_invocation_name); - if (__argc > 1) p = __stpcpy(p, " \\"); - p = __stpcpy(p, RESET); - p = __stpcpy(p, "\n"); - __write(__fatalbuf, p - __fatalbuf); + kprintf("\t%m%n\t%s%s", SUBTLE, program_invocation_name); for (i = 1; i < __argc; ++i) { - p = __fatalbuf; - p = __stpcpy(p, "\t\t"); - p = __stpcpy(p, __argv[i]); - if (i < __argc - 1) p = __stpcpy(p, " \\"); - p = __stpcpy(p, "\n"); + kprintf(" %s", __argv[i]); } + kprintf("%s%n", RESET); if (!IsTiny() && e == ENOMEM) { - __write("\n", 1); PrintMemoryIntervals(2, &_mmi); } __die(); diff --git a/libc/log/oncrash.c b/libc/log/oncrash.c index b55773594..05771904f 100644 --- a/libc/log/oncrash.c +++ b/libc/log/oncrash.c @@ -19,7 +19,6 @@ #include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/calls/issandboxed.h" #include "libc/calls/sigbits.h" #include "libc/calls/strace.internal.h" #include "libc/calls/struct/sigaction.h" @@ -200,10 +199,8 @@ relegated void ShowCrashReport(int err, int sig, struct siginfo *si, names.version[0] = 0; names.nodename[0] = 0; __stpcpy(host, "unknown"); - if (!__issandboxed) { - gethostname(host, sizeof(host)); - uname(&names); - } + gethostname(host, sizeof(host)); + uname(&names); p = buf; errno = err; kprintf("%n%serror%s: Uncaught %G (%s) on %s pid %d%n" @@ -292,8 +289,7 @@ relegated noinstrument void __oncrash(int sig, struct siginfo *si, DebugBreak(); } else if (__nocolor || g_isrunningundermake) { gdbpid = -1; - } else if (!IsTiny() && IsLinux() && FindDebugBinary() && - !__issandboxed) { + } else if (!IsTiny() && IsLinux() && FindDebugBinary() && !__isworker) { RestoreDefaultCrashSignalHandlers(); gdbpid = AttachDebugger( ((sig == SIGTRAP || sig == SIGQUIT) && diff --git a/libc/log/restoretty.c b/libc/log/restoretty.c index 22134c463..02966ef0f 100644 --- a/libc/log/restoretty.c +++ b/libc/log/restoretty.c @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/issandboxed.h" #include "libc/calls/struct/termios.h" #include "libc/calls/termios.h" #include "libc/errno.h" @@ -52,7 +51,7 @@ const void *const g_oldtermios_ctor[] initarray = { void __restore_tty(int fd) { int e; - if (!__issandboxed) { + if (!__isworker) { e = errno; if (g_oldtermios.c_lflag && !__nocolor && isatty(fd)) { write(fd, ANSI_RESTORE, strlen(ANSI_RESTORE)); diff --git a/libc/log/startfatal.c b/libc/log/startfatal.c index 9a50bd4db..5fda7877f 100644 --- a/libc/log/startfatal.c +++ b/libc/log/startfatal.c @@ -28,7 +28,7 @@ */ relegated void __start_fatal(const char *file, int line) { __restore_tty(1); - kprintf("\r%serror%s:%s:%d:%s%s: ", !__nocolor ? "\e[J\e[30;101m" : "", + kprintf("%r%serror%s:%s:%d:%s%s: ", !__nocolor ? "\e[J\e[30;101m" : "", !__nocolor ? "\e[94;49m" : "", file, line, program_invocation_short_name, !__nocolor ? "\e[0m" : ""); } diff --git a/libc/runtime/getsymboltable.c b/libc/runtime/getsymboltable.c index 9bd119970..584170d26 100644 --- a/libc/runtime/getsymboltable.c +++ b/libc/runtime/getsymboltable.c @@ -19,7 +19,6 @@ #include "libc/assert.h" #include "libc/bits/bits.h" #include "libc/bits/weaken.h" -#include "libc/calls/issandboxed.h" #include "libc/calls/strace.internal.h" #include "libc/macros.internal.h" #include "libc/runtime/runtime.h" @@ -118,7 +117,7 @@ static struct SymbolTable *GetSymbolTableFromElf(void) { struct SymbolTable *GetSymbolTable(void) { int ft, st; struct Zipos *z; - if (!g_symtab && !__issandboxed) { + if (!g_symtab && !__isworker) { ft = g_ftrace, g_ftrace = 0; st = __strace, __strace = 0; if (weaken(__zipos_get) && (z = weaken(__zipos_get)())) { diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index b22492e42..7f81645e4 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -228,8 +228,12 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size, */ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { - STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → ...", addr, size, - DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off); +#if defined(SYSDEBUG) && (_KERNTRACE || _NTTRACE) + if (IsWindows()) { + STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → ...", addr, size, + DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off); + } +#endif void *res; char *p = addr; struct DirectMap dm; diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h index d3e6baa78..9181de853 100644 --- a/libc/runtime/runtime.h +++ b/libc/runtime/runtime.h @@ -39,6 +39,7 @@ extern uint8_t __zip_start[]; /* αpε */ extern uint8_t __zip_end[]; /* αpε */ extern bool ftrace_enabled; extern size_t __virtualmax; +extern bool __isworker; void mcount(void); unsigned long getauxval(unsigned long); diff --git a/libc/sock/asanmsghdr.c b/libc/sock/asanmsghdr.c new file mode 100644 index 000000000..3d826738e --- /dev/null +++ b/libc/sock/asanmsghdr.c @@ -0,0 +1,31 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2022 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/intrin/asan.internal.h" +#include "libc/sock/sock.h" + +bool __asan_is_valid_msghdr(const struct msghdr *msg) { + if (!__asan_is_valid(msg, sizeof(struct msghdr))) return false; + if (msg->msg_name) { + if (!__asan_is_valid(msg->msg_name, msg->msg_namelen)) return false; + } + if (msg->msg_control) { + if (!__asan_is_valid(msg->msg_control, msg->msg_controllen)) return false; + } + return __asan_is_valid_iov(msg->msg_iov, msg->msg_iovlen); +} diff --git a/libc/sock/internal.h b/libc/sock/internal.h index 5fe8fccc2..50486fb8a 100644 --- a/libc/sock/internal.h +++ b/libc/sock/internal.h @@ -132,6 +132,7 @@ int sys_select_nt(int, fd_set *, fd_set *, fd_set *, struct timeval *) hidden; int sys_shutdown_nt(struct Fd *, int) hidden; int sys_setsockopt_nt(struct Fd *, int, int, const void *, uint32_t) hidden; +bool __asan_is_valid_msghdr(const struct msghdr *); ssize_t sys_send_nt(int, const struct iovec *, size_t, uint32_t) hidden; ssize_t sys_recv_nt(struct Fd *, const struct iovec *, size_t, uint32_t) hidden; size_t __iovec2nt(struct NtIovec[hasatleast 16], const struct iovec *, diff --git a/libc/sock/recvmsg.c b/libc/sock/recvmsg.c index 9c7a0ec62..137b6e74f 100644 --- a/libc/sock/recvmsg.c +++ b/libc/sock/recvmsg.c @@ -39,34 +39,58 @@ * @restartable (unless SO_RCVTIMEO) */ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) { - ssize_t got; - if (!IsWindows()) { + ssize_t rc, got; + if (IsAsan() && !__asan_is_valid_msghdr(msg)) { + rc = efault(); + } else if (!IsWindows()) { got = sys_recvmsg(fd, msg, flags); - /* An address was provided, convert from BSD form */ + // An address was provided, convert from BSD form if (msg->msg_name && IsBsd() && got != -1) { sockaddr2linux(msg->msg_name); } - return got; - } else { - if (__isfdopen(fd)) { - if (msg->msg_control) return einval(); /* control msg not supported */ + rc = got; + } else if (__isfdopen(fd)) { + if (!msg->msg_control) { if (__isfdkind(fd, kFdSocket)) { - return sys_recvfrom_nt(&g_fds.p[fd], msg->msg_iov, msg->msg_iovlen, - flags, msg->msg_name, &msg->msg_namelen); + rc = sys_recvfrom_nt(&g_fds.p[fd], msg->msg_iov, msg->msg_iovlen, flags, + msg->msg_name, &msg->msg_namelen); } else if (__isfdkind(fd, kFdFile) && !msg->msg_name) { /* socketpair */ - if (flags) return einval(); - if ((got = sys_read_nt(&g_fds.p[fd], msg->msg_iov, msg->msg_iovlen, - -1)) != -1) { - msg->msg_flags = 0; - return got; + if (!flags) { + if ((got = sys_read_nt(&g_fds.p[fd], msg->msg_iov, msg->msg_iovlen, + -1)) != -1) { + msg->msg_flags = 0; + rc = got; + } else { + rc = -1; + } } else { - return -1; + rc = einval(); // flags not supported on nt } } else { - return enotsock(); + rc = enotsock(); } } else { - return ebadf(); + rc = einval(); // control msg not supported on nt + } + } else { + rc = ebadf(); + } +#if defined(SYSDEBUG) && _DATATRACE + if (__strace > 0) { + if (!msg || (rc == -1 && errno == EFAULT)) { + DATATRACE("recvmsg(%d, %p, %#x) → %'ld% m", fd, msg, flags, rc); + } else { + kprintf(STRACE_PROLOGUE "recvmsg(%d, [{"); + if (msg->msg_namelen) + kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name); + if (msg->msg_controllen) + kprintf(".control=%#.*hhs, ", msg->msg_controllen, msg->msg_control); + if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags); + kprintf(".iov=", fd); + __strace_iov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0); + kprintf("}], %#x) → %'ld% m%n", flags, rc); } } +#endif + return rc; } diff --git a/libc/sock/sendmsg.c b/libc/sock/sendmsg.c index 210bf2cf0..d338ded3e 100644 --- a/libc/sock/sendmsg.c +++ b/libc/sock/sendmsg.c @@ -18,8 +18,11 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/assert.h" #include "libc/calls/internal.h" +#include "libc/calls/strace.internal.h" #include "libc/calls/struct/iovec.h" #include "libc/dce.h" +#include "libc/intrin/asan.internal.h" +#include "libc/intrin/kprintf.h" #include "libc/sock/internal.h" #include "libc/sock/sock.h" #include "libc/str/str.h" @@ -39,35 +42,57 @@ * @restartable (unless SO_RCVTIMEO) */ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) { - if (!IsWindows()) { + int64_t rc; + char addr2[128]; + struct msghdr msg2; + if (IsAsan() && !__asan_is_valid_msghdr(msg)) { + rc = efault(); + } else if (!IsWindows()) { if (IsBsd() && msg->msg_name) { /* An optional address is provided, convert it to the BSD form */ - char addr2[128]; - struct msghdr msg2; - if (msg->msg_namelen > sizeof(addr2)) return einval(); - memcpy(&addr2[0], msg->msg_name, msg->msg_namelen); - sockaddr2bsd(&addr2[0]); - - /* Copy all of msg (except for msg_name) into the new ephemeral local */ - memcpy(&msg2, msg, sizeof(msg2)); - msg2.msg_name = &addr2[0]; - return sys_sendmsg(fd, &msg2, flags); + if (msg->msg_namelen <= sizeof(addr2)) { + memcpy(&addr2[0], msg->msg_name, msg->msg_namelen); + sockaddr2bsd(&addr2[0]); + /* Copy all of msg (except for msg_name) into the new ephemeral local */ + memcpy(&msg2, msg, sizeof(msg2)); + msg2.msg_name = &addr2[0]; + rc = sys_sendmsg(fd, &msg2, flags); + } else { + rc = einval(); + } } /* else do the syscall */ - return sys_sendmsg(fd, msg, flags); - } else { - if (__isfdopen(fd)) { - if (msg->msg_control) return einval(); /* control msg not supported */ - if (__isfdkind(fd, kFdSocket)) { - return sys_sendto_nt(fd, msg->msg_iov, msg->msg_iovlen, flags, - msg->msg_name, msg->msg_namelen); - } else if (__isfdkind(fd, kFdFile)) { - return sys_write_nt(fd, msg->msg_iov, msg->msg_iovlen, -1); - } else { - return enotsock(); - } + rc = sys_sendmsg(fd, msg, flags); + } else if (__isfdopen(fd)) { + if (msg->msg_control) { + rc = einval(); /* control msg not supported */ + } else if (__isfdkind(fd, kFdSocket)) { + rc = sys_sendto_nt(fd, msg->msg_iov, msg->msg_iovlen, flags, + msg->msg_name, msg->msg_namelen); + } else if (__isfdkind(fd, kFdFile)) { + rc = sys_write_nt(fd, msg->msg_iov, msg->msg_iovlen, -1); } else { - return ebadf(); + rc = enotsock(); + } + } else { + rc = ebadf(); + } +#if defined(SYSDEBUG) && _DATATRACE + if (__strace > 0) { + if (!msg || (rc == -1 && errno == EFAULT)) { + DATATRACE("sendmsg(%d, %p, %#x) → %'ld% m", fd, msg, flags, rc); + } else { + kprintf(STRACE_PROLOGUE "sendmsg(%d, {"); + if (msg->msg_namelen) + kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name); + if (msg->msg_controllen) + kprintf(".control=%#.*hhs, ", msg->msg_controllen, msg->msg_control); + if (msg->msg_flags) kprintf(".flags=%#x, ", msg->msg_flags); + kprintf(".iov=", fd); + __strace_iov(msg->msg_iov, msg->msg_iovlen, rc != -1 ? rc : 0); + kprintf("}, %#x) → %'ld% m%n", flags, rc); } } +#endif + return rc; } diff --git a/libc/sock/syslog.c b/libc/sock/syslog.c index 75a5b0349..1b325ab2b 100644 --- a/libc/sock/syslog.c +++ b/libc/sock/syslog.c @@ -50,7 +50,12 @@ static int log_mask; static uint16_t log_id; /* Used for Windows EvtID */ static int64_t log_fd = -1; -static const struct sockaddr_un log_addr = {AF_UNIX, "/dev/log"}; +static const char *const kLogPaths[] = { + "/dev/log", + // "/var/run/log", // TODO: Help with XNU and FreeBSD. +}; + +static struct sockaddr_un log_addr = {AF_UNIX, "/dev/log"}; static int64_t Time(int64_t *tp) { struct timespec ts; @@ -73,16 +78,20 @@ forceinline int is_lost_conn(int e) { } static void __openlog() { + int i; if (IsWindows()) { log_fd = RegisterEventSource(NULL, log_ident); } else { log_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (log_fd >= 0) { - int rc = connect(log_fd, (void *)&log_addr, sizeof(log_addr)); - if (rc < 0) { - printf("ERR: connect(openlog) failed: %s (errno=%d)\n", strerror(errno), - errno); + for (i = 0; i < ARRAYLEN(kLogPaths); ++i) { + strcpy(log_addr.sun_path, kLogPaths[i]); + if (!connect(log_fd, (void *)&log_addr, sizeof(log_addr))) { + return; + } } + printf("ERR: connect(openlog) failed: %s (errno=%d)\n", strerror(errno), + errno); } } } diff --git a/libc/sock/syslog.h b/libc/sock/syslog.h index 5342509bb..368fd6c18 100644 --- a/libc/sock/syslog.h +++ b/libc/sock/syslog.h @@ -1,11 +1,9 @@ #ifndef COSMOPOLITAN_LIBC_SOCK_SYSLOG_H_ #define COSMOPOLITAN_LIBC_SOCK_SYSLOG_H_ - - #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -#define LOG_PRI(p) ((p) & LOG_PRIMASK) +#define LOG_PRI(p) (LOG_PRIMASK & (p)) int setlogmask(int); void openlog(const char *, int, int); diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 1a3c4037b..d8910826b 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -3308,42 +3308,4 @@ syscon misc ETH_P_RARP 0x8035 0 0 0 0 0 syscon misc ETH_P_SCA 0x6007 0 0 0 0 0 syscon misc ETH_P_WAN_PPP 7 0 0 0 0 0 -syscon log LOG_EMERG 0 0 0 0 0 0 # consensus -syscon log LOG_KERN 0 0 0 0 0 0 # consensus -syscon log LOG_ALERT 1 1 1 1 1 1 # unix consensus -syscon log LOG_PID 1 1 1 1 1 1 # unix consensus -syscon log LOG_CONS 2 2 2 2 2 2 # unix consensus -syscon log LOG_CRIT 2 2 2 2 2 2 # unix consensus -syscon log LOG_ERR 3 3 3 3 3 3 # unix consensus -syscon log LOG_ODELAY 4 4 4 4 4 4 # unix consensus -syscon log LOG_WARNING 4 4 4 4 4 4 # unix consensus -syscon log LOG_NOTICE 5 5 5 5 5 5 # unix consensus -syscon log LOG_INFO 6 6 6 6 6 6 # unix consensus -syscon log LOG_DEBUG 7 7 7 7 7 7 # unix consensus -syscon log LOG_PRIMASK 7 7 7 7 7 7 # unix consensus -syscon log LOG_NDELAY 8 8 8 8 8 8 # unix consensus -syscon log LOG_USER 8 8 8 8 8 8 # unix consensus -syscon log LOG_MAIL 0x10 0x10 0x10 0x10 0x10 0x10 # unix consensus -syscon log LOG_NOWAIT 0x10 0x10 0x10 0x10 0x10 0x10 # unix consensus -syscon log LOG_DAEMON 24 24 24 24 24 24 # unix consensus -syscon log LOG_NFACILITIES 24 25 24 24 24 24 -syscon log LOG_AUTH 0x20 0x20 0x20 0x20 0x20 0x20 # unix consensus -syscon log LOG_PERROR 0x20 0x20 0x20 0x20 0x20 0x20 # unix consensus -syscon log LOG_SYSLOG 40 40 40 40 40 40 # unix consensus -syscon log LOG_LPR 48 48 48 48 48 48 # unix consensus -syscon log LOG_NEWS 56 56 56 56 56 56 # unix consensus -syscon log LOG_UUCP 0x40 0x40 0x40 0x40 0x40 40 # unix consensus -syscon log LOG_CRON 72 72 72 72 72 72 # unix consensus -syscon log LOG_SELECT 76 0 0 0 0 0 -syscon log LOG_SENSE 77 0 0 0 0 0 -syscon log LOG_LOCAL0 0x80 0x80 0x80 0x80 0x80 0x80 # unix consensus -syscon log LOG_LOCAL1 136 136 136 136 136 136 # unix consensus -syscon log LOG_LOCAL2 144 144 144 144 144 144 # unix consensus -syscon log LOG_LOCAL3 152 152 152 152 152 152 # unix consensus -syscon log LOG_LOCAL4 160 160 160 160 160 160 # unix consensus -syscon log LOG_LOCAL5 168 168 168 168 168 168 # unix consensus -syscon log LOG_LOCAL6 176 176 176 176 176 176 # unix consensus -syscon log LOG_LOCAL7 184 184 184 184 184 184 # unix consensus -syscon log LOG_FACMASK 0x03f8 0x03f8 0x03f8 0x03f8 0x03f8 0x03f8 # unix consensus - # https://youtu.be/GUQUD3IMbb4?t=85 diff --git a/libc/sysv/consts/LOG_ALERT.S b/libc/sysv/consts/LOG_ALERT.S deleted file mode 100644 index e06f8d0fa..000000000 --- a/libc/sysv/consts/LOG_ALERT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_ALERT,1,1,1,1,1,1 diff --git a/libc/sysv/consts/LOG_AUTH.S b/libc/sysv/consts/LOG_AUTH.S deleted file mode 100644 index f810118f8..000000000 --- a/libc/sysv/consts/LOG_AUTH.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_AUTH,0x20,0x20,0x20,0x20,0x20,0x20 diff --git a/libc/sysv/consts/LOG_CONS.S b/libc/sysv/consts/LOG_CONS.S deleted file mode 100644 index ece48311f..000000000 --- a/libc/sysv/consts/LOG_CONS.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_CONS,2,2,2,2,2,2 diff --git a/libc/sysv/consts/LOG_CRIT.S b/libc/sysv/consts/LOG_CRIT.S deleted file mode 100644 index d623e5551..000000000 --- a/libc/sysv/consts/LOG_CRIT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_CRIT,2,2,2,2,2,2 diff --git a/libc/sysv/consts/LOG_CRON.S b/libc/sysv/consts/LOG_CRON.S deleted file mode 100644 index f392b84ca..000000000 --- a/libc/sysv/consts/LOG_CRON.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_CRON,72,72,72,72,72,72 diff --git a/libc/sysv/consts/LOG_DAEMON.S b/libc/sysv/consts/LOG_DAEMON.S deleted file mode 100644 index 10f3772dd..000000000 --- a/libc/sysv/consts/LOG_DAEMON.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_DAEMON,24,24,24,24,24,24 diff --git a/libc/sysv/consts/LOG_DEBUG.S b/libc/sysv/consts/LOG_DEBUG.S deleted file mode 100644 index 3e39ee2b6..000000000 --- a/libc/sysv/consts/LOG_DEBUG.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_DEBUG,7,7,7,7,7,7 diff --git a/libc/sysv/consts/LOG_EMERG.S b/libc/sysv/consts/LOG_EMERG.S deleted file mode 100644 index 48aa6fd42..000000000 --- a/libc/sysv/consts/LOG_EMERG.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_EMERG,0,0,0,0,0,0 diff --git a/libc/sysv/consts/LOG_ERR.S b/libc/sysv/consts/LOG_ERR.S deleted file mode 100644 index bf9507d94..000000000 --- a/libc/sysv/consts/LOG_ERR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_ERR,3,3,3,3,3,3 diff --git a/libc/sysv/consts/LOG_FACMASK.S b/libc/sysv/consts/LOG_FACMASK.S deleted file mode 100644 index 25d730624..000000000 --- a/libc/sysv/consts/LOG_FACMASK.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_FACMASK,0x03f8,0x03f8,0x03f8,0x03f8,0x03f8,0x03f8 diff --git a/libc/sysv/consts/LOG_INFO.S b/libc/sysv/consts/LOG_INFO.S deleted file mode 100644 index 1eb6985af..000000000 --- a/libc/sysv/consts/LOG_INFO.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_INFO,6,6,6,6,6,6 diff --git a/libc/sysv/consts/LOG_KERN.S b/libc/sysv/consts/LOG_KERN.S deleted file mode 100644 index 20c97fe34..000000000 --- a/libc/sysv/consts/LOG_KERN.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_KERN,0,0,0,0,0,0 diff --git a/libc/sysv/consts/LOG_LOCAL0.S b/libc/sysv/consts/LOG_LOCAL0.S deleted file mode 100644 index fcd14530b..000000000 --- a/libc/sysv/consts/LOG_LOCAL0.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL0,0x80,0x80,0x80,0x80,0x80,0x80 diff --git a/libc/sysv/consts/LOG_LOCAL1.S b/libc/sysv/consts/LOG_LOCAL1.S deleted file mode 100644 index 36ffdde59..000000000 --- a/libc/sysv/consts/LOG_LOCAL1.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL1,136,136,136,136,136,136 diff --git a/libc/sysv/consts/LOG_LOCAL2.S b/libc/sysv/consts/LOG_LOCAL2.S deleted file mode 100644 index 1ddfe950c..000000000 --- a/libc/sysv/consts/LOG_LOCAL2.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL2,144,144,144,144,144,144 diff --git a/libc/sysv/consts/LOG_LOCAL3.S b/libc/sysv/consts/LOG_LOCAL3.S deleted file mode 100644 index d8af1d662..000000000 --- a/libc/sysv/consts/LOG_LOCAL3.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL3,152,152,152,152,152,152 diff --git a/libc/sysv/consts/LOG_LOCAL4.S b/libc/sysv/consts/LOG_LOCAL4.S deleted file mode 100644 index 6abccdf09..000000000 --- a/libc/sysv/consts/LOG_LOCAL4.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL4,160,160,160,160,160,160 diff --git a/libc/sysv/consts/LOG_LOCAL5.S b/libc/sysv/consts/LOG_LOCAL5.S deleted file mode 100644 index 6062a680f..000000000 --- a/libc/sysv/consts/LOG_LOCAL5.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL5,168,168,168,168,168,168 diff --git a/libc/sysv/consts/LOG_LOCAL6.S b/libc/sysv/consts/LOG_LOCAL6.S deleted file mode 100644 index 53c16ccac..000000000 --- a/libc/sysv/consts/LOG_LOCAL6.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL6,176,176,176,176,176,176 diff --git a/libc/sysv/consts/LOG_LOCAL7.S b/libc/sysv/consts/LOG_LOCAL7.S deleted file mode 100644 index 8b0d73e2a..000000000 --- a/libc/sysv/consts/LOG_LOCAL7.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LOCAL7,184,184,184,184,184,184 diff --git a/libc/sysv/consts/LOG_LPR.S b/libc/sysv/consts/LOG_LPR.S deleted file mode 100644 index 0be5f536c..000000000 --- a/libc/sysv/consts/LOG_LPR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_LPR,48,48,48,48,48,48 diff --git a/libc/sysv/consts/LOG_MAIL.S b/libc/sysv/consts/LOG_MAIL.S deleted file mode 100644 index e534e178f..000000000 --- a/libc/sysv/consts/LOG_MAIL.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_MAIL,0x10,0x10,0x10,0x10,0x10,0x10 diff --git a/libc/sysv/consts/LOG_NDELAY.S b/libc/sysv/consts/LOG_NDELAY.S deleted file mode 100644 index af158f72c..000000000 --- a/libc/sysv/consts/LOG_NDELAY.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_NDELAY,8,8,8,8,8,8 diff --git a/libc/sysv/consts/LOG_NEWS.S b/libc/sysv/consts/LOG_NEWS.S deleted file mode 100644 index af6bc33e1..000000000 --- a/libc/sysv/consts/LOG_NEWS.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_NEWS,56,56,56,56,56,56 diff --git a/libc/sysv/consts/LOG_NFACILITIES.S b/libc/sysv/consts/LOG_NFACILITIES.S deleted file mode 100644 index 924f57b8d..000000000 --- a/libc/sysv/consts/LOG_NFACILITIES.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_NFACILITIES,24,25,24,24,24,24 diff --git a/libc/sysv/consts/LOG_NOTICE.S b/libc/sysv/consts/LOG_NOTICE.S deleted file mode 100644 index 7164aa399..000000000 --- a/libc/sysv/consts/LOG_NOTICE.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_NOTICE,5,5,5,5,5,5 diff --git a/libc/sysv/consts/LOG_NOWAIT.S b/libc/sysv/consts/LOG_NOWAIT.S deleted file mode 100644 index 415b564d8..000000000 --- a/libc/sysv/consts/LOG_NOWAIT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_NOWAIT,0x10,0x10,0x10,0x10,0x10,0x10 diff --git a/libc/sysv/consts/LOG_ODELAY.S b/libc/sysv/consts/LOG_ODELAY.S deleted file mode 100644 index 5b97aa3b3..000000000 --- a/libc/sysv/consts/LOG_ODELAY.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_ODELAY,4,4,4,4,4,4 diff --git a/libc/sysv/consts/LOG_PERROR.S b/libc/sysv/consts/LOG_PERROR.S deleted file mode 100644 index a80b7f8df..000000000 --- a/libc/sysv/consts/LOG_PERROR.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_PERROR,0x20,0x20,0x20,0x20,0x20,0x20 diff --git a/libc/sysv/consts/LOG_PID.S b/libc/sysv/consts/LOG_PID.S deleted file mode 100644 index 7fff6d6b4..000000000 --- a/libc/sysv/consts/LOG_PID.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_PID,1,1,1,1,1,1 diff --git a/libc/sysv/consts/LOG_PRIMASK.S b/libc/sysv/consts/LOG_PRIMASK.S deleted file mode 100644 index bd140bfbe..000000000 --- a/libc/sysv/consts/LOG_PRIMASK.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_PRIMASK,7,7,7,7,7,7 diff --git a/libc/sysv/consts/LOG_SELECT.S b/libc/sysv/consts/LOG_SELECT.S deleted file mode 100644 index 431f1f2c2..000000000 --- a/libc/sysv/consts/LOG_SELECT.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_SELECT,76,0,0,0,0,0 diff --git a/libc/sysv/consts/LOG_SENSE.S b/libc/sysv/consts/LOG_SENSE.S deleted file mode 100644 index a48c8e947..000000000 --- a/libc/sysv/consts/LOG_SENSE.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_SENSE,77,0,0,0,0,0 diff --git a/libc/sysv/consts/LOG_SYSLOG.S b/libc/sysv/consts/LOG_SYSLOG.S deleted file mode 100644 index 42420d291..000000000 --- a/libc/sysv/consts/LOG_SYSLOG.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_SYSLOG,40,40,40,40,40,40 diff --git a/libc/sysv/consts/LOG_USER.S b/libc/sysv/consts/LOG_USER.S deleted file mode 100644 index 71538bc39..000000000 --- a/libc/sysv/consts/LOG_USER.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_USER,8,8,8,8,8,8 diff --git a/libc/sysv/consts/LOG_UUCP.S b/libc/sysv/consts/LOG_UUCP.S deleted file mode 100644 index daa7b2fbe..000000000 --- a/libc/sysv/consts/LOG_UUCP.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_UUCP,0x40,0x40,0x40,0x40,0x40,40 diff --git a/libc/sysv/consts/LOG_WARNING.S b/libc/sysv/consts/LOG_WARNING.S deleted file mode 100644 index 805b9731a..000000000 --- a/libc/sysv/consts/LOG_WARNING.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon log,LOG_WARNING,4,4,4,4,4,4 diff --git a/libc/sysv/consts/audit.h b/libc/sysv/consts/audit.h new file mode 100644 index 000000000..25051c10f --- /dev/null +++ b/libc/sysv/consts/audit.h @@ -0,0 +1,13 @@ +#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_AUDIT_H_ +#define COSMOPOLITAN_LIBC_SYSV_CONSTS_AUDIT_H_ +#include "libc/elf/def.h" + +#define __AUDIT_ARCH_64BIT 0x80000000 +#define __AUDIT_ARCH_LE 0x40000000 +#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000 +#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000 + +#define AUDIT_ARCH_X86_64 (EM_X86_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE) +#define AUDIT_ARCH_I386 (EM_386 | __AUDIT_ARCH_LE) + +#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_AUDIT_H_ */ diff --git a/libc/sysv/consts/log.h b/libc/sysv/consts/log.h index 838bfd293..989473351 100644 --- a/libc/sysv/consts/log.h +++ b/libc/sysv/consts/log.h @@ -1,93 +1,45 @@ #ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_LOG_H_ #define COSMOPOLITAN_LIBC_SYSV_CONSTS_LOG_H_ -#include "libc/runtime/symbolic.h" -#define LOG_ALERT SYMBOLIC(LOG_ALERT) -#define LOG_AUTH SYMBOLIC(LOG_AUTH) -#define LOG_CONS SYMBOLIC(LOG_CONS) -#define LOG_CRIT SYMBOLIC(LOG_CRIT) -#define LOG_CRON SYMBOLIC(LOG_CRON) -#define LOG_DAEMON SYMBOLIC(LOG_DAEMON) -#define LOG_DEBUG SYMBOLIC(LOG_DEBUG) -#define LOG_EMERG SYMBOLIC(LOG_EMERG) -#define LOG_ERR SYMBOLIC(LOG_ERR) -#define LOG_FACMASK SYMBOLIC(LOG_FACMASK) -#define LOG_INFO SYMBOLIC(LOG_INFO) -#define LOG_KERN SYMBOLIC(LOG_KERN) -#define LOG_LOCAL0 SYMBOLIC(LOG_LOCAL0) -#define LOG_LOCAL1 SYMBOLIC(LOG_LOCAL1) -#define LOG_LOCAL2 SYMBOLIC(LOG_LOCAL2) -#define LOG_LOCAL3 SYMBOLIC(LOG_LOCAL3) -#define LOG_LOCAL4 SYMBOLIC(LOG_LOCAL4) -#define LOG_LOCAL5 SYMBOLIC(LOG_LOCAL5) -#define LOG_LOCAL6 SYMBOLIC(LOG_LOCAL6) -#define LOG_LOCAL7 SYMBOLIC(LOG_LOCAL7) -#define LOG_LPR SYMBOLIC(LOG_LPR) -#define LOG_MAIL SYMBOLIC(LOG_MAIL) -#define LOG_NDELAY SYMBOLIC(LOG_NDELAY) -#define LOG_NEWS SYMBOLIC(LOG_NEWS) -#define LOG_NFACILITIES SYMBOLIC(LOG_NFACILITIES) -#define LOG_NOTICE SYMBOLIC(LOG_NOTICE) -#define LOG_NOWAIT SYMBOLIC(LOG_NOWAIT) -#define LOG_ODELAY SYMBOLIC(LOG_ODELAY) -#define LOG_PERROR SYMBOLIC(LOG_PERROR) -#define LOG_PID SYMBOLIC(LOG_PID) -#define LOG_PRIMASK SYMBOLIC(LOG_PRIMASK) -#define LOG_SELECT SYMBOLIC(LOG_SELECT) -#define LOG_SENSE SYMBOLIC(LOG_SENSE) -#define LOG_SYSLOG SYMBOLIC(LOG_SYSLOG) -#define LOG_USER SYMBOLIC(LOG_USER) -#define LOG_UUCP SYMBOLIC(LOG_UUCP) -#define LOG_WARNING SYMBOLIC(LOG_WARNING) +#define LOG_MASK(pri) (1 << (pri)) +#define LOG_UPTO(pri) ((1 << ((pri) + 1)) - 1) -/* - * arguments to setlogmask. - */ -#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ -#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ +#define LOG_EMERG 0 +#define LOG_KERN 0 +#define LOG_ALERT 1 +#define LOG_PID 1 +#define LOG_CONS 2 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_ODELAY 4 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 +#define LOG_PRIMASK 7 +#define LOG_NDELAY 8 +#define LOG_USER 8 +#define LOG_MAIL 16 +#define LOG_NOWAIT 16 +#define LOG_DAEMON 24 +#define LOG_NFACILITIES 24 +#define LOG_AUTH 32 +#define LOG_PERROR 32 +#define LOG_SYSLOG 40 +#define LOG_LPR 48 +#define LOG_NEWS 56 +#define LOG_UUCP 64 +#define LOG_CRON 72 +#define LOG_SELECT 76 +#define LOG_SENSE 77 +#define LOG_LOCAL0 128 +#define LOG_LOCAL1 136 +#define LOG_LOCAL2 144 +#define LOG_LOCAL3 152 +#define LOG_LOCAL4 160 +#define LOG_LOCAL5 168 +#define LOG_LOCAL6 176 +#define LOG_LOCAL7 184 +#define LOG_FACMASK 0x03f8 - -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern const long LOG_ALERT; -extern const long LOG_AUTH; -extern const long LOG_CONS; -extern const long LOG_CRIT; -extern const long LOG_CRON; -extern const long LOG_DAEMON; -extern const long LOG_DEBUG; -extern const long LOG_EMERG; -extern const long LOG_ERR; -extern const long LOG_FACMASK; -extern const long LOG_INFO; -extern const long LOG_KERN; -extern const long LOG_LOCAL0; -extern const long LOG_LOCAL1; -extern const long LOG_LOCAL2; -extern const long LOG_LOCAL3; -extern const long LOG_LOCAL4; -extern const long LOG_LOCAL5; -extern const long LOG_LOCAL6; -extern const long LOG_LOCAL7; -extern const long LOG_LPR; -extern const long LOG_MAIL; -extern const long LOG_NDELAY; -extern const long LOG_NEWS; -extern const long LOG_NFACILITIES; -extern const long LOG_NOTICE; -extern const long LOG_NOWAIT; -extern const long LOG_ODELAY; -extern const long LOG_PERROR; -extern const long LOG_PID; -extern const long LOG_PRIMASK; -extern const long LOG_SELECT; -extern const long LOG_SENSE; -extern const long LOG_SYSLOG; -extern const long LOG_USER; -extern const long LOG_UUCP; -extern const long LOG_WARNING; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_LOG_H_ */ diff --git a/libc/sysv/consts/pr.h b/libc/sysv/consts/pr.h index 4238bd629..8fd8d471a 100644 --- a/libc/sysv/consts/pr.h +++ b/libc/sysv/consts/pr.h @@ -7,6 +7,9 @@ #define SECCOMP_MODE_STRICT 1 #define SECCOMP_MODE_FILTER 2 +#define PR_SET_NO_NEW_PRIVS 38 +#define PR_GET_NO_NEW_PRIVS 39 + #define PR_SET_NAME 15 #define PR_GET_NAME 0x10 @@ -85,8 +88,6 @@ #define PR_SET_MM 35 #define PR_SET_CHILD_SUBREAPER 36 #define PR_GET_CHILD_SUBREAPER 37 -#define PR_SET_NO_NEW_PRIVS 38 -#define PR_GET_NO_NEW_PRIVS 39 #define PR_GET_TID_ADDRESS 40 #define PR_SET_THP_DISABLE 41 #define PR_GET_THP_DISABLE 42 diff --git a/libc/sysv/consts/seccomp.h b/libc/sysv/consts/seccomp.h deleted file mode 100644 index fb7e495f3..000000000 --- a/libc/sysv/consts/seccomp.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_SECCOMP_H_ -#define COSMOPOLITAN_LIBC_SYSV_CONSTS_SECCOMP_H_ - -#define SECCOMP_SET_MODE_STRICT 0 -#define SECCOMP_SET_MODE_FILTER 1 -#define SECCOMP_GET_ACTION_AVAIL 2 -#define SECCOMP_GET_NOTIF_SIZES 3 -#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0) -#define SECCOMP_FILTER_FLAG_LOG (1UL << 1) -#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2) -#define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3) -#define SECCOMP_FILTER_FLAG_TSYNC_ESRCH (1UL << 4) -#define SECCOMP_RET_KILL_PROCESS 0x80000000U -#define SECCOMP_RET_KILL_THREAD 0x00000000U -#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD -#define SECCOMP_RET_TRAP 0x00030000U -#define SECCOMP_RET_ERRNO 0x00050000U -#define SECCOMP_RET_USER_NOTIF 0x7fc00000U -#define SECCOMP_RET_TRACE 0x7ff00000U -#define SECCOMP_RET_LOG 0x7ffc0000U -#define SECCOMP_RET_ALLOW 0x7fff0000U -#define SECCOMP_RET_ACTION_FULL 0xffff0000U -#define SECCOMP_RET_ACTION 0x7fff0000U -#define SECCOMP_RET_DATA 0x0000ffffU -#define SECCOMP_USER_NOTIF_FLAG_CONTINUE (1UL << 0) -#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0) -#define SECCOMP_ADDFD_FLAG_SEND (1UL << 1) - -#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_SECCOMP_H_ */ diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index b0ee6af7a..5a1da61b2 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -47,7 +47,7 @@ scall sys_lseek 0x0c70c71de20c7008 globl hidden # netbsd+openbsd:evilpad scall __sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad scall sys_msync 0x115100041204101a globl hidden scall sys_mprotect 0x04a04a04a204a00a globl hidden -scall __sys_munmap 0x049049049204900b globl hidden +scall __sys_munmap 0x049049049204090b globl hidden scall sys_sigaction 0x15402e1a0202e00d globl hidden # rt_sigaction on Lunix; it's complicated on NetBSD scall sys_sigprocmask 0x125030154214900e globl hidden # a.k.a. rt_sigprocmask, openbsd:byvalue, a.k.a. pthread_sigmask scall sys_ioctl 0x0360360362036010 globl hidden diff --git a/libc/testlib/showerror.c b/libc/testlib/showerror.c index aceb323fc..6427501d1 100644 --- a/libc/testlib/showerror.c +++ b/libc/testlib/showerror.c @@ -64,8 +64,9 @@ testonly void testlib_showerror_(int line, const char *wantcode, e = errno; if (!IsWindows()) __getpid(); if (!IsWindows()) __getpid(); - __stpcpy(hostname, "unknown"); - gethostname(hostname, sizeof(hostname)); + if (gethostname(hostname, sizeof(hostname))) { + __stpcpy(hostname, "unknown"); + } kprintf("%serror%s:%s%s:%d%s: %s(%s) on %s\n" "\t%s(%s, %s)\n", RED2, UNBOLD, BLUE1, testlib_showerror_file, line, RESET, diff --git a/test/libc/calls/seccomp_test.c b/test/libc/calls/seccomp_test.c index c575a32ed..7ea7d6329 100644 --- a/test/libc/calls/seccomp_test.c +++ b/test/libc/calls/seccomp_test.c @@ -17,19 +17,29 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/struct/bpf.h" +#include "libc/calls/struct/filter.h" #include "libc/calls/struct/iovec.h" +#include "libc/calls/struct/seccomp.h" +#include "libc/errno.h" #include "libc/intrin/kprintf.h" #include "libc/runtime/runtime.h" #include "libc/sock/sock.h" +#include "libc/sysv/consts/audit.h" #include "libc/sysv/consts/o.h" #include "libc/sysv/consts/pr.h" -#include "libc/sysv/consts/seccomp.h" #include "libc/sysv/consts/sig.h" #include "libc/testlib/testlib.h" +#include "tool/net/sandbox.h" bool __is_linux_2_6_23(void) { + int rc; if (!IsLinux()) return false; - return prctl(PR_GET_SECCOMP) != -1; // errno should be EINVAL + asm volatile("syscall" + : "=a"(rc) + : "0"(157), "D"(PR_GET_SECCOMP) + : "rcx", "r11", "memory"); + return rc != -EINVAL; } void SetUp(void) { @@ -70,3 +80,46 @@ TEST(seccompStrictMode, goodProcess_isAuthorized) { EXPECT_EQ(0, WEXITSTATUS(ws)); EXPECT_STREQ("hi", buf); } + +TEST(seccompFilter, isSoMuchBetter) { + char buf[3] = {0}; + int ws, pid, pfds[2]; + ASSERT_SYS(0, 0, pipe(pfds)); + ASSERT_NE(-1, (pid = fork())); + if (!pid) { + struct sock_filter filter[] = { + _SECCOMP_MACHINE(AUDIT_ARCH_X86_64), // + _SECCOMP_LOAD_SYSCALL_NR(), // + _SECCOMP_ALLOW_SYSCALL(0x0013), // readv + _SECCOMP_ALLOW_SYSCALL(0x0014), // writev + _SECCOMP_ALLOW_SYSCALL(0x0000), // read + _SECCOMP_ALLOW_SYSCALL(0x0001), // write + _SECCOMP_ALLOW_SYSCALL(0x0003), // close + _SECCOMP_ALLOW_SYSCALL(0x000f), // rt_sigreturn + _SECCOMP_ALLOW_SYSCALL(0x00e7), // exit_group + _SECCOMP_ALLOW_SYSCALL(0x0009), // mmap + _SECCOMP_ALLOW_SYSCALL(0x0106), // newfstatat + _SECCOMP_ALLOW_SYSCALL(0x0008), // lseek + _SECCOMP_ALLOW_SYSCALL(0x000b), // munmap + _SECCOMP_ALLOW_SYSCALL(0x00e4), // clock_gettime + _SECCOMP_ALLOW_SYSCALL(0x003f), // uname + _SECCOMP_LOG_AND_RETURN_ERRNO(1), // EPERM + }; + struct sock_fprog prog = { + .len = ARRAYLEN(filter), + .filter = filter, + }; + ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)); + ASSERT_EQ(0, prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)); + ASSERT_SYS(0, 3, write(pfds[1], "hi", 3)); + ASSERT_SYS(EPERM, -1, open("/etc/passwd", O_RDONLY)); + _Exit(0); + } + EXPECT_SYS(0, 0, close(pfds[1])); + EXPECT_SYS(0, 3, read(pfds[0], buf, 3)); + EXPECT_SYS(0, 0, close(pfds[0])); + EXPECT_NE(-1, wait(&ws)); + EXPECT_TRUE(WIFEXITED(ws)); + EXPECT_EQ(0, WEXITSTATUS(ws)); + EXPECT_STREQ("hi", buf); +} diff --git a/test/libc/intrin/kprintf_test.c b/test/libc/intrin/kprintf_test.c index 6275426d1..e5c35a217 100644 --- a/test/libc/intrin/kprintf_test.c +++ b/test/libc/intrin/kprintf_test.c @@ -166,7 +166,7 @@ static const struct { {"", "% s"}, // {"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷", "%hs", S(u"𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷")}, // {"☺☻♥♦♣♠!", "%ls", S(L"☺☻♥♦♣♠!")}, // - {"☺☻♥♦♣♠!\n", "%S", S(L"☺☻♥♦♣♠!\n")}, // + {"HELLO", "%^s", S("hello")}, // {"eeeeeee ", "%10s", S("eeeeeee")}, // {"hello", "%.*s", 5, S("hello world")}, // {"þell", "%.*s", 5, S("þello world")}, // @@ -179,7 +179,6 @@ static const struct { {"\"xx\"", "%#s", S("xx")}, // {"u\"☺☺\"", "%#hs", S(u"☺☺")}, // {"L\"☺☺\"", "%#ls", S(L"☺☺")}, // - {"L\"☺☺\"", "%#S", S(L"☺☺")}, // {"\"\\\\\\\"\\177\"", "%#s", S("\\\"\177")}, // {"%%", "%%%%"}, // {"%", "%.%"}, // diff --git a/third_party/lua/lauxlib.c b/third_party/lua/lauxlib.c index c0a595850..03e7a6b52 100644 --- a/third_party/lua/lauxlib.c +++ b/third_party/lua/lauxlib.c @@ -202,16 +202,16 @@ LUALIB_API void luaL_traceback2(lua_State *L, lua_State *L1, const char *msg, int top = lua_gettop(L); int last = lastlevel(L1); int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; - if (msg) lua_pushfstring(L, "%s\n", msg); + if (msg) lua_pushfstring(L, "%s\r\n", msg); luaL_checkstack(L, 10, NULL); lua_pushliteral(L, "stack traceback:"); while (lua_getstack(L1, level++, &ar)) { if (n1-- == 0) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ + lua_pushliteral(L, "\r\n\t..."); /* add a '...' */ level = last - LEVELS2 + 1; /* and skip to last ones */ } else { lua_getinfo(L1, "Slntu", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); + lua_pushfstring(L, "\r\n\t%s:", ar.short_src); if (ar.currentline > 0) lua_pushfstring(L, "%d:", ar.currentline); lua_pushliteral(L, " in "); @@ -228,7 +228,7 @@ LUALIB_API void luaL_traceback2(lua_State *L, lua_State *L1, const char *msg, lua_pop(L, 2); } } - if (ar.istailcall) lua_pushliteral(L, "\n\t(...tail calls...)"); + if (ar.istailcall) lua_pushliteral(L, "\r\n\t(...tail calls...)"); lua_concat(L, lua_gettop(L) - top); } } diff --git a/tool/net/help.txt b/tool/net/help.txt index 47145b422..98679e4bc 100644 --- a/tool/net/help.txt +++ b/tool/net/help.txt @@ -45,6 +45,7 @@ FLAGS -s increase silence [repeatable] -v increase verbosity [repeatable] -V increase ssl verbosity [repeatable] + -S increase bpf seccomp sandboxing [repeatable] -H K:V sets http header globally [repeatable] -D DIR overlay assets in local directory [repeatable] -r /X=/Y redirect X to Y [repeatable] @@ -1231,7 +1232,7 @@ UNIX MODULE Reads from file descriptor. - unix.write(fd:int, data[, offset]) → rc:int, errno:int + unix.write(fd:int, data[, offset]) → rc:int[, errno:int] Writes to file descriptor. @@ -1242,25 +1243,25 @@ UNIX MODULE `flags` should have one of `O_RDONLY`, `O_WRONLY`, or `O_RDWR`. The following values may also be OR'd into `flags`: - - `O_CREAT`: Create file if it doesn't exist. - - `O_TRUNC` Automatic truncate(fd,0) if exists. - - `O_CLOEXEC`: Automatic close() upon execve(). - - `O_EXCL`: Exclusive access. See below. - - `O_APPEND`: Open file for append only. - - `O_DIRECT` (not supported on Apple and OpenBSD) - - `O_DIRECTORY` (hint on UNIX but required on NT) - - `O_TMPFILE` (for Linux and Windows only) - - `O_NOFOLLOW` (zero on Windows) - - `O_DSYNC` (zero on non-Linux/Apple) - - `O_RSYNC` (zero on non-Linux/Apple) - - `O_PATH` (zero on non-Linux) - - `O_VERIFY` (zero on non-FreeBSD) - - `O_SHLOCK` (zero on non-BSD) - - `O_EXLOCK` (zero on non-BSD) - - `O_RANDOM` (zero on non-Windows) - - `O_SEQUENTIAL` (zero on non-Windows) - - `O_COMPRESSED` (zero on non-Windows) - - `O_INDEXED` (zero on non-Windows) + - `O_CREAT`: create file if it doesn't exist + - `O_TRUNC` automatic ftruncate(fd,0) if exists + - `O_CLOEXEC`: automatic close() upon execve() + - `O_EXCL`: exclusive access (see below) + - `O_APPEND`: open file for append only + - `O_DIRECT` it's complicated (not supported on Apple and OpenBSD) + - `O_DIRECTORY` useful for stat'ing (hint on UNIX but required on NT) + - `O_TMPFILE` try to make temp more secure (Linux and Windows only) + - `O_NOFOLLOW` fail if it's a symlink (zero on Windows) + - `O_DSYNC` it's complicated (zero on non-Linux/Apple) + - `O_RSYNC` it's complicated (zero on non-Linux/Apple) + - `O_PATH` it's complicated (zero on non-Linux) + - `O_VERIFY` it's complicated (zero on non-FreeBSD) + - `O_SHLOCK` it's complicated (zero on non-BSD) + - `O_EXLOCK` it's complicated (zero on non-BSD) + - `O_RANDOM` hint random access intent (zero on non-Windows) + - `O_SEQUENTIAL` hint sequential access intent (zero on non-Windows) + - `O_COMPRESSED` ask fs to abstract compression (zero on non-Windows) + - `O_INDEXED` turns on that slow performance (zero on non-Windows) There are three regular combinations for the above flags: @@ -1277,7 +1278,7 @@ UNIX MODULE already. If it does exist then `nil` is returned along with `errno` set to `EEXIST`. - unix.close(fd:int) → rc:int, errno:int + unix.close(fd:int) → rc:int[, errno:int] Closes file descriptor. @@ -1288,12 +1289,12 @@ UNIX MODULE will be closed. Any open connections it owns will be reset. This function never returns. - unix.fork() → childpid|0, errno:int + unix.fork() → childpid|0:int[, errno:int] Creates a new process mitosis style. This returns twice. The parent process gets the nonzero pid. The child gets zero. - unix.commandv(prog) → path, errno:int + unix.commandv(prog:str) → path:str[, errno:int] Performs `$PATH` lookup of executable. We automatically suffix `.com` and `.exe` automatically for all platforms when path @@ -1302,6 +1303,11 @@ UNIX MODULE `prog` contains slashes then it's not path searched either and will be returned if it exists. + unix.realpath(filename:str) → abspath:str[, errno:int] + + Returns absolute path of filename, with `.` and `..` components + removed, and symlinks will be resolved. + unix.execve(prog, argv[, envp]) → errno Exits current process, replacing it with a new instance of the @@ -1315,29 +1321,29 @@ UNIX MODULE The first element in `argv` should be `prog`. This function is normally called after forking. - unix.access(path:str, how) → rc:int, errno:int + unix.access(path:str, how) → rc:int[, errno:int] Checks if effective user of current process has permission to access file. `how` can be `R_OK`, `W_OK`, `X_OK`, or `F_OK` to check for read, write, execute, and existence respectively. - unix.mkdir(path:str, mode) → rc:int, errno:int + unix.mkdir(path:str, mode) → rc:int[, errno:int] Makes directory. `mode` should be octal, e.g. `0755`. - unix.chdir(path:str) → rc:int, errno:int + unix.chdir(path:str) → rc:int[, errno:int] Changes current directory to `path`. - unix.unlink(path:str) → rc:int, errno:int + unix.unlink(path:str) → rc:int[, errno:int] Removes file at `path`. - unix.rmdir(path:str) → rc:int, errno:int + unix.rmdir(path:str) → rc:int[, errno:int] Removes empty directory at `path`. - unix.chroot(path:str) → rc:int, errno:int + unix.chroot(path:str) → rc:int[, errno:int] Changes root directory. Raises `ENOSYS` on Windows. @@ -1352,44 +1358,95 @@ UNIX MODULE writing. `flags` can have `O_CLOEXEC`. On error, `reader` and `writer` will be `nil` and `errno` will be set to non-nil. - unix.rename(oldpath, newpath) → rc:int, errno:int - unix.link(existingpath, newpath) → rc:int, errno:int - unix.symlink(target, linkpath) → rc:int, errno:int - unix.chown(path:str, uid, gid) → rc:int, errno:int - unix.chmod(path:str, mode) → rc:int, errno:int - unix.getcwd(path:str, mode) → rc:int, errno:int + unix.rename(oldpath:str, newpath:str) → rc:int[, errno:int] + + Renames file. + + unix.link(existingpath:str, newpath:str) → rc:int[, errno:int] + + Creates hard link, so your underlying inode has two names. + + unix.symlink(target:str, linkpath:str) → rc:int[, errno:int] + + Creates soft link, or a symbolic link. + + unix.chown(path:str, uid, gid) → rc:int[, errno:int] + + Changes user and gorup on file. + + unix.chmod(path:str, mode) → rc:int[, errno:int] + unix.getcwd(path:str, mode) → rc:int[, errno:int] unix.getpid() → pid unix.getppid() → pid - unix.kill(pid, sig) → rc:int, errno:int - unix.raise(sig) → rc:int, errno:int + unix.kill(pid, sig) → rc:int[, errno:int] + unix.raise(sig) → rc:int[, errno:int] unix.wait(pid[, options]) → pid, wstatus, nil, errno:int - unix.fcntl(fd:int, cmd[, arg]) → rc:int, errno:int + unix.fcntl(fd:int, cmd[, arg]) → rc:int[, errno:int] unix.getsid(pid) → sid, errno:int unix.getpgrp() → pgid, errno:int unix.getpgid(pid) → pgid, errno:int unix.setpgid(pid, pgid) → pgid, errno:int unix.setsid() → sid, errno:int unix.getuid() → uid, errno:int + unix.setuid(uid:int) → rc:int[, errno:int] unix.getgid() → gid, errno:int - unix.umask(mask) → rc:int, errno:int - unix.gettime([clock]) → seconds, nanos, errno:int - unix.nanosleep(seconds, nanos) → remseconds, remnanos, errno:int - unix.sync(fd:int) - unix.fsync(fd:int) → rc:int, errno:int - unix.fdatasync(fd:int) → rc:int, errno:int + unix.setgid(gid:int) → rc:int[, errno:int] + unix.umask(mask) → rc:int[, errno:int] - unix.seek(fd:int, offset, whence) → newpos, errno:int - where whence ∈ {SEEK_SET, SEEK_CUR, SEEK_END} - whence defaults to SEEK_SET - unix.truncate(path:str, length) → rc:int, errno:int - unix.truncate(fd:int, length) → rc:int, errno:int + unix.syslog(priority:str, msg:str) + + Generates a log message which will be distributed by syslogd. + + `priority` is a bitmask containing the facility value and the + level value. If no facility value is ORed into priority, then + the default value set by openlog() is used. it set to NULL, the + program name is used. Level is one of `LOG_EMERG`, `LOG_ALERT`, + `LOG_CRIT`, `LOG_ERR`, `LOG_WARNING`, `LOG_NOTICE`, `LOG_INFO`, + `LOG_DEBUG`. + + This function currently works on Linux, Windows, and NetBSD. On + WIN32 it uses the ReportEvent() facility. + + unix.clock_gettime([clock]) → seconds, nanos, errno:int + + Returns nanosecond precision timestamp from the system. + + `clock` should be `CLOCK_REALTIME`, `CLOCK_MONOTONIC`, or + `CLOCK_MONOTONIC_RAW` since they work across platforms. + You may also try your luck with `CLOCK_REALTIME_COARSE`, + `CLOCK_MONOTONIC_COARSE`, `CLOCK_PROCESS_CPUTIME_ID`, + `CLOCK_TAI`, `CLOCK_PROF`, `CLOCK_BOOTTIME`, + `CLOCK_REALTIME_ALARM`, and `CLOCK_BOOTTIME_ALARM`, + + unix.nanosleep(seconds, nanos) → remseconds, remnanos, errno:int + + Sleeps with nanosecond precision. + + unix.sync(fd:int) + unix.fsync(fd:int) → rc:int[, errno:int] + unix.fdatasync(fd:int) → rc:int[, errno:int] + + These functions are used to make programs slower by asking the + operating system to flush data to the physical medium. + + unix.seek(fd:int, offset:int, whence:int) → newpos:int[, errno:int] + + Seeks to file position. + + `whence` can be one of `SEEK_SET`, `SEEK_CUR`, or `SEEK_END`. + + unix.truncate(path:str, length) → rc:int[, errno:int] + unix.ftruncate(fd:int, length) → rc:int[, errno:int] + + Reduces or extends underlying physical medium of file. + If file was originally larger, content >length is lost. unix.socket([family[, type[, protocol]]]) → fd:int[, errno:int] `SOCK_CLOEXEC` may be or'd into type - `family` defaults to `AF_INET` - `type` defaults to `SOCK_STREAM` - `protocol` defaults to `IPPROTO_TCP` + `family` defaults to `AF_INET` but can be `AF_UNIX` + `type` defaults to `SOCK_STREAM` but can be `SOCK_DGRAM` + `protocol` defaults to `IPPROTO_TCP` but can be `IPPROTO_UDP` unix.socketpair([family[, type[, protocol]]]) → fd1, fd2, errno:int @@ -1398,11 +1455,11 @@ UNIX MODULE `type` defaults to `SOCK_STREAM` `protocol` defaults to `IPPROTO_TCP` - unix.bind(fd:int, ip, port) → rc:int, errno:int + unix.bind(fd:int, ip, port) → rc:int[, errno:int] - unix.connect(fd:int, ip, port) → rc:int, errno:int + unix.connect(fd:int, ip, port) → rc:int[, errno:int] - unix.listen(fd:int[, backlog]) → rc:int, errno:int + unix.listen(fd:int[, backlog]) → rc:int[, errno:int] unix.getsockname(fd:int) → ip, port, errno:int @@ -1430,7 +1487,7 @@ UNIX MODULE addresses. The `flags` parameter can have `MSG_OOB`, `MSG_DONTROUTE`, or `MSG_NOSIGNAL`. - unix.shutdown(fd:int, how:int) → rc:int, errno:int + unix.shutdown(fd:int, how:int) → rc:int[, errno:int] Partially closes socket. `how` can be `SHUT_RD`, `SHUT_WR`, or `SHUT_RDWR`. @@ -1602,21 +1659,6 @@ UNIX MODULE - `ENOSYS`: System call not available on this platform. On Windows this is raised by chroot(), setuid(), setgid(). - - `EPERM`: Operation not permitted. Raised by accept(), adjtimex(), - arch_prctl(), bdflush(), capget(), chmod(), chown(), chroot(), - clock_getres(), copy_file_range(), execve(), fcntl(), - get_robust_list(), getdomainname(), getgroups(), gethostname(), - getpriority(), getrlimit(), getsid(), gettimeofday(), kill(), - link(), mbind(), membarrier(), migrate_pages(), mkdir(), mknod(), - mlock(), mmap(), msgctl(), nice(), open(), prctl(), ptrace(), - reboot(), rename(), rmdir(), sched_setaffinity(), - sched_setattr(), sched_setparam(), sched_setscheduler(), - seteuid(), setfsgid(), setfsuid(), setgid(), setpgid(), - setresuid(), setreuid(), setsid(), setuid(), setup(), shmget(), - sigaltstack(), stime(), swapon(), symlink(), syslog(), - timer_create(), timerfd_create(), tkill(), truncate(), u - unlink(), utime(), utimensat(), vhangup(), vm86(), write(). - - `ENOENT`: no such file or directory. Raised by access(), alloc_hugepages(), bind(), chdir(), chmod(), chown(), chroot(), clock_getres(), execve(), opendir(), inotify_add_watch(), kcmp(), @@ -1692,6 +1734,28 @@ UNIX MODULE rmdir(), semget(), send(), setpgid(), shmget(), socket(), stat(), symlink(), truncate(), unlink(), uselib(), utime(), utimensat(), + - `EPERM`: Operation not permitted. Raised by accept(), chmod(), + chown(), chroot(), copy_file_range(), execve(), fallocate(), + fanotify_init(), fcntl(), futex(), get_robust_list(), + getdomainname(), getgroups(), gethostname(), getpriority(), + getrlimit(), getsid(), gettimeofday(), idle(), init_module(), + io_submit(), ioctl_console(), ioctl_ficlonerange(), + ioctl_fideduperange(), ioctl_ns(), ioctl_tty(), ioperm(), iopl(), + ioprio_set(), kcmp(), kexec_load(), keyctl(), kill(), link(), + lookup_dcookie(), madvise(), mbind(), membarrier(), + migrate_pages(), mkdir(), mknod(), mlock(), mmap(), mount(), + move_pages(), msgctl(), nice(), open(), open_by_handle_at(), + pciconfig_read(), perf_event_open(), pidfd_getfd(), + pidfd_send_signal(), pivot_root(), prctl(), process_vm_readv(), + ptrace(), quotactl(), reboot(), rename(), request_key(), rmdir(), + rt_sigqueueinfo(), sched_setaffinity(), sched_setattr(), + sched_setparam(), sched_setscheduler(), semctl(), seteuid(), + setfsgid(), setfsuid(), setgid(), setns(), setpgid(), + setresuid(), setreuid(), setsid(), setuid(), setup(), setxattr(), + shmctl(), shmget(), sigaltstack(), spu_create(), stime(), + swapon(), symlink(), syslog(), truncate(), unlink(), utime(), + utimensat(), write() + - `ENOTBLK`: Block device required. Raised by umount(). - `EBUSY`: Device or resource busy. Raised by bdflush(), dup(), diff --git a/tool/net/lunix.c b/tool/net/lunix.c index f11628947..b6e0cbf62 100644 --- a/tool/net/lunix.c +++ b/tool/net/lunix.c @@ -37,6 +37,7 @@ #include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/sock/sock.h" +#include "libc/sock/syslog.h" #include "libc/str/str.h" #include "libc/sysv/consts/af.h" #include "libc/sysv/consts/at.h" @@ -46,6 +47,7 @@ #include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/itimer.h" +#include "libc/sysv/consts/log.h" #include "libc/sysv/consts/msg.h" #include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/o.h" @@ -104,6 +106,16 @@ static int ReturnRc(lua_State *L, int64_t rc, int olderr) { return 2; } +static int ReturnErrno(lua_State *L, int nils, int olderr) { + int i; + for (i = 0; i < nils; ++i) { + lua_pushnil(L); + } + lua_pushinteger(L, errno); + errno = olderr; + return nils + 1; +} + static char **ConvertLuaArrayToStringList(lua_State *L, int i) { int j, n; char **p; @@ -133,13 +145,13 @@ static void FreeStringList(char **p) { //////////////////////////////////////////////////////////////////////////////// // System Calls -// unix.exit([exitcode]) → ⊥ +// unix.exit([exitcode:int]) → ⊥ static wontreturn int LuaUnixExit(lua_State *L) { _Exit(luaL_optinteger(L, 1, 0)); } -// unix.access(path, mode) → rc[, errno] -// mode can be: R_OK, W_OK, X_OK, F_OK +// unix.access(path:str, how:int) → rc:int[, errno:int] +// how can be: R_OK, W_OK, X_OK, F_OK static int LuaUnixAccess(lua_State *L) { const char *file; int rc, mode, olderr; @@ -150,19 +162,31 @@ static int LuaUnixAccess(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.mkdir(path, mode) → rc[, errno] +// unix.mkdir(path:str[, mode:int]) → rc:int[, errno:int] // mode should be octal static int LuaUnixMkdir(lua_State *L) { const char *file; int rc, mode, olderr; olderr = errno; file = luaL_checklstring(L, 1, 0); - mode = luaL_checkinteger(L, 2); + mode = luaL_optinteger(L, 2, 0755); rc = mkdir(file, mode); return ReturnRc(L, rc, olderr); } -// unix.chdir(path) → rc[, errno] +// unix.makedirs(path:str[, mode:int]) → rc:int[, errno:int] +// mode should be octal +static int LuaUnixMakedirs(lua_State *L) { + const char *file; + int rc, mode, olderr; + olderr = errno; + file = luaL_checklstring(L, 1, 0); + mode = luaL_optinteger(L, 2, 0755); + rc = makedirs(file, mode); + return ReturnRc(L, rc, olderr); +} + +// unix.chdir(path:str) → rc:int[, errno:int] static int LuaUnixChdir(lua_State *L) { int rc, olderr; const char *file; @@ -172,7 +196,7 @@ static int LuaUnixChdir(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.unlink(path) → rc[, errno] +// unix.unlink(path:str) → rc:int[, errno:int] static int LuaUnixUnlink(lua_State *L) { int rc, olderr; const char *file; @@ -182,7 +206,7 @@ static int LuaUnixUnlink(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.rmdir(path) → rc[, errno] +// unix.rmdir(path:str) → rc:int[, errno:int] static int LuaUnixRmdir(lua_State *L) { const char *file; int rc, olderr; @@ -192,7 +216,7 @@ static int LuaUnixRmdir(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.rename(oldpath, newpath) → rc[, errno] +// unix.rename(oldpath:str, newpath:str) → rc:int[, errno:int] static int LuaUnixRename(lua_State *L) { const char *oldpath, *newpath; int rc, olderr; @@ -203,7 +227,7 @@ static int LuaUnixRename(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.link(existingpath, newpath) → rc[, errno] +// unix.link(existingpath:str, newpath:str) → rc:int[, errno:int] static int LuaUnixLink(lua_State *L) { const char *existingpath, *newpath; int rc, olderr; @@ -214,7 +238,7 @@ static int LuaUnixLink(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.symlink(target, linkpath) → rc[, errno] +// unix.symlink(target:str, linkpath:str) → rc:int[, errno:int] static int LuaUnixSymlink(lua_State *L) { const char *target, *linkpath; int rc, olderr; @@ -225,7 +249,7 @@ static int LuaUnixSymlink(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.chown(path, uid, gid) → rc[, errno] +// unix.chown(path:str, uid:int, gid:int) → rc:int[, errno:int] static int LuaUnixChown(lua_State *L) { const char *file; int rc, uid, gid, olderr; @@ -237,7 +261,7 @@ static int LuaUnixChown(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.chmod(path, mode) → rc[, errno] +// unix.chmod(path:str, mode:int) → rc:int[, errno:int] static int LuaUnixChmod(lua_State *L) { const char *file; int rc, mode, olderr; @@ -248,7 +272,7 @@ static int LuaUnixChmod(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.getcwd(path, mode) → rc[, errno] +// unix.getcwd(path:str, mode:int) → rc:int[, errno:int] static int LuaUnixGetcwd(lua_State *L) { char *path; path = getcwd(0, 0); @@ -258,7 +282,7 @@ static int LuaUnixGetcwd(lua_State *L) { return 1; } -// unix.fork() → childpid|0, errno +// unix.fork() → childpid|0:int[, errno:int] static int LuaUnixFork(lua_State *L) { int rc, olderr; olderr = errno; @@ -298,7 +322,7 @@ static int LuaUnixExecve(lua_State *L) { return 1; } -// unix.commandv(prog) → path[, errno] +// unix.commandv(prog:str) → path:str[, errno:int] static int LuaUnixCommandv(lua_State *L) { const char *prog; int rc, olderr, pushed; @@ -319,7 +343,29 @@ static int LuaUnixCommandv(lua_State *L) { return pushed; } -// unix.chroot(path) → rc[, errno] +// unix.realpath(path:str) → path:str[, errno:int] +static int LuaUnixRealpath(lua_State *L) { + char *resolved; + int rc, olderr; + const char *path; + olderr = errno; + path = luaL_checkstring(L, 1); + if ((resolved = realpath(path, 0))) { + lua_pushstring(L, resolved); + free(resolved); + return 1; + } else { + return ReturnErrno(L, 1, olderr); + } +} + +// unix.syslog(priority:str, msg:str) +static int LuaUnixSyslog(lua_State *L) { + syslog(luaL_checkinteger(L, 1), "%s", luaL_checkstring(L, 2)); + return 0; +} + +// unix.chroot(path:str) → rc:int[, errno:int] static int LuaUnixChroot(lua_State *L) { int rc, olderr; const char *path; @@ -351,27 +397,23 @@ static int LuaUnixGetrlimit(lua_State *L) { lua_pushinteger(L, rlim.rlim_max); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } -// unix.getpid() → pid +// unix.getpid() → pid:int static int LuaUnixGetpid(lua_State *L) { lua_pushinteger(L, getpid()); return 1; } -// unix.getppid() → pid +// unix.getppid() → pid:int static int LuaUnixGetppid(lua_State *L) { lua_pushinteger(L, getppid()); return 1; } -// unix.kill(pid, sig) → rc[, errno] +// unix.kill(pid, sig) → rc:int[, errno:int] static int LuaUnixKill(lua_State *L) { int rc, pid, sig, olderr; olderr = errno; @@ -381,7 +423,7 @@ static int LuaUnixKill(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.raise(sig) → rc[, errno] +// unix.raise(sig) → rc:int[, errno:int] static int LuaUnixRaise(lua_State *L) { int rc, sig, olderr; olderr = errno; @@ -402,16 +444,11 @@ static int LuaUnixWait(lua_State *L) { lua_pushinteger(L, wstatus); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); // for future use - lua_pushinteger(L, errno); - errno = olderr; - return 4; + return ReturnErrno(L, 3, olderr); } } -// unix.fcntl(fd, cmd[, arg]) → rc[, errno] +// unix.fcntl(fd, cmd[, arg]) → rc:int[, errno:int] static int LuaUnixFcntl(lua_State *L) { intptr_t arg; int rc, fd, cmd, olderr; @@ -450,15 +487,11 @@ static int LuaUnixPipe(lua_State *L) { lua_pushinteger(L, pipefd[1]); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } -// unix.getsid(pid) → sid, errno +// unix.getsid(pid) → sid:int[, errno:int] static int LuaUnixGetsid(lua_State *L) { int rc, pid, olderr; olderr = errno; @@ -467,7 +500,7 @@ static int LuaUnixGetsid(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.getpgrp() → pgid, errno +// unix.getpgrp() → pgid:int[, errno:int] static int LuaUnixGetpgrp(lua_State *L) { int rc, olderr; olderr = errno; @@ -475,7 +508,7 @@ static int LuaUnixGetpgrp(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.getpgid(pid) → pgid, errno +// unix.getpgid(pid:int) → pgid:int[, errno:int] static int LuaUnixGetpgid(lua_State *L) { int rc, pid, olderr; olderr = errno; @@ -484,7 +517,7 @@ static int LuaUnixGetpgid(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.umask(mask) → rc[, errno] +// unix.umask(mask:int) → rc:int[, errno:int] static int LuaUnixUmask(lua_State *L) { int rc, mask, olderr; olderr = errno; @@ -493,7 +526,7 @@ static int LuaUnixUmask(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.setpgid(pid, pgid) → pgid, errno +// unix.setpgid(pid:int, pgid:int) → pgid:int[, errno:int] static int LuaUnixSetpgid(lua_State *L) { int rc, pid, pgid, olderr; olderr = errno; @@ -503,7 +536,7 @@ static int LuaUnixSetpgid(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.setsid() → sid, errno +// unix.setsid() → sid:int[, errno:int] static int LuaUnixSetsid(lua_State *L) { int rc, olderr; olderr = errno; @@ -511,7 +544,7 @@ static int LuaUnixSetsid(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.getuid() → uid, errno +// unix.getuid() → uid[, errno] static int LuaUnixGetuid(lua_State *L) { int rc, olderr; olderr = errno; @@ -519,7 +552,13 @@ static int LuaUnixGetuid(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.getgid() → gid, errno +// unix.setuid(uid:int) → rc:int[, errno:int] +static int LuaUnixSetuid(lua_State *L) { + int olderr = errno; + return ReturnRc(L, setuid(luaL_checkinteger(L, 1)), olderr); +} + +// unix.getgid() → gid:int[, errno:int] static int LuaUnixGetgid(lua_State *L) { int rc, olderr; olderr = errno; @@ -527,7 +566,13 @@ static int LuaUnixGetgid(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.gettime([clock]) → seconds, nanos, errno +// unix.setgid(gid:int) → rc:int[, errno:int] +static int LuaUnixSetgid(lua_State *L) { + int olderr = errno; + return ReturnRc(L, setgid(luaL_checkinteger(L, 1)), olderr); +} + +// unix.clock_gettime([clock]) → seconds, nanos, errno static int LuaUnixGettime(lua_State *L) { struct timespec ts; int rc, clock, olderr; @@ -539,11 +584,7 @@ static int LuaUnixGettime(lua_State *L) { lua_pushinteger(L, ts.tv_nsec); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } @@ -560,21 +601,17 @@ static int LuaUnixNanosleep(lua_State *L) { lua_pushinteger(L, rem.tv_nsec); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } -// unix.sync(fd) +// unix.sync(fd:int) static int LuaUnixSync(lua_State *L) { sync(); return 0; } -// unix.fsync(fd) → rc[, errno] +// unix.fsync(fd:int) → rc:int[, errno:int] static int LuaUnixFsync(lua_State *L) { int rc, fd, olderr; olderr = errno; @@ -583,7 +620,7 @@ static int LuaUnixFsync(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.fdatasync(fd) → rc[, errno] +// unix.fdatasync(fd:int) → rc:int[, errno:int] static int LuaUnixFdatasync(lua_State *L) { int rc, fd, olderr; olderr = errno; @@ -604,7 +641,7 @@ static int LuaUnixOpen(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.close(fd) → rc[, errno] +// unix.close(fd:int) → rc:int[, errno:int] static int LuaUnixClose(lua_State *L) { int rc, fd, olderr; olderr = errno; @@ -627,8 +664,8 @@ static int LuaUnixSeek(lua_State *L) { return ReturnRc(L, newpos, olderr); } -// unix.truncate(path, length) → rc[, errno] -// unix.truncate(fd, length) → rc[, errno] +// unix.truncate(path, length) → rc:int[, errno:int] +// unix.truncate(fd, length) → rc:int[, errno:int] static int LuaUnixTruncate(lua_State *L) { int64_t length; const char *path; @@ -649,7 +686,7 @@ static int LuaUnixTruncate(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.read(fd[, bufsiz, offset]) → data, errno +// unix.read(fd:int[, bufsiz:str, offset:int]) → data:str, errno:int static int LuaUnixRead(lua_State *L) { char *buf; size_t got; @@ -680,7 +717,7 @@ static int LuaUnixRead(lua_State *L) { return pushed; } -// unix.write(fd, data[, offset]) → rc[, errno] +// unix.write(fd:int, data:str[, offset:int]) → rc:int[, errno:int] static int LuaUnixWrite(lua_State *L) { size_t size; int fd, olderr; @@ -699,8 +736,8 @@ static int LuaUnixWrite(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.stat(path) → UnixStat*[, errno] -// unix.stat(fd) → UnixStat*[, errno] +// unix.stat(path:str) → UnixStat*[, errno] +// unix.stat(fd:int) → UnixStat*[, errno] static int LuaUnixStat(lua_State *L) { const char *path; int rc, fd, olderr; @@ -731,8 +768,8 @@ static int LuaUnixStat(lua_State *L) { return 1; } -// unix.opendir(path) → UnixDir*[, errno] -// unix.opendir(fd) → UnixDir*[, errno] +// unix.opendir(path:str) → UnixDir*[, errno] +// unix.opendir(fd:int) → UnixDir*[, errno] static int LuaUnixOpendir(lua_State *L) { DIR *rc; int fd, olderr; @@ -797,15 +834,11 @@ static int LuaUnixSocketpair(lua_State *L) { lua_pushinteger(L, sv[1]); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } -// unix.bind(fd, ip, port) → rc[, errno] +// unix.bind(fd, ip, port) → rc:int[, errno:int] // SOCK_CLOEXEC may be or'd into type // family defaults to AF_INET // type defaults to SOCK_STREAM @@ -822,7 +855,7 @@ static int LuaUnixBind(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.connect(fd, ip, port) → rc[, errno] +// unix.connect(fd, ip, port) → rc:int[, errno:int] // SOCK_CLOEXEC may be or'd into type // family defaults to AF_INET // type defaults to SOCK_STREAM @@ -839,7 +872,7 @@ static int LuaUnixConnect(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.listen(fd[, backlog]) → rc[, errno] +// unix.listen(fd[, backlog]) → rc:int[, errno:int] static int LuaUnixListen(lua_State *L) { int rc, fd, olderr, backlog; olderr = errno; @@ -863,11 +896,7 @@ static int LuaUnixGetsockname(lua_State *L) { lua_pushinteger(L, ntohs(sa.sin_port)); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } @@ -885,11 +914,7 @@ static int LuaUnixGetpeername(lua_State *L) { lua_pushinteger(L, ntohs(sa.sin_port)); return 2; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 3; + return ReturnErrno(L, 2, olderr); } } @@ -909,12 +934,7 @@ static int LuaUnixAccept(lua_State *L) { lua_pushinteger(L, ntohs(sa.sin_port)); return 3; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 4; + return ReturnErrno(L, 3, olderr); } } @@ -1016,7 +1036,7 @@ static int LuaUnixSendto(lua_State *L) { return ReturnRc(L, rc, olderr); } -// unix.shutdown(fd, how) → rc[, errno] +// unix.shutdown(fd, how) → rc:int[, errno:int] // how can be SHUT_RD, SHUT_WR, or SHUT_RDWR static int LuaUnixShutdown(lua_State *L) { int rc, fd, how, olderr; @@ -1149,12 +1169,7 @@ static int LuaUnixSigaction(lua_State *L) { lua_pushinteger(L, oldsa.sa_mask.__bits[0]); return 3; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 4; + return ReturnErrno(L, 3, olderr); } } @@ -1206,13 +1221,7 @@ static int LuaUnixSetitimer(lua_State *L) { lua_pushinteger(L, oldit.it_value.tv_usec); return 4; } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 5; + return ReturnErrno(L, 4, olderr); } } @@ -1362,7 +1371,7 @@ static int FreeUnixDir(struct UnixDir *dir) { return closedir(dir->dir); } -// UnixDir:close() → rc[, errno] +// UnixDir:close() → rc:int[, errno:int] // may be called multiple times // called by the garbage collector too static int LuaUnixDirClose(lua_State *L) { @@ -1393,13 +1402,7 @@ static int LuaUnixDirRead(lua_State *L) { } else if (!ent && !errno) { return 0; // end of listing } else { - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 5; + return ReturnErrno(L, 4, olderr); } } @@ -1414,10 +1417,7 @@ static int LuaUnixDirFd(lua_State *L) { lua_pushinteger(L, fd); return 1; } else { - lua_pushnil(L); - lua_pushinteger(L, errno); - errno = olderr; - return 2; + return ReturnErrno(L, 1, olderr); } } @@ -1478,12 +1478,15 @@ static const luaL_Reg kLuaUnix[] = { {"fork", LuaUnixFork}, // make child process via mitosis {"execve", LuaUnixExecve}, // replace process with program {"commandv", LuaUnixCommandv}, // resolve program on $PATH + {"realpath", LuaUnixRealpath}, // abspath without dots/symlinks + {"syslog", LuaUnixSyslog}, // logs to system log {"kill", LuaUnixKill}, // signal child process {"raise", LuaUnixRaise}, // signal this process {"wait", LuaUnixWait}, // wait for child to change status {"pipe", LuaUnixPipe}, // create two anon fifo fds {"dup", LuaUnixDup}, // copy fd to lowest empty slot {"mkdir", LuaUnixMkdir}, // make directory + {"makedirs", LuaUnixMakedirs}, // make directory and parents too {"rmdir", LuaUnixRmdir}, // remove empty directory {"opendir", LuaUnixOpendir}, // read directory entry list {"rename", LuaUnixRename}, // rename file or directory @@ -1494,8 +1497,9 @@ static const luaL_Reg kLuaUnix[] = { {"fsync", LuaUnixFsync}, // flush open file {"fdatasync", LuaUnixFdatasync}, // flush open file w/o metadata {"truncate", LuaUnixTruncate}, // shrink or extend file medium - {"umask", LuaUnixChroot}, // change root directory - {"chroot", LuaUnixGetppid}, // get parent process id + {"ftruncate", LuaUnixTruncate}, // shrink or extend file medium + {"umask", LuaUnixUmask}, // change root directory + {"chroot", LuaUnixChroot}, // get parent process id {"setrlimit", LuaUnixSetrlimit}, // prevent cpu memory bombs {"getrlimit", LuaUnixGetrlimit}, // query resource limits {"getppid", LuaUnixGetppid}, // get parent process id @@ -1506,8 +1510,10 @@ static const luaL_Reg kLuaUnix[] = { {"setsid", LuaUnixSetsid}, // create a new session id {"getpid", LuaUnixGetpid}, // get id of this process {"getuid", LuaUnixGetuid}, // get real user id of process + {"setuid", LuaUnixSetuid}, // set real user id of process {"getgid", LuaUnixGetgid}, // get real group id of process - {"gettime", LuaUnixGettime}, // get timestamp w/ nano precision + {"setgid", LuaUnixSetgid}, // set real group id of process + {"clock_gettime", LuaUnixGettime}, // get timestamp w/ nano precision {"nanosleep", LuaUnixNanosleep}, // sleep w/ nano precision {"socket", LuaUnixSocket}, // create network communication fd {"socketpair", LuaUnixSocketpair}, // create bidirectional pipe @@ -1685,5 +1691,15 @@ int LuaUnix(lua_State *L) { LuaSetIntField(L, "ITIMER_PROF", ITIMER_PROF); LuaSetIntField(L, "ITIMER_VIRTUAL", ITIMER_VIRTUAL); + // syslog() stuff + LuaSetIntField(L, "LOG_EMERG", LOG_EMERG); + LuaSetIntField(L, "LOG_ALERT", LOG_ALERT); + LuaSetIntField(L, "LOG_CRIT", LOG_CRIT); + LuaSetIntField(L, "LOG_ERR", LOG_ERR); + LuaSetIntField(L, "LOG_WARNING", LOG_WARNING); + LuaSetIntField(L, "LOG_NOTICE", LOG_NOTICE); + LuaSetIntField(L, "LOG_INFO", LOG_INFO); + LuaSetIntField(L, "LOG_DEBUG", LOG_DEBUG); + return 1; } diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 8c2b5b50d..2f982962d 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -22,11 +22,11 @@ #include "libc/bits/popcnt.h" #include "libc/bits/safemacros.internal.h" #include "libc/calls/calls.h" -#include "libc/calls/issandboxed.h" #include "libc/calls/math.h" #include "libc/calls/sigbits.h" #include "libc/calls/strace.internal.h" #include "libc/calls/struct/dirent.h" +#include "libc/calls/struct/filter.h" #include "libc/calls/struct/flock.h" #include "libc/calls/struct/rusage.h" #include "libc/calls/struct/sigaction.h" @@ -71,6 +71,7 @@ #include "libc/str/str.h" #include "libc/str/undeflate.h" #include "libc/sysv/consts/af.h" +#include "libc/sysv/consts/audit.h" #include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/dt.h" #include "libc/sysv/consts/ex.h" @@ -90,7 +91,6 @@ #include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/rusage.h" #include "libc/sysv/consts/s.h" -#include "libc/sysv/consts/seccomp.h" #include "libc/sysv/consts/shut.h" #include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/so.h" @@ -144,6 +144,7 @@ #include "tool/build/lib/case.h" #include "tool/build/lib/psk.h" #include "tool/net/luacheck.h" +#include "tool/net/sandbox.h" STATIC_STACK_SIZE(0x40000); STATIC_YOINK("zip_uri_support"); @@ -367,7 +368,6 @@ static bool terminated; static bool uniprocess; static bool invalidated; static bool logmessages; -static bool issandboxed; static bool isinitialized; static bool checkedmethod; static bool sslinitialized; @@ -393,6 +393,7 @@ static int zfd; static int frags; static int gmtoff; static int client; +static int sandboxed; static int changeuid; static int changegid; static int isyielding; @@ -1168,10 +1169,10 @@ static void ReportWorkerExit(int pid, int ws) { static void ReportWorkerResources(int pid, struct rusage *ru) { char *s, *b = 0; if (logrusage || LOGGABLE(kLogDebug)) { - AppendResourceReport(&b, ru, "\n"); + AppendResourceReport(&b, ru, "\r\n"); if (b) { if ((s = IndentLines(b, appendz(b).i - 1, 0, 1))) { - LOGF(kLogDebug, "(stat) resource report for pid %d\n%s", pid, s); + LOGF(kLogDebug, "(stat) resource report for pid %d\r\n%s", pid, s); free(s); } free(b); @@ -2217,15 +2218,44 @@ static void *LoadAsset(struct Asset *a, size_t *out_size) { } } -static wontreturn void PrintUsage(FILE *f, int rc) { +static const char *GetPagerPath(char path[PATH_MAX]) { + const char *s; + if ((s = commandv("less", path))) return s; + if ((s = commandv("more", path))) return s; + return 0; +} + +static wontreturn void PrintUsage(int fd, int rc) { size_t n; + int pip[2]; const char *p; struct Asset *a; - if ((a = GetAssetZip("/help.txt", 9)) && (p = LoadAsset(a, &n))) { - fwrite(p, 1, n, f); - free(p); + char *args[2] = {0}; + char pathbuf[PATH_MAX]; + if (!(a = GetAssetZip("/help.txt", 9)) || !(p = LoadAsset(a, &n))) { + fprintf(stderr, "error: /help.txt is not a zip asset\n"); + exit(1); + } + if (isatty(0) && isatty(1) && (args[0] = GetPagerPath(pathbuf))) { + sigaction(SIGPIPE, &(struct sigaction){.sa_handler = SIG_IGN}, 0); + close(0); + pipe(pip); + if (!fork()) { + close(pip[1]); + execv(args[0], args); + _Exit(127); + } + close(0); + WritevAll(pip[1], &(struct iovec){p, n}, 1); + close(pip[1]); + wait(0); + free(p); + exit(0); + } else { + WritevAll(fd, &(struct iovec){p, n}, 1); + free(p); + exit(rc); } - exit(rc); } static void AppendLogo(void) { @@ -3623,7 +3653,7 @@ static void LogMessage(const char *d, const char *s, size_t n) { while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n; if ((s2 = DecodeLatin1(s, n, &n2))) { if ((s3 = IndentLines(s2, n2, &n3, 1))) { - INFOF("(stat) %s %,ld byte message\n%.*s", d, n, n3, s3); + INFOF("(stat) %s %,ld byte message\r\n%.*s", d, n, n3, s3); free(s3); } free(s2); @@ -3638,7 +3668,7 @@ static void LogBody(const char *d, const char *s, size_t n) { while (n && (s[n - 1] == '\r' || s[n - 1] == '\n')) --n; if ((s2 = VisualizeControlCodes(s, n, &n2))) { if ((s3 = IndentLines(s2, n2, &n3, 1))) { - INFOF("(stat) %s %,ld byte payload\n%.*s", d, n, n3, s3); + INFOF("(stat) %s %,ld byte payload\r\n%.*s", d, n, n3, s3); free(s3); } free(s2); @@ -3772,8 +3802,8 @@ static int LuaFetch(lua_State *L) { */ DEBUGF("(ftch) client resolving %s", host); if ((rc = getaddrinfo(host, port, &hints, &addr)) != EAI_SUCCESS) { - luaL_error(L, "getaddrinfo(%s:%s) error: EAI_%s", host, port, - gai_strerror(rc)); + luaL_error(L, "getaddrinfo(%s:%s) error: EAI_%s %s", host, port, + gai_strerror(rc), strerror(errno)); unreachable; } @@ -5516,11 +5546,6 @@ static const luaL_Reg kLuaFuncs[] = { {"Underlong", LuaUnderlong}, // {"VisualizeControlCodes", LuaVisualizeControlCodes}, // {"Write", LuaWrite}, // - {"bsf", LuaBsf}, // - {"bsr", LuaBsr}, // - {"crc32", LuaCrc32}, // - {"crc32c", LuaCrc32c}, // - {"popcnt", LuaPopcnt}, // #ifndef UNSECURE {"Fetch", LuaFetch}, // {"EvadeDragnetSurveillance", LuaEvadeDragnetSurveillance}, // @@ -6581,13 +6606,90 @@ static void CloseServerFds(void) { } static int ExitWorker(void) { - if (IsModeDbg() && !issandboxed) { + if (IsModeDbg() && !sandboxed) { isexitingworker = true; return eintr(); } _Exit(0); } +static const struct sock_filter kSandboxOnline[] = { + _SECCOMP_MACHINE(AUDIT_ARCH_X86_64), // + _SECCOMP_LOAD_SYSCALL_NR(), // + _SECCOMP_ALLOW_SYSCALL(0x0013), // readv + _SECCOMP_ALLOW_SYSCALL(0x0014), // writev + _SECCOMP_ALLOW_SYSCALL(0x0009), // mmap + _SECCOMP_ALLOW_SYSCALL(0x000b), // munmap + _SECCOMP_ALLOW_SYSCALL(0x0000), // read + _SECCOMP_ALLOW_SYSCALL(0x0001), // write + _SECCOMP_ALLOW_SYSCALL(0x0003), // close + _SECCOMP_ALLOW_SYSCALL(0x0008), // lseek + _SECCOMP_ALLOW_SYSCALL(0x000f), // rt_sigreturn + _SECCOMP_ALLOW_SYSCALL(0x00e7), // exit_group + _SECCOMP_ALLOW_SYSCALL(0x0106), // newfstatat + _SECCOMP_ALLOW_SYSCALL(0x00e4), // clock_gettime + _SECCOMP_ALLOW_SYSCALL(0x003f), // uname + _SECCOMP_ALLOW_SYSCALL(0x0048), // fcntl + _SECCOMP_ALLOW_SYSCALL(0x0029), // socket + _SECCOMP_ALLOW_SYSCALL(0x002a), // connect + _SECCOMP_ALLOW_SYSCALL(0x002c), // sendto + _SECCOMP_ALLOW_SYSCALL(0x002d), // recvfrom + _SECCOMP_ALLOW_SYSCALL(0x0036), // setsockopt + _SECCOMP_LOG_AND_RETURN_ERRNO(1), // EPERM +}; + +static const struct sock_filter kSandboxOffline[] = { + _SECCOMP_MACHINE(AUDIT_ARCH_X86_64), // + _SECCOMP_LOAD_SYSCALL_NR(), // + _SECCOMP_ALLOW_SYSCALL(0x0013), // readv + _SECCOMP_ALLOW_SYSCALL(0x0014), // writev + _SECCOMP_ALLOW_SYSCALL(0x0000), // read + _SECCOMP_ALLOW_SYSCALL(0x0001), // write + _SECCOMP_ALLOW_SYSCALL(0x0009), // mmap + _SECCOMP_ALLOW_SYSCALL(0x000b), // munmap + _SECCOMP_ALLOW_SYSCALL(0x0003), // close + _SECCOMP_ALLOW_SYSCALL(0x0008), // lseek + _SECCOMP_ALLOW_SYSCALL(0x000f), // rt_sigreturn + _SECCOMP_ALLOW_SYSCALL(0x00e7), // exit_group + _SECCOMP_ALLOW_SYSCALL(0x0106), // newfstatat + _SECCOMP_ALLOW_SYSCALL(0x00e4), // clock_gettime + _SECCOMP_ALLOW_SYSCALL(0x003f), // uname + _SECCOMP_ALLOW_SYSCALL(0x0048), // fcntl + _SECCOMP_LOG_AND_RETURN_ERRNO(1), // EPERM +}; + +static const struct sock_fprog kSandboxOnlineProg = { + .len = ARRAYLEN(kSandboxOnline), + .filter = kSandboxOnline, +}; + +static const struct sock_fprog kSandboxOfflineProg = { + .len = ARRAYLEN(kSandboxOffline), + .filter = kSandboxOffline, +}; + +static int EnableSandbox(void) { + const struct sock_fprog *sandbox; + switch (sandboxed) { + case 0: + return 0; + case 1: + DEBUGF("(stat) applying '%s' sandbox policy", "online"); + sandbox = &kSandboxOnlineProg; + break; + default: + DEBUGF("(stat) applying '%s' sandbox policy", "offline"); + sandbox = &kSandboxOfflineProg; + break; + } + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != -1 && + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, sandbox) != -1) { + return 0; + } else { + return -1; + } +} + // returns 0 otherwise -1 if worker needs to unwind stack and exit static int HandleConnection(size_t i) { int pid, rc = 0; @@ -6595,6 +6697,7 @@ static int HandleConnection(size_t i) { if ((client = accept4(servers.p[i].fd, &clientaddr, &clientaddrsize, SOCK_CLOEXEC)) != -1) { startconnection = nowl(); + VERBOSEF("(srvr) accept %s via %s", DescribeClient(), DescribeServer()); messageshandled = 0; if (hasonclientconnection && LuaOnClientConnection()) { close(client); @@ -6607,11 +6710,19 @@ static int HandleConnection(size_t i) { switch ((pid = fork())) { case 0: meltdown = false; + __isworker = true; connectionclose = false; if (!IsTiny()) { - if (systrace) __strace = 1; - if (funtrace) ftrace_install(); + if (systrace) { + extern unsigned long long __kbirth; + __strace = 1; + __kbirth = rdtsc(); + } + if (funtrace) { + ftrace_install(); + } } + CHECK_NE(-1, EnableSandbox()); if (hasonworkerstart) { CallSimpleHook("OnWorkerStart"); } @@ -6632,7 +6743,6 @@ static int HandleConnection(size_t i) { if (!pid && !IsWindows()) { CloseServerFds(); } - VERBOSEF("(srvr) accept %s via %s", DescribeClient(), DescribeServer()); HandleMessages(); DEBUGF("(stat) %s closing after %,ldµs", DescribeClient(), (long)((nowl() - startconnection) * 1e6L)); @@ -6809,7 +6919,7 @@ static void Listen(void) { INFOF("(srvr) listen http://%hhu.%hhu.%hhu.%hhu:%d", ip >> 24, ip >> 16, ip >> 8, ip, port); if (printport && !ports.p[j]) { - printf("%d\n", port); + printf("%d\r\n", port); fflush(stdout); } } @@ -7004,6 +7114,7 @@ static void GetOpts(int argc, char *argv[]) { bool storeasset = false; while ((opt = getopt(argc, argv, GETOPTS)) != -1) { switch (opt) { + CASE('S', ++sandboxed); CASE('v', ++__log_level); CASE('s', --__log_level); CASE('f', funtrace = true); @@ -7014,7 +7125,6 @@ static void GetOpts(int argc, char *argv[]) { CASE('a', logrusage = true); CASE('u', uniprocess = true); CASE('g', loglatency = true); - CASE('S', issandboxed = true); CASE('m', logmessages = true); CASE('l', ProgramAddr(optarg)); CASE('H', ProgramHeader(optarg)); @@ -7028,7 +7138,7 @@ static void GetOpts(int argc, char *argv[]) { CASE('c', ProgramCache(ParseInt(optarg))); CASE('r', ProgramRedirectArg(307, optarg)); CASE('t', ProgramTimeout(ParseInt(optarg))); - CASE('h', PrintUsage(stdout, EXIT_SUCCESS)); + CASE('h', PrintUsage(1, EXIT_SUCCESS)); CASE('M', ProgramMaxPayloadSize(ParseInt(optarg))); #ifndef STATIC CASE('e', LuaEvalCode(optarg)); @@ -7046,7 +7156,7 @@ static void GetOpts(int argc, char *argv[]) { CASE('K', ProgramFile(optarg, ProgramPrivateKey)); #endif default: - PrintUsage(stderr, EX_USAGE); + PrintUsage(2, EX_USAGE); } } // if storing asset(s) is requested, don't need to continue @@ -7107,6 +7217,8 @@ void RedBean(int argc, char *argv[]) { #ifdef STATIC EventLoop(-1, HEARTBEAT); #else + GetResolvConf(); // for effect + GetHostsTxt(); // for effect if (!IsWindows() && isatty(0)) { ReplEventLoop(); } else { @@ -7127,7 +7239,6 @@ void RedBean(int argc, char *argv[]) { int main(int argc, char *argv[]) { if (!IsTiny()) { - setenv("GDB", "", true); ShowCrashReports(); } RedBean(argc, argv); diff --git a/tool/net/sandbox.h b/tool/net/sandbox.h new file mode 100644 index 000000000..2d1da23d4 --- /dev/null +++ b/tool/net/sandbox.h @@ -0,0 +1,23 @@ +#ifndef COSMOPOLITAN_TOOL_NET_SANDBOX_H_ +#define COSMOPOLITAN_TOOL_NET_SANDBOX_H_ +#include "libc/calls/struct/bpf.h" +#include "libc/calls/struct/filter.h" +#include "libc/calls/struct/seccomp.h" +// clang-format off + +#define _SECCOMP_MACHINE(MAGNUM) \ + BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, arch)), \ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0), \ + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS) + +#define _SECCOMP_LOAD_SYSCALL_NR() \ + BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)) + +#define _SECCOMP_ALLOW_SYSCALL(MAGNUM) \ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, MAGNUM, 0, 1), \ + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW) + +#define _SECCOMP_LOG_AND_RETURN_ERRNO(MAGNUM) \ + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (MAGNUM & SECCOMP_RET_DATA)) + +#endif /* COSMOPOLITAN_TOOL_NET_SANDBOX_H_ */