Overhaul process spawning

This commit is contained in:
Justine Tunney 2023-09-10 08:12:43 -07:00
parent 99dc1281f5
commit 26e254fb4d
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
96 changed files with 1848 additions and 1541 deletions

View file

@ -17,8 +17,11 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/rlimit.h"
#include "libc/calls/struct/rlimit.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bits.h"
@ -40,6 +43,7 @@
#include "libc/nt/enum/version.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdckdint.h"
#include "libc/str/str.h"
@ -47,6 +51,8 @@
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/rlim.h"
#include "libc/sysv/consts/rlimit.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/tls.h"
#include "third_party/dlmalloc/dlmalloc.h"
@ -910,7 +916,7 @@ static __wur __asan_die_f *__asan_report(const void *addr, int size,
*p = 0;
kprintf("%s", buf);
__asan_report_memory_origin(addr, size, kind);
kprintf("\nthe crash was caused by\n");
kprintf("\nthe crash was caused by %s\n", program_invocation_name);
ftrace_enabled(+1);
return __asan_die();
}
@ -1428,32 +1434,6 @@ static size_t __asan_strlen(const char *s) {
return i;
}
static textstartup void __asan_shadow_string(char *s) {
__asan_map_shadow((intptr_t)s, __asan_strlen(s) + 1);
}
static textstartup void __asan_shadow_auxv(intptr_t *auxv) {
size_t i;
for (i = 0; auxv[i]; i += 2) {
if (_weaken(AT_RANDOM) && auxv[i] == *_weaken(AT_RANDOM)) {
__asan_map_shadow(auxv[i + 1], 16);
} else if (_weaken(AT_EXECFN) && auxv[i] == *_weaken(AT_EXECFN)) {
__asan_shadow_string((char *)auxv[i + 1]);
} else if (_weaken(AT_PLATFORM) && auxv[i] == *_weaken(AT_PLATFORM)) {
__asan_shadow_string((char *)auxv[i + 1]);
}
}
__asan_map_shadow((uintptr_t)auxv, (i + 2) * sizeof(intptr_t));
}
static textstartup void __asan_shadow_string_list(char **list) {
size_t i;
for (i = 0; list[i]; ++i) {
__asan_shadow_string(list[i]);
}
__asan_map_shadow((uintptr_t)list, (i + 1) * sizeof(char *));
}
static textstartup void __asan_shadow_mapping(struct MemoryIntervals *m,
size_t i) {
uintptr_t x, y;
@ -1465,18 +1445,94 @@ static textstartup void __asan_shadow_mapping(struct MemoryIntervals *m,
}
}
static textstartup void __asan_shadow_existing_mappings(void) {
static textstartup char *__asan_get_last_string(char **list) {
char *res = 0;
for (int i = 0; list[i]; ++i) {
res = list[i];
}
return res;
}
static textstartup uintptr_t __asan_get_stack_top(int argc, char **argv,
char **envp,
unsigned long *auxv,
long pagesz) {
uintptr_t top;
const char *s;
if ((s = __asan_get_last_string(envp)) ||
(s = __asan_get_last_string(argv))) {
top = (uintptr_t)s + __asan_strlen(s);
} else {
unsigned long *xp = auxv;
while (*xp) xp += 2;
top = (uintptr_t)xp;
}
return (top + (pagesz - 1)) & -pagesz;
}
static textstartup void __asan_shadow_existing_mappings(int argc, char **argv,
char **envp,
unsigned long *auxv) {
__asan_shadow_mapping(&_mmi, 0);
__asan_map_shadow(GetStackAddr(), GetStackSize());
__asan_poison((void *)GetStackAddr(), getauxval(AT_PAGESZ),
kAsanStackOverflow);
// WinMain() maps its own stack and its shadow too
if (IsWindows()) {
return;
}
// get microprocessor page size
long pagesz = 4096;
for (int i = 0; auxv[i]; i += 2) {
if (auxv[i] == AT_PAGESZ) {
pagesz = auxv[i + 1];
}
}
// get configured stack size of main thread
// supported platforms use defaults ranging from 4mb to 512mb
struct rlimit rlim;
uintptr_t stack_size = 4 * 1024 * 1024;
if (!sys_getrlimit(RLIMIT_STACK, &rlim) && //
rlim.rlim_cur > 0 && rlim.rlim_cur < RLIM_INFINITY) {
stack_size = (rlim.rlim_cur + (pagesz - 1)) & -pagesz;
}
// Every UNIX system in our support vector creates arg blocks like:
//
// <HIGHEST-STACK-ADDRESS>
// last environ string
// ...
// first environ string
// ...
// auxiliary value pointers
// environ pointers
// argument pointers
// argument count
// --- %rsp _start()
// ...
// ...
// ... program's stack
// ...
// ...
// <LOWEST-STACK-ADDRESS>
//
// The region of memory between highest and lowest can be computed
// across all supported platforms ±1 page accuracy as the distance
// between the last character of the last environ variable rounded
// up to the microprocessor page size (this computes the top addr)
// and the bottom is computed by subtracting RLIMIT_STACK rlim_cur
// It's simple but gets tricky if we consider environ can be empty
uintptr_t stack_top = __asan_get_stack_top(argc, argv, envp, auxv, pagesz);
uintptr_t stack_bot = stack_top - stack_size;
__asan_map_shadow(stack_bot, stack_top - stack_bot);
__asan_poison((void *)stack_bot, GetGuardSize(), kAsanStackOverflow);
}
forceinline ssize_t __write_str(const char *s) {
return sys_write(2, s, __asan_strlen(s));
}
void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
void __asan_init(int argc, char **argv, char **envp, unsigned long *auxv) {
static bool once;
if (!_cmpxchg(&once, false, true)) return;
if (IsWindows() && NtGetVersion() < kNtVersionWindows10) {
@ -1493,16 +1549,13 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
REQUIRE(dlmemalign);
REQUIRE(dlmalloc_usable_size);
}
__asan_shadow_existing_mappings();
__asan_shadow_existing_mappings(argc, argv, envp, auxv);
__asan_map_shadow((uintptr_t)__executable_start, _end - __executable_start);
__asan_map_shadow(0, 4096);
__asan_poison((void *)__veil("r", 0L), getauxval(AT_PAGESZ), kAsanNullPage);
if (!IsWindows()) {
sys_mprotect((void *)0x7fff8000, 0x10000, PROT_READ);
}
__asan_shadow_string_list(argv);
__asan_shadow_string_list(envp);
__asan_shadow_auxv(auxv);
__asan_install_malloc_hooks();
STRACE(" _ ____ _ _ _ ");
STRACE(" / \\ / ___| / \\ | \\ | |");

View file

@ -18,22 +18,30 @@
*/
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/libfatal.internal.h"
#include "libc/nexgen32e/stackframe.h"
#define N 64
#define N 100
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
const char *(DescribeBacktrace)(char buf[N], struct StackFrame *fr) {
int o = 0;
dontinstrument dontasan const char *(DescribeBacktrace)(char buf[N],
struct StackFrame *fr) {
bool gotsome = false;
char *p = buf;
char *pe = p + N;
while (fr) {
if (gotsome) {
append(" ");
if (p + 1 < pe) {
*p++ = ' ';
*p = 0;
}
} else {
gotsome = true;
}
append("%x", fr->addr);
if (p + 17 <= pe) {
p = __hexcpy(p, fr->addr);
}
fr = fr->next;
}
return buf;

View file

@ -5,8 +5,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
const char *DescribeBacktrace(char[64], struct StackFrame *);
#define DescribeBacktrace(x) DescribeBacktrace(alloca(64), x)
const char *DescribeBacktrace(char[100], struct StackFrame *);
#define DescribeBacktrace(x) DescribeBacktrace(alloca(100), x)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -22,7 +22,9 @@
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/asancodes.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/directmap.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
@ -30,7 +32,7 @@
#define G FRAMESIZE
static void *_mapframe(void *p, int f) {
static dontasan void *_mapframe(void *p, int f) {
int rc, prot, flags;
struct DirectMap dm;
prot = PROT_READ | PROT_WRITE;

View file

@ -41,7 +41,7 @@
* @threadsafe
* @vforksafe
*/
int getpid(void) {
dontasan int getpid(void) {
int rc;
if (IsMetal()) {
rc = 1;

View file

@ -19,10 +19,13 @@
#include "libc/intrin/kmalloc.h"
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/describebacktrace.internal.h"
#include "libc/intrin/extend.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/sysv/consts/map.h"
@ -63,7 +66,7 @@ void __kmalloc_unlock(void) {
* @return zero-initialized memory on success, or null w/ errno
* @raise ENOMEM if we require more vespene gas
*/
void *kmalloc(size_t size) {
dontasan void *kmalloc(size_t size) {
char *p, *e;
size_t i, n, t;
n = ROUNDUP(size + (IsAsan() * 8), KMALLOC_ALIGN);

View file

@ -325,13 +325,13 @@ privileged long kloghandle(void) {
long proc;
proc = __imp_GetCurrentProcess();
hand = __imp_GetStdHandle(kNtStdErrorHandle);
__imp_DuplicateHandle(proc, hand, proc, &hand, 0, true,
__imp_DuplicateHandle(proc, hand, proc, &hand, 0, false,
kNtDuplicateSameAccess);
} else if (n && n < 512) {
hand = __imp_CreateFileW(
path, kNtFileAppendData,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
&kNtIsInheritable, kNtOpenAlways, kNtFileAttributeNormal, 0);
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
kNtOpenAlways, kNtFileAttributeNormal, 0);
} else {
hand = -1; // KPRINTF_LOG was empty string or too long
}