mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-13 14:39:10 +00:00
Improve pledge() usability and consistency
- We now kill the program on violations like OpenBSD - We now print a message explaining which promise is needed - This change also fixes a linkage bug with thread local storage - Your sigaction() handlers should now be more thread safe A new `__pledge_mode` global has been introduced to make pledge() more customizable on Linux. For example: __attribute__((__constructor__)) static void init(void) { __pledge_mode = SECCOMP_RET_ERRNO | EPERM; } Can be used to restore our old permissive pledge() behavior.
This commit is contained in:
parent
13c1c45075
commit
5546559034
30 changed files with 713 additions and 86 deletions
|
@ -19,17 +19,5 @@
|
|||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
unsigned __sighandrvas[NSIG];
|
||||
unsigned __sighandflags[NSIG];
|
||||
|
||||
static pthread_mutex_t __sig_lock_obj;
|
||||
|
||||
void(__sig_lock)(void) {
|
||||
__sig_lock_obj.attr = PTHREAD_MUTEX_RECURSIVE;
|
||||
pthread_mutex_lock(&__sig_lock_obj);
|
||||
}
|
||||
|
||||
void(__sig_unlock)(void) {
|
||||
__sig_lock_obj.attr = PTHREAD_MUTEX_RECURSIVE;
|
||||
pthread_mutex_unlock(&__sig_lock_obj);
|
||||
}
|
||||
_Thread_local unsigned __sighandrvas[NSIG];
|
||||
_Thread_local unsigned __sighandflags[NSIG];
|
||||
|
|
|
@ -23,18 +23,27 @@
|
|||
#include "libc/calls/struct/bpf.h"
|
||||
#include "libc/calls/struct/filter.h"
|
||||
#include "libc/calls/struct/seccomp.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/audit.h"
|
||||
#include "libc/sysv/consts/kern.h"
|
||||
#include "libc/sysv/consts/nrlinux.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/pr.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define SPECIAL 0xf000
|
||||
|
@ -63,6 +72,13 @@
|
|||
|
||||
#define PLEDGE(pledge) pledge, ARRAYLEN(pledge)
|
||||
|
||||
#define AbortPledge(reason) \
|
||||
do { \
|
||||
assert(!reason); \
|
||||
asm("hlt"); \
|
||||
unreachable; \
|
||||
} while (0)
|
||||
|
||||
struct Filter {
|
||||
size_t n;
|
||||
struct sock_filter p[700];
|
||||
|
@ -79,6 +95,7 @@ static const uint16_t kPledgeLinuxDefault[] = {
|
|||
// difference in the latency of sched_yield() if it's at the start of
|
||||
// the bpf script or the end.
|
||||
static const uint16_t kPledgeLinuxStdio[] = {
|
||||
__NR_linux_sigreturn, //
|
||||
__NR_linux_exit_group, //
|
||||
__NR_linux_sched_yield, //
|
||||
__NR_linux_sched_getaffinity, //
|
||||
|
@ -175,7 +192,6 @@ static const uint16_t kPledgeLinuxStdio[] = {
|
|||
__NR_linux_sigaltstack, //
|
||||
__NR_linux_sigprocmask, //
|
||||
__NR_linux_sigsuspend, //
|
||||
__NR_linux_sigreturn, //
|
||||
__NR_linux_sigpending, //
|
||||
__NR_linux_socketpair, //
|
||||
__NR_linux_getrusage, //
|
||||
|
@ -432,7 +448,7 @@ static const struct sock_filter kFilterStart[] = {
|
|||
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS),
|
||||
// each filter assumes ordinal is already loaded into accumulator
|
||||
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||
// Forbid some system calls with ENOSYS (rather than EPERM)
|
||||
// forbid some system calls with ENOSYS (rather than EPERM)
|
||||
BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, __NR_linux_memfd_secret, 5, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_rseq, 4, 0),
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_memfd_create, 3, 0),
|
||||
|
@ -442,15 +458,91 @@ static const struct sock_filter kFilterStart[] = {
|
|||
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (38 & SECCOMP_RET_DATA)),
|
||||
};
|
||||
|
||||
static const struct sock_filter kFilterEnd[] = {
|
||||
// if syscall isn't whitelisted then have it return -EPERM (-1)
|
||||
static const struct sock_filter kFilterIgnoreExitGroup[] = {
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_exit_group, 0, 1),
|
||||
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (1 & SECCOMP_RET_DATA)),
|
||||
};
|
||||
|
||||
static void Log(const char *s, ...) {
|
||||
va_list va;
|
||||
va_start(va, s);
|
||||
do {
|
||||
write(2, s, strlen(s));
|
||||
} while ((s = va_arg(va, const char *)));
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
static bool HasSyscall(struct Pledges *p, uint16_t n) {
|
||||
int i;
|
||||
for (i = 0; i < p->len; ++i) {
|
||||
if ((p->syscalls[i] & 0x0fff) == n) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *FixCpy(char p[17], uint64_t x, uint8_t k) {
|
||||
while (k > 0) *p++ = "0123456789abcdef"[(x >> (k -= 4)) & 15];
|
||||
*p = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *HexCpy(char p[17], uint64_t x) {
|
||||
return FixCpy(p, x, ROUNDUP(x ? bsrl(x) + 1 : 1, 4));
|
||||
}
|
||||
|
||||
static void OnSigSys(int sig, siginfo_t *si, ucontext_t *ctx) {
|
||||
int i;
|
||||
bool found;
|
||||
char ord[17], rip[17];
|
||||
struct sigaction dfl = {.sa_sigaction = SIG_DFL};
|
||||
ctx->uc_mcontext.rax = -si->si_errno;
|
||||
FixCpy(ord, si->si_syscall, 12);
|
||||
HexCpy(rip, ctx->uc_mcontext.rip);
|
||||
for (found = i = 0; i < ARRAYLEN(kPledgeLinux); ++i) {
|
||||
if (HasSyscall(kPledgeLinux + i, si->si_syscall)) {
|
||||
Log("error: has not pledged ", kPledgeLinux[i].name, //
|
||||
" (ord=", ord, " rip=", rip, ")\n", 0);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
Log("error: unsupported syscall (ord=", ord, " rip=", rip, ")\n", 0);
|
||||
}
|
||||
switch (__pledge_mode) {
|
||||
case SECCOMP_RET_KILL_PROCESS:
|
||||
if (!sigaction(SIGABRT, &dfl, 0)) {
|
||||
sys_kill(getpid(), SIGABRT, 1);
|
||||
}
|
||||
_Exit(128 + SIGABRT);
|
||||
case SECCOMP_RET_KILL_THREAD:
|
||||
if (!sigaction(SIGABRT, &dfl, 0)) {
|
||||
sys_tgkill(getpid(), gettid(), SIGABRT);
|
||||
}
|
||||
_Exit1(128 + SIGABRT);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MonitorSigSys(void) {
|
||||
static _Thread_local bool once;
|
||||
if (once) return;
|
||||
once = true;
|
||||
struct sigaction sa = {
|
||||
.sa_sigaction = OnSigSys,
|
||||
.sa_flags = SA_SIGINFO | SA_RESTART,
|
||||
};
|
||||
if (sigaction(SIGSYS, &sa, 0)) {
|
||||
AbortPledge("sigaction failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void AppendFilter(struct Filter *f, struct sock_filter *p, size_t n) {
|
||||
if (UNLIKELY(f->n + n > ARRAYLEN(f->p))) {
|
||||
asm("hlt"); // need to increase array size
|
||||
unreachable;
|
||||
AbortPledge("need to increase array size");
|
||||
}
|
||||
memcpy(f->p + f->n, p, n * sizeof(*f->p));
|
||||
f->n += n;
|
||||
|
@ -1093,20 +1185,22 @@ static void AllowSocketUnix(struct Filter *f) {
|
|||
// - PR_SET_SECCOMP (22)
|
||||
// - PR_SET_NO_NEW_PRIVS (38)
|
||||
// - PR_CAPBSET_READ (23)
|
||||
// - PR_CAPBSET_DROP (24)
|
||||
//
|
||||
static void AllowPrctlStdio(struct Filter *f) {
|
||||
static const struct sock_filter fragment[] = {
|
||||
/*L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_prctl, 0, 10 - 1),
|
||||
/*L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])),
|
||||
/*L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 15, 5, 0),
|
||||
/*L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 16, 4, 0),
|
||||
/*L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 21, 3, 0),
|
||||
/*L5*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 2, 0),
|
||||
/*L5*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 23, 1, 0),
|
||||
/*L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 38, 0, 1),
|
||||
/*L7*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||
/*L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||
/*L9*/ /* next filter */
|
||||
/* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_linux_prctl, 0, 11 - 1),
|
||||
/* L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[0])),
|
||||
/* L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 15, 6, 0),
|
||||
/* L3*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 16, 5, 0),
|
||||
/* L4*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 21, 4, 0),
|
||||
/* L5*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 22, 3, 0),
|
||||
/* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 23, 2, 0),
|
||||
/* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 24, 1, 0),
|
||||
/* L8*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 38, 0, 1),
|
||||
/* L9*/ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
|
||||
/*L10*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)),
|
||||
/*L11*/ /* next filter */
|
||||
};
|
||||
AppendFilter(f, PLEDGE(fragment));
|
||||
}
|
||||
|
@ -1220,8 +1314,7 @@ static void AppendPledge(struct Filter *f, const uint16_t *p, size_t len) {
|
|||
};
|
||||
AppendFilter(f, PLEDGE(fragment));
|
||||
} else {
|
||||
asm("hlt"); // list of ordinals exceeds max displacement
|
||||
unreachable;
|
||||
AbortPledge("list of ordinals exceeds max displacement");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1311,8 +1404,7 @@ static void AppendPledge(struct Filter *f, const uint16_t *p, size_t len) {
|
|||
AllowPrlimitStdio(f);
|
||||
break;
|
||||
default:
|
||||
asm("hlt"); // switch forgot to define a special ordinal
|
||||
unreachable;
|
||||
AbortPledge("switch forgot to define a special ordinal");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1322,7 +1414,14 @@ int sys_pledge_linux(unsigned long ipromises) {
|
|||
struct Filter f;
|
||||
CheckLargeStackAllocation(&f, sizeof(f));
|
||||
f.n = 0;
|
||||
|
||||
// set up the seccomp filter
|
||||
AppendFilter(&f, PLEDGE(kFilterStart));
|
||||
if (ipromises == -1) {
|
||||
// if we're pledging empty string, then avoid triggering a sigsys
|
||||
// when _Exit() gets called since we need to fallback to _Exit1()
|
||||
AppendFilter(&f, PLEDGE(kFilterIgnoreExitGroup));
|
||||
}
|
||||
if (!(~ipromises & (1ul << PROMISE_EXEC))) {
|
||||
AppendOriginVerification(&f);
|
||||
}
|
||||
|
@ -1332,7 +1431,30 @@ int sys_pledge_linux(unsigned long ipromises) {
|
|||
AppendPledge(&f, kPledgeLinux[i].syscalls, kPledgeLinux[i].len);
|
||||
}
|
||||
}
|
||||
AppendFilter(&f, PLEDGE(kFilterEnd));
|
||||
|
||||
// now determine the default seccomp action
|
||||
// the __pledge_mode global could be set to
|
||||
// - SECCOMP_RET_KILL
|
||||
// - SECCOMP_RET_KILL_THREAD
|
||||
// - SECCOMP_RET_KILL_PROCESS
|
||||
// - SECCOMP_RET_ERRNO | EPERM
|
||||
struct sock_filter filter[1] = {BPF_STMT(BPF_RET | BPF_K, 0)};
|
||||
if (~ipromises & (1ul << PROMISE_EXEC)) {
|
||||
// our sigsys error message handler can't be inherited across
|
||||
// execve() boundaries so if you've pledged exec then that'll
|
||||
// mean no error messages for you.
|
||||
filter[0].k = __pledge_mode;
|
||||
AppendFilter(&f, PLEDGE(filter));
|
||||
} else {
|
||||
// if we haven't pledged exec, then we can monitor SIGSYS
|
||||
// and print a helpful error message when things do break
|
||||
// the handler then decides what to do with __pledge_mode
|
||||
MonitorSigSys();
|
||||
filter[0].k = SECCOMP_RET_TRAP | EPERM;
|
||||
AppendFilter(&f, PLEDGE(filter));
|
||||
}
|
||||
|
||||
// register our seccomp filter with the kernel
|
||||
if ((rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) != -1) {
|
||||
struct sock_fprog sandbox = {.len = f.n, .filter = f.p};
|
||||
rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &sandbox);
|
||||
|
@ -1388,11 +1510,13 @@ int ParsePromises(const char *promises, unsigned long *out) {
|
|||
*
|
||||
* Pledging causes most system calls to become unavailable. Your system
|
||||
* call policy is enforced by the kernel, which means it can propagate
|
||||
* across execve() if permitted. This system call is supported on
|
||||
* OpenBSD and Linux where it's polyfilled using SECCOMP BPF. The way it
|
||||
* works on Linux is verboten system calls will raise EPERM whereas
|
||||
* OpenBSD just kills the process while logging a helpful message to
|
||||
* /var/log/messages explaining which promise category you needed.
|
||||
* across execve() if permitted. Root is not required. This system call
|
||||
* is supported on OpenBSD and Linux where it's polyfilled using SECCOMP
|
||||
* BPF. The way it works on Linux is, if a forbidden system call is used
|
||||
* then the kernel will will the process. On OpenBSD, a helpful message
|
||||
* explaining which promise is needed should be emitted to your system
|
||||
* log. On Linux, we log that to stderr with one exception: reporting is
|
||||
* currently not possible if you pledge exec.
|
||||
*
|
||||
* Timing is everything with pledge. For example, if you're using
|
||||
* threads, then you may want to enable them explicitly *before* calling
|
||||
|
@ -1548,6 +1672,7 @@ int ParsePromises(const char *promises, unsigned long *out) {
|
|||
* @raise ENOSYS if host os isn't Linux or OpenBSD
|
||||
* @raise EINVAL if `execpromises` on Linux isn't a subset of `promises`
|
||||
* @raise EINVAL if `promises` allows exec and `execpromises` is null
|
||||
* @threadsafe
|
||||
*/
|
||||
int pledge(const char *promises, const char *execpromises) {
|
||||
int rc;
|
||||
|
|
|
@ -99,7 +99,6 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
STRACE("delivering %G", sig);
|
||||
|
||||
// enter the signal
|
||||
__sig_lock();
|
||||
rva = __sighandrvas[sig];
|
||||
flags = __sighandflags[sig];
|
||||
if ((~flags & SA_NODEFER) || (flags & SA_RESETHAND)) {
|
||||
|
@ -110,7 +109,6 @@ static bool __sig_deliver(bool restartable, int sig, int si_code,
|
|||
// signal handler. in that case you must use SA_NODEFER.
|
||||
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
|
||||
}
|
||||
__sig_unlock();
|
||||
|
||||
// setup the somewhat expensive information args
|
||||
// only if they're requested by the user in sigaction()
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -245,7 +244,7 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
}
|
||||
|
||||
/**
|
||||
* Installs handler for kernel interrupt, e.g.:
|
||||
* Installs handler for kernel interrupt to thread, e.g.:
|
||||
*
|
||||
* void GotCtrlC(int sig, siginfo_t *si, ucontext_t *ctx);
|
||||
* struct sigaction sa = {.sa_sigaction = GotCtrlC,
|
||||
|
@ -445,6 +444,7 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
* @return 0 on success or -1 w/ errno
|
||||
* @see xsigaction() for a much better api
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||
|
@ -452,9 +452,7 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
|||
if (sig == SIGKILL || sig == SIGSTOP) {
|
||||
rc = einval();
|
||||
} else {
|
||||
__sig_lock();
|
||||
rc = __sigaction(sig, act, oldact);
|
||||
__sig_unlock();
|
||||
}
|
||||
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig, DescribeSigaction(0, act),
|
||||
DescribeSigaction(rc, oldact), rc);
|
||||
|
|
32
libc/calls/siglock.c
Normal file
32
libc/calls/siglock.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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/calls/state.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
static pthread_mutex_t __sig_lock_obj;
|
||||
|
||||
void(__sig_lock)(void) {
|
||||
__sig_lock_obj.attr = PTHREAD_MUTEX_RECURSIVE;
|
||||
pthread_mutex_lock(&__sig_lock_obj);
|
||||
}
|
||||
|
||||
void(__sig_unlock)(void) {
|
||||
__sig_lock_obj.attr = PTHREAD_MUTEX_RECURSIVE;
|
||||
pthread_mutex_unlock(&__sig_lock_obj);
|
||||
}
|
|
@ -7,8 +7,8 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
hidden extern int __vforked;
|
||||
hidden extern bool __time_critical;
|
||||
hidden extern unsigned __sighandrvas[NSIG];
|
||||
hidden extern unsigned __sighandflags[NSIG];
|
||||
hidden _Thread_local extern unsigned __sighandrvas[NSIG];
|
||||
hidden _Thread_local extern unsigned __sighandflags[NSIG];
|
||||
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
|
||||
|
||||
void __fds_lock(void);
|
||||
|
|
26
libc/calls/struct/statfs.h
Normal file
26
libc/calls/struct/statfs.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_STATFS_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_STATFS_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct statfs {
|
||||
int64_t f_type; /* type of filesystem */
|
||||
int64_t f_bsize; /* optimal transfer block size */
|
||||
int64_t f_blocks; /* total data blocks in filesystem */
|
||||
int64_t f_bfree; /* free blocks in filesystem */
|
||||
int64_t f_bavail; /* free blocks available to */
|
||||
int64_t f_files; /* total file nodes in filesystem */
|
||||
int64_t f_ffree; /* free file nodes in filesystem */
|
||||
int64_t f_fsid; /* filesystem id */
|
||||
int64_t f_namelen; /* maximum length of filenames */
|
||||
int64_t f_frsize; /* fragment size */
|
||||
int64_t f_flags; /* mount flags of filesystem 2.6.36 */
|
||||
int64_t f_spare[4];
|
||||
};
|
||||
|
||||
int statfs(const char *, struct statfs *);
|
||||
int fstatfs(int, struct statfs *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_STATFS_H_ */
|
|
@ -68,7 +68,6 @@ i32 sys_mincore(void *, u64, unsigned char *) hidden;
|
|||
i32 sys_mkdirat(i32, const char *, u32) hidden;
|
||||
i32 sys_mkfifo(const char *, u32) hidden;
|
||||
i32 sys_mknod(const char *, u32, u64) hidden;
|
||||
i32 sys_unmount(const char *, i32) hidden;
|
||||
i32 sys_mprotect(void *, u64, i32) hidden;
|
||||
i32 sys_msync(void *, u64, i32) hidden;
|
||||
i32 sys_munmap(void *, u64) hidden;
|
||||
|
@ -97,11 +96,13 @@ i32 sys_sigaltstack(const void *, void *) hidden;
|
|||
i32 sys_symlinkat(const char *, i32, const char *) hidden;
|
||||
i32 sys_sync(void) hidden;
|
||||
i32 sys_sync_file_range(i32, i64, i64, u32) hidden;
|
||||
i32 sys_syslog(i32, char *, i32) hidden;
|
||||
i32 sys_tgkill(i32, i32, i32) hidden;
|
||||
i32 sys_tkill(i32, i32, void *) hidden;
|
||||
i32 sys_truncate(const char *, u64, u64) hidden;
|
||||
i32 sys_uname(void *) hidden;
|
||||
i32 sys_unlinkat(i32, const char *, i32) hidden;
|
||||
i32 sys_unmount(const char *, i32) hidden;
|
||||
i32 sys_unveil(const char *, const char *) hidden;
|
||||
i64 sys_copy_file_range(i32, long *, i32, long *, u64, u32) hidden;
|
||||
i64 sys_getrandom(void *, u64, u32) hidden;
|
||||
|
|
|
@ -19,5 +19,6 @@
|
|||
#include "libc/intrin/promises.internal.h"
|
||||
|
||||
// XXX: should be inherited thread local
|
||||
unsigned __pledge_mode;
|
||||
unsigned long __promises;
|
||||
unsigned long __execpromises;
|
||||
|
|
|
@ -158,6 +158,11 @@ const char *GetSiCodeName(int sig, int si_code) {
|
|||
} else if (si_code == POLL_HUP) {
|
||||
strcpy(b + 5, "HUP"); /* device disconnected */
|
||||
}
|
||||
} else if (sig == SIGSYS) {
|
||||
NameIt(b, "SYS_", si_code);
|
||||
if (si_code == SYS_SECCOMP) {
|
||||
strcpy(b + 4, "SECCOMP");
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
|
|
@ -90,13 +90,13 @@ __oncrash_sigbus:
|
|||
.endfn __oncrash_sigbus,globl
|
||||
|
||||
.org 11*7
|
||||
__oncrash_sigsys:
|
||||
__oncrash_sigurg:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call __oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn __oncrash_sigsys,globl
|
||||
.endfn __oncrash_sigurg,globl
|
||||
|
||||
// </SYNC-LIST>: showcrashreports.c, oncrashthunks.S, oncrash.c, internal.h
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ void ShowCrashReports(void) {
|
|||
kCrashSigs[4] = SIGTRAP; /* bad system call */
|
||||
kCrashSigs[5] = SIGABRT; /* abort() called */
|
||||
kCrashSigs[6] = SIGBUS; /* misaligned, noncanonical ptr, etc. */
|
||||
kCrashSigs[7] = SIGSYS; /* bad system call */
|
||||
kCrashSigs[7] = SIGURG; /* placeholder */
|
||||
/* </SYNC-LIST>: showcrashreports.c, oncrashthunks.S, oncrash.c */
|
||||
if (!IsWindows()) {
|
||||
bzero(&ss, sizeof(ss));
|
||||
|
|
|
@ -55,10 +55,6 @@
|
|||
STATIC_YOINK("_check_sigchld");
|
||||
|
||||
extern int64_t __wincrashearly;
|
||||
extern unsigned char __data_start[]; /* αpε */
|
||||
extern unsigned char __data_end[]; /* αpε */
|
||||
extern unsigned char __bss_start[]; /* αpε */
|
||||
extern unsigned char __bss_end[]; /* αpε */
|
||||
bool32 __onntconsoleevent_nt(uint32_t);
|
||||
|
||||
static textwindows wontreturn void AbortFork(const char *func) {
|
||||
|
|
|
@ -17,6 +17,7 @@ extern intptr_t __oldstack; /* CRT */
|
|||
extern uint64_t __nosync; /* SYS */
|
||||
extern _Atomic(int) __ftrace; /* SYS */
|
||||
extern _Atomic(int) __strace; /* SYS */
|
||||
extern uint32_t __pledge_mode; /* SYS */
|
||||
extern char *program_invocation_name; /* RII */
|
||||
extern char *program_invocation_short_name; /* RII */
|
||||
extern uint64_t __syscount; /* RII */
|
||||
|
@ -41,6 +42,10 @@ extern unsigned char *__relo_start[]; /* αpε */
|
|||
extern unsigned char *__relo_end[]; /* αpε */
|
||||
extern uint8_t __zip_start[]; /* αpε */
|
||||
extern uint8_t __zip_end[]; /* αpε */
|
||||
extern uint8_t __data_start[]; /* αpε */
|
||||
extern uint8_t __data_end[]; /* αpε */
|
||||
extern uint8_t __bss_start[]; /* αpε */
|
||||
extern uint8_t __bss_end[]; /* αpε */
|
||||
extern size_t __virtualmax;
|
||||
extern bool __isworker;
|
||||
|
||||
|
|
2
libc/sysv/calls/sys_syslog.s
Normal file
2
libc/sysv/calls/sys_syslog.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_syslog,0xfffffffffffff067,globl,hidden
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall syslog,0xfffffffffffff067,globl
|
21
libc/sysv/consts/kern.h
Normal file
21
libc/sysv/consts/kern.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_KERN_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_KERN_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define KERN_SOH "\001"
|
||||
#define KERN_SOH_ASCII '\001'
|
||||
#define KERN_EMERG KERN_SOH "0"
|
||||
#define KERN_ALERT KERN_SOH "1"
|
||||
#define KERN_CRIT KERN_SOH "2"
|
||||
#define KERN_ERR KERN_SOH "3"
|
||||
#define KERN_WARNING KERN_SOH "4"
|
||||
#define KERN_NOTICE KERN_SOH "5"
|
||||
#define KERN_INFO KERN_SOH "6"
|
||||
#define KERN_DEBUG KERN_SOH "7"
|
||||
#define KERN_DEFAULT ""
|
||||
#define KERN_CONT KERN_SOH "c"
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_KERN_H_ */
|
19
libc/sysv/consts/loglevel.h
Normal file
19
libc/sysv/consts/loglevel.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_LOGLEVEL_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_LOGLEVEL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define LOGLEVEL_SCHED -2
|
||||
#define LOGLEVEL_DEFAULT -1
|
||||
#define LOGLEVEL_EMERG 0
|
||||
#define LOGLEVEL_ALERT 1
|
||||
#define LOGLEVEL_CRIT 2
|
||||
#define LOGLEVEL_ERR 3
|
||||
#define LOGLEVEL_WARNING 4
|
||||
#define LOGLEVEL_NOTICE 5
|
||||
#define LOGLEVEL_INFO 6
|
||||
#define LOGLEVEL_DEBUG 7
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_LOGLEVEL_H_ */
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sysv/consts/nrlinux.h"
|
||||
#include "libc/macros.internal.h"
|
||||
.privileged
|
||||
|
||||
|
@ -25,8 +26,8 @@ __restore_bt:
|
|||
.endfn __restore_bt,globl,hidden
|
||||
nop # gap so that __get_symbol(st, addr - 1) fails
|
||||
.align 16
|
||||
__restore_rt: # @see gdb/amd64-linux-tdep.c
|
||||
mov $0x000f,%rax # [sic]
|
||||
__restore_rt: # @see gdb/amd64-linux-tdep.c
|
||||
mov $__NR_linux_sigreturn,%rax # [sic]
|
||||
syscall
|
||||
.align 16
|
||||
.endfn __restore_rt,globl,hidden
|
||||
|
|
|
@ -140,7 +140,7 @@ scall __sys_getrusage 0x1bd0130752075062 globl hidden
|
|||
scall sys_sysinfo 0xfffffffffffff063 globl hidden
|
||||
scall sys_times 0xfffffffffffff064 globl hidden
|
||||
scall sys_ptrace 0x01a01a01a201a065 globl hidden
|
||||
scall syslog 0xfffffffffffff067 globl
|
||||
scall sys_syslog 0xfffffffffffff067 globl hidden
|
||||
scall sys_getuid 0x0180180182018066 globl hidden
|
||||
scall sys_getgid 0x02f02f02f202f068 globl hidden
|
||||
scall sys_getppid 0xfff027027202706e globl hidden # see sys_getpid()→edx for netbsd
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue