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.
This commit is contained in:
Justine Tunney 2022-04-18 08:54:42 -07:00
parent 7166679620
commit 5a132f9652
79 changed files with 2271 additions and 651 deletions

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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 *);

View file

@ -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 ? "..." : "");
}

1341
libc/calls/struct/bpf.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -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_ */

23
libc/calls/struct/hog.py Normal file
View file

@ -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

View file

@ -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_ */

View file

@ -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

View file

@ -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) {

View file

@ -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;

View file

@ -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:
*

View file

@ -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;
}

View file

@ -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();

View file

@ -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) &&

View file

@ -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));

View file

@ -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" : "");
}

View file

@ -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)())) {

View file

@ -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;

View file

@ -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);

31
libc/sock/asanmsghdr.c Normal file
View file

@ -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);
}

View file

@ -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 *,

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_ALERT,1,1,1,1,1,1

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_AUTH,0x20,0x20,0x20,0x20,0x20,0x20

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_CONS,2,2,2,2,2,2

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_CRIT,2,2,2,2,2,2

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_CRON,72,72,72,72,72,72

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_DAEMON,24,24,24,24,24,24

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_DEBUG,7,7,7,7,7,7

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_EMERG,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_ERR,3,3,3,3,3,3

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_FACMASK,0x03f8,0x03f8,0x03f8,0x03f8,0x03f8,0x03f8

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_INFO,6,6,6,6,6,6

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_KERN,0,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL0,0x80,0x80,0x80,0x80,0x80,0x80

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL1,136,136,136,136,136,136

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL2,144,144,144,144,144,144

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL3,152,152,152,152,152,152

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL4,160,160,160,160,160,160

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL5,168,168,168,168,168,168

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL6,176,176,176,176,176,176

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LOCAL7,184,184,184,184,184,184

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_LPR,48,48,48,48,48,48

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_MAIL,0x10,0x10,0x10,0x10,0x10,0x10

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_NDELAY,8,8,8,8,8,8

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_NEWS,56,56,56,56,56,56

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_NFACILITIES,24,25,24,24,24,24

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_NOTICE,5,5,5,5,5,5

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_NOWAIT,0x10,0x10,0x10,0x10,0x10,0x10

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_ODELAY,4,4,4,4,4,4

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_PERROR,0x20,0x20,0x20,0x20,0x20,0x20

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_PID,1,1,1,1,1,1

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_PRIMASK,7,7,7,7,7,7

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_SELECT,76,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_SENSE,77,0,0,0,0,0

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_SYSLOG,40,40,40,40,40,40

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_USER,8,8,8,8,8,8

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_UUCP,0x40,0x40,0x40,0x40,0x40,40

View file

@ -1,2 +0,0 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon log,LOG_WARNING,4,4,4,4,4,4

13
libc/sysv/consts/audit.h Normal file
View file

@ -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_ */

View file

@ -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_ */

View file

@ -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

View file

@ -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_ */

View file

@ -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

View file

@ -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,

View file

@ -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);
}

View file

@ -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")}, //
{"%%", "%%%%"}, //
{"%", "%.%"}, //

View file

@ -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);
}
}

View file

@ -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(),

View file

@ -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;
}

View file

@ -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);

23
tool/net/sandbox.h Normal file
View file

@ -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_ */