Skip to content

Commit

Permalink
Make execve() linger when it can't spoof parent
Browse files Browse the repository at this point in the history
It's now possible to use execve() when the parent process isn't built by
cosmo. In such cases, the current process will kill all threads and then
linger around, waiting for the newly created process to die, and then we
propagate its exit code to the parent. This should help bazel and others

Allocating private anonymous memory is now 5x faster on Windows. This is
thanks to VirtualAlloc() which is faster than the file mapping APIs. The
fork() function also now goes 30% faster, since we are able to avoid the
VirtualProtect() calls on mappings in most cases now.

Fixes #1253
  • Loading branch information
jart committed Jan 5, 2025
1 parent c97a858 commit 42a3bb7
Show file tree
Hide file tree
Showing 40 changed files with 612 additions and 656 deletions.
2 changes: 1 addition & 1 deletion ape/ape.lds
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ ape_stack_offset = 0;
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
ape_stack_filesz = 0;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 4 * 1024 * 1024;

ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
ape_note_filesz = ape_note_end - ape_note;
Expand Down
7 changes: 3 additions & 4 deletions libc/calls/metalfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,9 @@ textstartup void InitializeMetalFile(void) {
size_t size = ROUNDUP(_ezip - __executable_start, 4096);
// TODO(jart): Restore support for ZIPOS on metal.
void *copied_base;
struct DirectMap dm;
dm = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED_linux | MAP_ANONYMOUS_linux, -1, 0);
copied_base = dm.addr;
void *addr = sys_mmap_metal(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED_linux | MAP_ANONYMOUS_linux, -1, 0);
copied_base = addr;
npassert(copied_base != (void *)-1);
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_PHYSICAL), size);
__ape_com_base = copied_base;
Expand Down
8 changes: 3 additions & 5 deletions libc/calls/openat-metal.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ int sys_openat_metal(int dirfd, const char *file, int flags, unsigned mode) {
if ((fd = __reservefd(-1)) == -1)
return -1;
if (!_weaken(calloc) || !_weaken(free)) {
struct DirectMap dm;
dm = sys_mmap_metal(NULL, ROUNDUP(sizeof(struct MetalFile), 4096),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1,
0);
state = dm.addr;
state = sys_mmap_metal(NULL, ROUNDUP(sizeof(struct MetalFile), 4096),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
-1, 0);
if (state == (void *)-1)
return -1;
} else {
Expand Down
4 changes: 4 additions & 0 deletions libc/calls/syscall-nt.internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#define COSMOPOLITAN_LIBC_CALLS_SYSCALL_NT_INTERNAL_H_
COSMOPOLITAN_C_START_

extern int sys_getppid_nt_cosmo;
extern int sys_getppid_nt_win32;

bool32 sys_isatty(int);
int sys_chdir_nt(const char *);
int sys_dup_nt(int, int, int, int);
Expand Down Expand Up @@ -37,6 +40,7 @@ int sys_unlinkat_nt(int, const char *, int);
int64_t sys_lseek_nt(int, int64_t, int);
ssize_t sys_read_nt_impl(int, void *, size_t, int64_t);
ssize_t sys_readlinkat_nt(int, const char *, char *, size_t);
void sys_getppid_nt_wipe(int, int);

COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_CALLS_SYSCALL_NT_INTERNAL_H_ */
6 changes: 3 additions & 3 deletions libc/intrin/clock_gettime-nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
// —Quoth MSDN § Windows Time
//
QueryUnbiasedInterruptTimePrecise(&hectons);
*ts = timespec_fromnanos(hectons * 100);
*ts = WindowsDurationToTimeSpec(hectons);
return 0;
case _CLOCK_MONOTONIC_COARSE:
//
Expand All @@ -83,7 +83,7 @@ textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
// —Quoth MSDN § QueryUnbiasedInterruptTimePrecise
//
QueryUnbiasedInterruptTime(&hectons);
*ts = timespec_fromnanos(hectons * 100);
*ts = WindowsDurationToTimeSpec(hectons);
return 0;
case _CLOCK_BOOTTIME:
//
Expand All @@ -95,7 +95,7 @@ textwindows int sys_clock_gettime_nt(int clock, struct timespec *ts) {
// —Quoth MSDN § Interrupt Time
//
QueryInterruptTimePrecise(&hectons);
*ts = timespec_fromnanos(hectons * 100);
*ts = WindowsDurationToTimeSpec(hectons);
return 0;
case _CLOCK_PROCESS_CPUTIME_ID:
GetProcessTimes(GetCurrentProcess(), &ftCreation, &ftExit, &ftKernel,
Expand Down
32 changes: 32 additions & 0 deletions libc/intrin/describeallocationtype.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2024 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/describeflags.h"
#include "libc/macros.h"
#include "libc/nt/enum/memflags.h"

static const struct DescribeFlags kNtAllocationTypeFlags[] = {
{kNtMemCommit, "Commit"}, //
{kNtMemReserve, "Reserve"}, //
{kNtMemReset, "Reset"}, //
};

const char *_DescribeNtAllocationType(char buf[48], uint32_t x) {
return _DescribeFlags(buf, 48, kNtAllocationTypeFlags,
ARRAYLEN(kNtAllocationTypeFlags), "kNtMem", x);
}
2 changes: 2 additions & 0 deletions libc/intrin/describeflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const char *_DescribeMapping(char[8], int, int) libcesque;
const char *_DescribeMremapFlags(char[30], int) libcesque;
const char *_DescribeMsg(char[16], int) libcesque;
const char *_DescribeMsyncFlags(char[48], int) libcesque;
const char *_DescribeNtAllocationType(char[48], uint32_t);
const char *_DescribeNtConsoleInFlags(char[256], uint32_t) libcesque;
const char *_DescribeNtConsoleOutFlags(char[128], uint32_t) libcesque;
const char *_DescribeNtCreationDisposition(uint32_t) libcesque;
Expand Down Expand Up @@ -87,6 +88,7 @@ const char *_DescribeWhichPrio(char[12], int) libcesque;
#define DescribeMremapFlags(x) _DescribeMremapFlags(alloca(30), x)
#define DescribeMsg(x) _DescribeMsg(alloca(16), x)
#define DescribeMsyncFlags(x) _DescribeMsyncFlags(alloca(48), x)
#define DescribeNtAllocationType(x) _DescribeNtAllocationType(alloca(48), x)
#define DescribeNtConsoleInFlags(x) _DescribeNtConsoleInFlags(alloca(256), x)
#define DescribeNtConsoleOutFlags(x) _DescribeNtConsoleOutFlags(alloca(128), x)
#define DescribeNtFileAccessFlags(x) _DescribeNtFileAccessFlags(alloca(512), x)
Expand Down
27 changes: 8 additions & 19 deletions libc/intrin/directmap-metal.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/metalfile.internal.h"
#include "libc/intrin/directmap.h"
#include "libc/macros.h"
#include "libc/runtime/pc.internal.h"
#include "libc/str/str.h"
Expand All @@ -32,19 +31,11 @@

static uint64_t sys_mmap_metal_break;

static struct DirectMap bad_mmap(void) {
struct DirectMap res;
res.addr = (void *)-1;
res.maphandle = -1;
return res;
}

struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot, int flags,
int fd, int64_t off) {
void *sys_mmap_metal(void *vaddr, size_t size, int prot, int flags, int fd,
int64_t off) {
/* asan runtime depends on this function */
size_t i;
struct mman *mm;
struct DirectMap res;
uint64_t addr, faddr = 0, page, e, *pte, *fdpte, *pml4t;
mm = __get_mm();
pml4t = __get_pml4t();
Expand All @@ -54,18 +45,18 @@ struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot, int flags,
struct Fd *sfd;
struct MetalFile *file;
if (off < 0 || fd < 0 || fd >= g_fds.n)
return bad_mmap();
return MAP_FAILED;
sfd = &g_fds.p[fd];
if (sfd->kind != kFdFile)
return bad_mmap();
return MAP_FAILED;
file = (struct MetalFile *)sfd->handle;
/* TODO: allow mapping partial page at end of file, if file size not
* multiple of page size */
if (off > file->size || size > file->size - off)
return bad_mmap();
return MAP_FAILED;
faddr = (uint64_t)file->base + off;
if (faddr % 4096 != 0)
return bad_mmap();
return MAP_FAILED;
}
if (!(flags & MAP_FIXED_linux)) {
if (!addr) {
Expand All @@ -88,7 +79,7 @@ struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot, int flags,
if ((flags & MAP_ANONYMOUS_linux)) {
page = __new_page(mm);
if (!page)
return bad_mmap();
return MAP_FAILED;
__clear_page(BANE + page);
e = page | PAGE_RSRV | PAGE_U;
if ((prot & PROT_WRITE))
Expand All @@ -114,9 +105,7 @@ struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot, int flags,
break;
}
}
res.addr = (void *)addr;
res.maphandle = -1;
return res;
return (void *)addr;
}

#endif /* __x86_64__ */
122 changes: 0 additions & 122 deletions libc/intrin/directmap-nt.c

This file was deleted.

67 changes: 0 additions & 67 deletions libc/intrin/directmap.c

This file was deleted.

Loading

0 comments on commit 42a3bb7

Please sign in to comment.