mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Avoid leaking handles across processes
This commit is contained in:
parent
a359de7893
commit
8a0008d985
44 changed files with 232 additions and 266 deletions
|
@ -61,7 +61,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
|||
handle = g_fds.p[oldfd].handle;
|
||||
proc = GetCurrentProcess();
|
||||
|
||||
if (DuplicateHandle(proc, handle, proc, &g_fds.p[newfd].handle, 0, true,
|
||||
if (DuplicateHandle(proc, handle, proc, &g_fds.p[newfd].handle, 0, false,
|
||||
kNtDuplicateSameAccess)) {
|
||||
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
|
||||
g_fds.p[newfd].mode = g_fds.p[oldfd].mode;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/struct/sigaction.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include "libc/nt/enum/threadaccess.h"
|
||||
#include "libc/nt/enum/wait.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
|
@ -65,6 +67,7 @@
|
|||
|
||||
// clang-format off
|
||||
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
|
||||
__msabi extern typeof(DuplicateHandle) *const __imp_DuplicateHandle;
|
||||
__msabi extern typeof(ExitProcess) *const __imp_ExitProcess;
|
||||
__msabi extern typeof(GenerateConsoleCtrlEvent) *const __imp_GenerateConsoleCtrlEvent;
|
||||
__msabi extern typeof(GetCurrentThreadId) *const __imp_GetCurrentThreadId;
|
||||
|
@ -72,6 +75,7 @@ __msabi extern typeof(GetExitCodeProcess) *const __imp_GetExitCodeProcess;
|
|||
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
|
||||
__msabi extern typeof(OpenThread) *const __imp_OpenThread;
|
||||
__msabi extern typeof(SetConsoleCtrlHandler) *const __imp_SetConsoleCtrlHandler;
|
||||
__msabi extern typeof(SetHandleInformation) *const __imp_SetHandleInformation;
|
||||
__msabi extern typeof(TerminateThread) *const __imp_TerminateThread;
|
||||
__msabi extern typeof(UnmapViewOfFile) *const __imp_UnmapViewOfFile;
|
||||
__msabi extern typeof(WaitForSingleObject) *const __imp_WaitForSingleObject;
|
||||
|
@ -171,23 +175,6 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
|
|||
PurgeThread(*_weaken(__sigchld_thread));
|
||||
PurgeThread(*_weaken(__sigwinch_thread));
|
||||
|
||||
// close win32 handles for memory mappings
|
||||
// unlike fork calling execve destroys all memory
|
||||
// closing a map handle won't impact the mapping itself
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
PurgeHandle(_mmi.p[i].h);
|
||||
}
|
||||
|
||||
// close o_cloexec fds and anything that isn't stdio
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind == kFdEmpty) {
|
||||
g_fds.p[i].handle = -1;
|
||||
} else if (i > 2 || (g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
PurgeHandle(g_fds.p[i].handle);
|
||||
g_fds.p[i].handle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// pass bitmask telling child which fds are sockets
|
||||
int bits;
|
||||
char buf[32], *v = 0;
|
||||
|
@ -205,10 +192,16 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
|
|||
struct NtStartupInfo si = {
|
||||
.cb = sizeof(struct NtStartupInfo),
|
||||
.dwFlags = kNtStartfUsestdhandles,
|
||||
.hStdInput = g_fds.p[0].handle,
|
||||
.hStdOutput = g_fds.p[1].handle,
|
||||
.hStdError = g_fds.p[2].handle,
|
||||
};
|
||||
for (i = 0; i <= 2; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty && //
|
||||
!(g_fds.p[i].flags & O_CLOEXEC)) {
|
||||
__imp_SetHandleInformation(g_fds.p[i].handle, kNtHandleFlagInherit, true);
|
||||
si.stdiofds[i] = g_fds.p[i].handle;
|
||||
} else {
|
||||
si.stdiofds[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// launch the process
|
||||
struct NtProcessInformation pi;
|
||||
|
@ -223,6 +216,11 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
|
|||
}
|
||||
PurgeHandle(pi.hThread);
|
||||
|
||||
// remove duplicate handles
|
||||
for (i = 0; i <= 2; ++i) {
|
||||
PurgeHandle(si.stdiofds[i]);
|
||||
}
|
||||
|
||||
// retreat to original win32-provided stack memory
|
||||
__switch_stacks(pi.hProcess, 0, 0, 0, sys_execve_nt_relay, __oldstack);
|
||||
}
|
||||
|
@ -240,19 +238,25 @@ static keywords void sys_execve_nt_relay(intptr_t h, long b, long c, long d) {
|
|||
|
||||
// close more handles
|
||||
__imp_SetConsoleCtrlHandler((void *)sys_execve_nt_event, 1);
|
||||
PurgeThread(g_fds.stdin.thread); // wasn't inherited by ntspawn
|
||||
PurgeHandle(g_fds.stdin.reader); // wasn't inherited by ntspawn
|
||||
PurgeHandle(g_fds.stdin.writer); // wasn't inherited by ntspawn
|
||||
PurgeHandle(g_fds.p[0].handle); // was inherited via startinfo
|
||||
PurgeHandle(g_fds.p[1].handle); // was inherited via startinfo
|
||||
PurgeHandle(g_fds.p[2].handle); // was inherited via startinfo
|
||||
PurgeThread(g_fds.stdin.thread);
|
||||
PurgeHandle(g_fds.stdin.reader);
|
||||
PurgeHandle(g_fds.stdin.writer);
|
||||
for (i = 0; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind != kFdEmpty) {
|
||||
PurgeHandle(g_fds.p[i].handle);
|
||||
if (g_fds.p[i].kind == kFdConsole) {
|
||||
PurgeHandle(g_fds.p[i].extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_weaken(__klog_handle)) {
|
||||
PurgeHandle(*_weaken(__klog_handle)); // wasn't inherited by ntspawn
|
||||
PurgeHandle(*_weaken(__klog_handle));
|
||||
}
|
||||
|
||||
// free all the memory mmap created
|
||||
for (i = 0; i < _mmi.i; ++i) {
|
||||
__imp_UnmapViewOfFile((void *)((uintptr_t)_mmi.p[i].x << 16));
|
||||
PurgeHandle(_mmi.p[i].h);
|
||||
}
|
||||
|
||||
// wait for process to terminate
|
||||
|
|
|
@ -130,12 +130,11 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
|
|||
|
||||
// open the file, following symlinks
|
||||
int e = errno;
|
||||
int64_t hand = CreateFile(path16, perm | extra_perm, share, &kNtIsInheritable,
|
||||
disp, attr | extra_attr, 0);
|
||||
int64_t hand = CreateFile(path16, perm | extra_perm, share, 0, disp,
|
||||
attr | extra_attr, 0);
|
||||
if (hand == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
|
||||
errno = e;
|
||||
hand = CreateFile(path16, perm, share, &kNtIsInheritable, disp,
|
||||
attr | extra_attr, 0);
|
||||
hand = CreateFile(path16, perm, share, 0, disp, attr | extra_attr, 0);
|
||||
}
|
||||
|
||||
return __fix_enotdir(hand, path16);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/handlock.internal.h"
|
||||
#include "libc/nt/createfile.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
|
@ -52,11 +53,11 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
|
|||
}
|
||||
__fds_unlock();
|
||||
hin = CreateNamedPipe(pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped,
|
||||
mode, 1, PIPE_BUF, PIPE_BUF, 0, &kNtIsInheritable);
|
||||
mode, 1, PIPE_BUF, PIPE_BUF, 0, 0);
|
||||
__fds_lock();
|
||||
if (hin != -1) {
|
||||
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, &kNtIsInheritable,
|
||||
kNtOpenExisting, kNtFileFlagOverlapped, 0)) != -1) {
|
||||
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, 0, kNtOpenExisting,
|
||||
kNtFileFlagOverlapped, 0)) != -1) {
|
||||
g_fds.p[reader].kind = kFdFile;
|
||||
g_fds.p[reader].flags = O_RDONLY | flags;
|
||||
g_fds.p[reader].mode = 0010444;
|
||||
|
|
|
@ -33,8 +33,8 @@ textwindows int sys_statfs_nt(const char *path, struct statfs *sf) {
|
|||
if (__mkntpath(path, path16) == -1) return -1;
|
||||
h = __fix_enotdir(
|
||||
CreateFile(path16, kNtFileGenericRead,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
||||
&kNtIsInheritable, kNtOpenExisting,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
|
||||
kNtOpenExisting,
|
||||
kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0),
|
||||
path16);
|
||||
if (h == -1) return -1;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* @see System Five Application Binary Interface § 3.4.3
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan struct AuxiliaryValue __getauxval(unsigned long at) {
|
||||
struct AuxiliaryValue __getauxval(unsigned long at) {
|
||||
unsigned long *ap;
|
||||
for (ap = __auxv; ap[0]; ap += 2) {
|
||||
if (at == ap[0]) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#define ToUpper(c) \
|
||||
(IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
|
||||
|
||||
dontasan privileged struct Env __getenv(char **p, const char *k) {
|
||||
privileged struct Env __getenv(char **p, const char *k) {
|
||||
char *t;
|
||||
int i, j;
|
||||
for (i = 0; (t = p[i]); ++i) {
|
||||
|
|
|
@ -773,7 +773,7 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
|
|||
}
|
||||
}
|
||||
|
||||
static dontasan void __asan_onmemory(void *x, void *y, size_t n, void *a) {
|
||||
static void __asan_onmemory(void *x, void *y, size_t n, void *a) {
|
||||
const unsigned char *p = x;
|
||||
struct ReportOriginHeap *t = a;
|
||||
if ((p <= t->a && t->a < p + n) ||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
|
||||
|
||||
dontinstrument dontasan const char *(DescribeBacktrace)(char buf[N],
|
||||
struct StackFrame *fr) {
|
||||
dontinstrument const char *(DescribeBacktrace)(char buf[N],
|
||||
struct StackFrame *fr) {
|
||||
bool gotsome = false;
|
||||
char *p = buf;
|
||||
char *pe = p + N;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
const char *(
|
||||
DescribeNtSecurityAttributes)(char buf[32],
|
||||
const struct NtSecurityAttributes *p) {
|
||||
if (p == &kNtIsInheritable) return "&kNtIsInheritable";
|
||||
FormatInt64(buf, (uintptr_t)p);
|
||||
return buf;
|
||||
}
|
||||
|
|
|
@ -32,15 +32,15 @@
|
|||
|
||||
static uint64_t sys_mmap_metal_break;
|
||||
|
||||
dontasan static struct DirectMap bad_mmap(void) {
|
||||
static struct DirectMap bad_mmap(void) {
|
||||
struct DirectMap res;
|
||||
res.addr = (void *)-1;
|
||||
res.maphandle = -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
dontasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot,
|
||||
int flags, int fd, int64_t off) {
|
||||
struct DirectMap 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;
|
||||
|
|
|
@ -42,13 +42,6 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
handle = g_fds.p[fd].handle;
|
||||
}
|
||||
|
||||
const struct NtSecurityAttributes *sec;
|
||||
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||
sec = 0; // MAP_PRIVATE isn't inherited across fork()
|
||||
} else {
|
||||
sec = &kNtIsInheritable; // MAP_SHARED gives us zero-copy fork()
|
||||
}
|
||||
|
||||
// nt will whine under many circumstances if we change the execute bit
|
||||
// later using mprotect(). the workaround is to always request execute
|
||||
// and then virtualprotect() it away until we actually need it. please
|
||||
|
@ -80,7 +73,7 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
int e = errno;
|
||||
struct DirectMap dm;
|
||||
TryAgain:
|
||||
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1,
|
||||
if ((dm.maphandle = CreateFileMapping(handle, 0, fl.flags1,
|
||||
(size + off) >> 32, (size + off), 0))) {
|
||||
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
|
||||
size, addr))) {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#define G FRAMESIZE
|
||||
|
||||
static dontasan void *_mapframe(void *p, int f) {
|
||||
static void *_mapframe(void *p, int f) {
|
||||
int rc, prot, flags;
|
||||
struct DirectMap dm;
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
|
@ -73,7 +73,7 @@ static dontasan void *_mapframe(void *p, int f) {
|
|||
* @return new value for `e` or null w/ errno
|
||||
* @raise ENOMEM if we require more vespene gas
|
||||
*/
|
||||
dontasan void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
|
||||
void *_extend(void *p, size_t n, void *e, int f, intptr_t h) {
|
||||
char *q;
|
||||
unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
|
||||
unassert((uintptr_t)p + (G << kAsanScale) <= h);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
dontasan unsigned __find_memory(const struct MemoryIntervals *mm, int x) {
|
||||
unsigned __find_memory(const struct MemoryIntervals *mm, int x) {
|
||||
unsigned l, m, r;
|
||||
l = 0;
|
||||
r = mm->i;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @param delta is added to enabled state
|
||||
* @return enabled state before `delta` was applied
|
||||
*/
|
||||
dontasan dontubsan dontinstrument int ftrace_enabled(int delta) {
|
||||
dontinstrument int ftrace_enabled(int delta) {
|
||||
int res;
|
||||
struct CosmoTib *tib;
|
||||
if (__tls_enabled) {
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* @threadsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
dontasan int getpid(void) {
|
||||
int getpid(void) {
|
||||
int rc;
|
||||
if (IsMetal()) {
|
||||
rc = 1;
|
||||
|
|
62
libc/intrin/handlock.c
Normal file
62
libc/intrin/handlock.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*-*- 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 2023 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/dce.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "third_party/nsync/mu.h"
|
||||
|
||||
/**
|
||||
* @fileoverview r/w lock for maanging windows file inheritence
|
||||
*/
|
||||
|
||||
static nsync_mu __hand_mu;
|
||||
|
||||
void __hand_init(void) {
|
||||
if (!SupportsWindows()) return;
|
||||
bzero(&__hand_mu, sizeof(__hand_mu));
|
||||
}
|
||||
|
||||
void __hand_rlock(void) {
|
||||
if (!IsWindows()) return;
|
||||
if (_weaken(nsync_mu_rlock) && __threaded) {
|
||||
_weaken(nsync_mu_rlock)(&__hand_mu);
|
||||
}
|
||||
}
|
||||
|
||||
void __hand_runlock(void) {
|
||||
if (!IsWindows()) return;
|
||||
if (_weaken(nsync_mu_runlock) && __threaded) {
|
||||
_weaken(nsync_mu_runlock)(&__hand_mu);
|
||||
}
|
||||
}
|
||||
|
||||
void __hand_lock(void) {
|
||||
if (!IsWindows()) return;
|
||||
if (_weaken(nsync_mu_lock) && __threaded) {
|
||||
_weaken(nsync_mu_lock)(&__hand_mu);
|
||||
}
|
||||
}
|
||||
|
||||
void __hand_unlock(void) {
|
||||
if (!IsWindows()) return;
|
||||
if (_weaken(nsync_mu_unlock) && __threaded) {
|
||||
_weaken(nsync_mu_unlock)(&__hand_mu);
|
||||
}
|
||||
}
|
14
libc/intrin/handlock.internal.h
Normal file
14
libc/intrin/handlock.internal.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_HANDLOCK_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_HANDLOCK_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
void __hand_init(void);
|
||||
void __hand_rlock(void);
|
||||
void __hand_runlock(void);
|
||||
void __hand_lock(void);
|
||||
void __hand_unlock(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_HANDLOCK_INTERNAL_H_ */
|
|
@ -46,31 +46,11 @@ $(LIBC_INTRIN_A).pkg: \
|
|||
$(LIBC_INTRIN_A_OBJS) \
|
||||
$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
# we can't use asan because:
|
||||
# __strace_init() calls this before asan is initialized
|
||||
o/$(MODE)/libc/intrin/strace_enabled.o: private \
|
||||
COPTS += \
|
||||
-fno-sanitize=address
|
||||
o/$(MODE)/libc/intrin/mman.greg.o: private COPTS += -Os
|
||||
|
||||
# we can't use asan because:
|
||||
# asan guard pages haven't been allocated yet
|
||||
o/$(MODE)/libc/intrin/directmap.o \
|
||||
o/$(MODE)/libc/intrin/directmap-nt.o: private \
|
||||
COPTS += \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=address
|
||||
|
||||
# we want small code size because:
|
||||
# to keep .text.head under 4096 bytes
|
||||
o/$(MODE)/libc/intrin/mman.greg.o: private \
|
||||
COPTS += \
|
||||
-Os
|
||||
|
||||
# we can't use asan and ubsan because:
|
||||
# this is asan and ubsan
|
||||
o/$(MODE)/libc/intrin/asan.o \
|
||||
o/$(MODE)/libc/intrin/ubsan.o: private \
|
||||
$(LIBC_INTRIN_A_OBJS): private \
|
||||
CFLAGS += \
|
||||
-x-no-pg \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector
|
||||
|
@ -81,121 +61,6 @@ o/$(MODE)/libc/intrin/asan.o: private \
|
|||
-finline \
|
||||
-finline-functions
|
||||
|
||||
o/$(MODE)/libc/intrin/asanthunk.o: private \
|
||||
CFLAGS += \
|
||||
-x-no-pg \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector
|
||||
|
||||
# we can't use compiler magic because:
|
||||
# kprintf() is mission critical to error reporting
|
||||
o/$(MODE)/libc/intrin/getmagnumstr.greg.o \
|
||||
o/$(MODE)/libc/intrin/strerrno.greg.o \
|
||||
o/$(MODE)/libc/intrin/strerrdoc.greg.o \
|
||||
o/$(MODE)/libc/intrin/strerror_wr.greg.o \
|
||||
o/$(MODE)/libc/intrin/kprintf.greg.o: private \
|
||||
CFLAGS += \
|
||||
-fpie \
|
||||
-fwrapv \
|
||||
-x-no-pg \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=all \
|
||||
-fno-stack-protector
|
||||
|
||||
# TODO(jart): Do we really need these?
|
||||
# synchronization primitives are intended to be magic free
|
||||
o/$(MODE)/libc/intrin/futex_wait.o \
|
||||
o/$(MODE)/libc/intrin/futex_wake.o \
|
||||
o/$(MODE)/libc/intrin/gettid.greg.o \
|
||||
o/$(MODE)/libc/intrin/_trylock_debug_4.o \
|
||||
o/$(MODE)/libc/intrin/_spinlock_debug_4.o: private \
|
||||
CFLAGS += \
|
||||
-fwrapv \
|
||||
-x-no-pg \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=all \
|
||||
-mgeneral-regs-only \
|
||||
-fno-stack-protector
|
||||
|
||||
# we can't use asan because:
|
||||
# global gone could be raised
|
||||
o/$(MODE)/libc/intrin/exit.o \
|
||||
o/$(MODE)/libc/intrin/restorewintty.o: private \
|
||||
CFLAGS += \
|
||||
-fno-sanitize=all
|
||||
|
||||
# we can't use -ftrapv because:
|
||||
# this file implements it
|
||||
o/$(MODE)/libc/intrin/ftrapv.o: private \
|
||||
CFLAGS += \
|
||||
-ffunction-sections \
|
||||
-ffreestanding \
|
||||
-fwrapv
|
||||
|
||||
# we can't use asan because:
|
||||
# sys_mmap() calls these which sets up shadow memory
|
||||
o/$(MODE)/libc/intrin/describeflags.o \
|
||||
o/$(MODE)/libc/intrin/describeframe.o \
|
||||
o/$(MODE)/libc/intrin/describemapflags.o \
|
||||
o/$(MODE)/libc/intrin/describeprotflags.o: private \
|
||||
CFLAGS += \
|
||||
-fno-sanitize=address
|
||||
|
||||
o/$(MODE)/libc/intrin/exit1.greg.o \
|
||||
o/$(MODE)/libc/intrin/wsarecv.o \
|
||||
o/$(MODE)/libc/intrin/wsarecvfrom.o \
|
||||
o/$(MODE)/libc/intrin/createfile.o \
|
||||
o/$(MODE)/libc/intrin/reopenfile.o \
|
||||
o/$(MODE)/libc/intrin/deletefile.o \
|
||||
o/$(MODE)/libc/intrin/createpipe.o \
|
||||
o/$(MODE)/libc/intrin/closehandle.o \
|
||||
o/$(MODE)/libc/intrin/openprocess.o \
|
||||
o/$(MODE)/libc/intrin/createthread.o \
|
||||
o/$(MODE)/libc/intrin/findclose.o \
|
||||
o/$(MODE)/libc/intrin/findnextfile.o \
|
||||
o/$(MODE)/libc/intrin/createprocess.o \
|
||||
o/$(MODE)/libc/intrin/findfirstfile.o \
|
||||
o/$(MODE)/libc/intrin/removedirectory.o \
|
||||
o/$(MODE)/libc/intrin/createsymboliclink.o \
|
||||
o/$(MODE)/libc/intrin/createnamedpipe.o \
|
||||
o/$(MODE)/libc/intrin/unmapviewoffile.o \
|
||||
o/$(MODE)/libc/intrin/virtualprotect.o \
|
||||
o/$(MODE)/libc/intrin/flushviewoffile.o \
|
||||
o/$(MODE)/libc/intrin/createdirectory.o \
|
||||
o/$(MODE)/libc/intrin/flushfilebuffers.o \
|
||||
o/$(MODE)/libc/intrin/terminateprocess.o \
|
||||
o/$(MODE)/libc/intrin/getfileattributes.o \
|
||||
o/$(MODE)/libc/intrin/getexitcodeprocess.o \
|
||||
o/$(MODE)/libc/intrin/waitforsingleobject.o \
|
||||
o/$(MODE)/libc/intrin/setcurrentdirectory.o \
|
||||
o/$(MODE)/libc/intrin/mapviewoffileex.o \
|
||||
o/$(MODE)/libc/intrin/movefileex.o \
|
||||
o/$(MODE)/libc/intrin/mapviewoffileexnuma.o \
|
||||
o/$(MODE)/libc/intrin/createfilemapping.o \
|
||||
o/$(MODE)/libc/intrin/createfilemappingnuma.o \
|
||||
o/$(MODE)/libc/intrin/waitformultipleobjects.o \
|
||||
o/$(MODE)/libc/intrin/wsagetoverlappedresult.o \
|
||||
o/$(MODE)/libc/intrin/generateconsolectrlevent.o \
|
||||
o/$(MODE)/libc/intrin/wsawaitformultipleevents.o: private\
|
||||
CFLAGS += \
|
||||
-Os \
|
||||
-fwrapv \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-sanitize=all
|
||||
|
||||
# privileged functions
|
||||
o/$(MODE)/libc/intrin/dos2errno.o \
|
||||
o/$(MODE)/libc/intrin/have_fsgsbase.o \
|
||||
o/$(MODE)/libc/intrin/getmagnumstr.o \
|
||||
o/$(MODE)/libc/intrin/formatint32.o \
|
||||
o/$(MODE)/libc/intrin/strsignal_r.o \
|
||||
o/$(MODE)/libc/intrin/strerror_wr.o: private \
|
||||
CFLAGS += \
|
||||
-ffreestanding \
|
||||
-fno-sanitize=all
|
||||
|
||||
o//libc/intrin/memmove.o: private \
|
||||
CFLAGS += \
|
||||
-fno-toplevel-reorder
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define kBufSize 1024
|
||||
#define kPid "TracerPid:\t"
|
||||
|
||||
static textwindows dontasan bool IsBeingDebugged(void) {
|
||||
static textwindows bool IsBeingDebugged(void) {
|
||||
return !!NtGetPeb()->BeingDebugged;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,8 @@ static inline const unsigned char *memchr_pure(const unsigned char *s,
|
|||
}
|
||||
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
dontasan static inline const unsigned char *memchr_sse(const unsigned char *s,
|
||||
unsigned char c,
|
||||
size_t n) {
|
||||
static inline const unsigned char *memchr_sse(const unsigned char *s,
|
||||
unsigned char c, size_t n) {
|
||||
size_t i;
|
||||
unsigned m;
|
||||
xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
||||
|
@ -68,7 +67,7 @@ dontasan static inline const unsigned char *memchr_sse(const unsigned char *s,
|
|||
* @return is pointer to first instance of c or NULL if not found
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan void *memchr(const void *s, int c, size_t n) {
|
||||
void *memchr(const void *s, int c, size_t n) {
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
const void *r;
|
||||
if (IsAsan()) __asan_verify(s, n);
|
||||
|
|
|
@ -37,9 +37,8 @@ static inline const unsigned char *memrchr_pure(const unsigned char *s,
|
|||
}
|
||||
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
dontasan static inline const unsigned char *memrchr_sse(const unsigned char *s,
|
||||
unsigned char c,
|
||||
size_t n) {
|
||||
static inline const unsigned char *memrchr_sse(const unsigned char *s,
|
||||
unsigned char c, size_t n) {
|
||||
size_t i;
|
||||
unsigned m;
|
||||
xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
|
||||
|
|
|
@ -54,7 +54,7 @@ struct ReclaimedPage {
|
|||
/**
|
||||
* Allocates new page of physical memory.
|
||||
*/
|
||||
dontasan texthead uint64_t __new_page(struct mman *mm) {
|
||||
texthead uint64_t __new_page(struct mman *mm) {
|
||||
uint64_t p = mm->frp;
|
||||
if (p != NOPAGE) {
|
||||
uint64_t q;
|
||||
|
@ -81,8 +81,8 @@ dontasan texthead uint64_t __new_page(struct mman *mm) {
|
|||
* Returns pointer to page table entry for page at virtual address.
|
||||
* Additional page tables are allocated if needed as a side-effect.
|
||||
*/
|
||||
dontasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
|
||||
int64_t vaddr, bool maketables) {
|
||||
textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t, int64_t vaddr,
|
||||
bool maketables) {
|
||||
uint64_t *e, p;
|
||||
unsigned char h;
|
||||
for (h = 39;; h -= 9) {
|
||||
|
@ -101,7 +101,7 @@ dontasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
|
|||
/**
|
||||
* Sorts, rounds, and filters BIOS memory map.
|
||||
*/
|
||||
static dontasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
||||
static textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
||||
uint64_t a, b;
|
||||
uint64_t x, y;
|
||||
unsigned i, j, n;
|
||||
|
@ -134,10 +134,9 @@ static dontasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
|||
/**
|
||||
* Identity maps an area of physical memory to its negative address.
|
||||
*/
|
||||
dontasan textreal uint64_t *__invert_memory_area(struct mman *mm,
|
||||
uint64_t *pml4t, uint64_t ps,
|
||||
uint64_t size,
|
||||
uint64_t pte_flags) {
|
||||
textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t,
|
||||
uint64_t ps, uint64_t size,
|
||||
uint64_t pte_flags) {
|
||||
uint64_t pe = ps + size, p, *m = NULL;
|
||||
ps = ROUNDDOWN(ps, 4096);
|
||||
pe = ROUNDUP(pe, 4096);
|
||||
|
@ -153,7 +152,7 @@ dontasan textreal uint64_t *__invert_memory_area(struct mman *mm,
|
|||
/**
|
||||
* Increments the reference count for a page of physical memory.
|
||||
*/
|
||||
dontasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
uint64_t *m, e;
|
||||
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
|
||||
if (m) {
|
||||
|
@ -168,8 +167,7 @@ dontasan void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
|||
/**
|
||||
* Increments the reference counts for an area of physical memory.
|
||||
*/
|
||||
dontasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
|
||||
uint64_t size) {
|
||||
void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps, uint64_t size) {
|
||||
uint64_t p = ROUNDDOWN(ps, 4096), e = ROUNDUP(ps + size, 4096);
|
||||
while (p != e) {
|
||||
__ref_page(mm, pml4t, p);
|
||||
|
@ -180,7 +178,7 @@ dontasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps,
|
|||
/**
|
||||
* Reclaims a page of physical memory for later use.
|
||||
*/
|
||||
static dontasan void __reclaim_page(struct mman *mm, uint64_t p) {
|
||||
static void __reclaim_page(struct mman *mm, uint64_t p) {
|
||||
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
|
||||
unassert(p == (p & PAGE_TA));
|
||||
rp->next = mm->frp;
|
||||
|
@ -192,7 +190,7 @@ static dontasan void __reclaim_page(struct mman *mm, uint64_t p) {
|
|||
* page if there are no virtual addresses (excluding the negative space)
|
||||
* referring to it.
|
||||
*/
|
||||
dontasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
||||
uint64_t *m, e;
|
||||
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
|
||||
if (m) {
|
||||
|
@ -208,8 +206,7 @@ dontasan void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) {
|
|||
/**
|
||||
* Identity maps all usable physical memory to its negative address.
|
||||
*/
|
||||
static dontasan textreal void __invert_memory(struct mman *mm,
|
||||
uint64_t *pml4t) {
|
||||
static textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
|
||||
uint64_t i;
|
||||
for (i = 0; i < mm->e820n; ++i) {
|
||||
uint64_t ps = mm->e820[i].addr, size = mm->e820[i].size;
|
||||
|
@ -232,8 +229,7 @@ static dontasan textreal void __invert_memory(struct mman *mm,
|
|||
: "i"(offsetof(type, member))); \
|
||||
} while (0)
|
||||
|
||||
dontasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
||||
uint64_t top) {
|
||||
textreal void __setup_mman(struct mman *mm, uint64_t *pml4t, uint64_t top) {
|
||||
export_offsetof(struct mman, pc_drive_base_table);
|
||||
export_offsetof(struct mman, pc_drive_last_sector);
|
||||
export_offsetof(struct mman, pc_drive_last_head);
|
||||
|
@ -259,8 +255,8 @@ dontasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
|||
/**
|
||||
* Maps APE-defined ELF program headers into memory and clears BSS.
|
||||
*/
|
||||
dontasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
||||
uint64_t top) {
|
||||
textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
||||
uint64_t top) {
|
||||
uint64_t i, f, v, m;
|
||||
struct Elf64_Phdr *p;
|
||||
extern char ape_phdrs[] __attribute__((__weak__));
|
||||
|
@ -294,9 +290,8 @@ dontasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
|||
* Reclaims memory pages which were used at boot time but which can now be
|
||||
* made available for the application.
|
||||
*/
|
||||
dontasan textreal void __reclaim_boot_pages(struct mman *mm,
|
||||
uint64_t skip_start,
|
||||
uint64_t skip_end) {
|
||||
textreal void __reclaim_boot_pages(struct mman *mm, uint64_t skip_start,
|
||||
uint64_t skip_end) {
|
||||
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, i, n = mm->e820n, b, e;
|
||||
for (i = 0; i < n; ++i) {
|
||||
b = mm->e820[i].addr;
|
||||
|
|
|
@ -48,9 +48,8 @@
|
|||
*/
|
||||
bool __nocolor;
|
||||
|
||||
optimizesize textstartup dontasan void __nocolor_init(int argc, char **argv,
|
||||
char **envp,
|
||||
intptr_t *auxv) {
|
||||
optimizesize textstartup void __nocolor_init(int argc, char **argv, char **envp,
|
||||
intptr_t *auxv) {
|
||||
char *s;
|
||||
__nocolor = (IsWindows() && !IsAtLeastWindows10()) ||
|
||||
((s = getenv("TERM")) && IsDumb(s));
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
*
|
||||
* @see IsAtLeastWindows10()
|
||||
*/
|
||||
textwindows dontasan int NtGetVersion(void) {
|
||||
textwindows int NtGetVersion(void) {
|
||||
return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
|||
* @return pointer to nul byte
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan char *stpcpy(char *d, const char *s) {
|
||||
char *stpcpy(char *d, const char *s) {
|
||||
size_t i = 0;
|
||||
if (IsAsan()) {
|
||||
__asan_verify(d, strlen(s) + 1);
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#define _KERNTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _POLLTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _DATATRACE 1 /* not configurable w/ flag yet */
|
||||
#define _STDIOTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _LOCKTRACE 0 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 1 /* not configurable w/ flag yet */
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
|
||||
#define STRACE_PROLOGUE "%rSYS %6P %'18T "
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @param delta is added to enabled state
|
||||
* @return enabled state before `delta` was applied
|
||||
*/
|
||||
dontasan dontubsan dontinstrument int strace_enabled(int delta) {
|
||||
dontinstrument int strace_enabled(int delta) {
|
||||
int res;
|
||||
struct CosmoTib *tib;
|
||||
if (__tls_enabled) {
|
||||
|
|
|
@ -32,7 +32,7 @@ static inline const char *strchr_pure(const char *s, int c) {
|
|||
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
dontasan static inline const char *strchr_sse(const char *s, unsigned char c) {
|
||||
static inline const char *strchr_sse(const char *s, unsigned char c) {
|
||||
unsigned k;
|
||||
unsigned m;
|
||||
const xmm_t *p;
|
||||
|
@ -56,7 +56,7 @@ dontasan static inline const char *strchr_sse(const char *s, unsigned char c) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static dontasan inline const char *strchr_x64(const char *p, uint64_t c) {
|
||||
static inline const char *strchr_x64(const char *p, uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
|
@ -95,7 +95,7 @@ static dontasan inline const char *strchr_x64(const char *p, uint64_t c) {
|
|||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
dontasan char *strchr(const char *s, int c) {
|
||||
char *strchr(const char *s, int c) {
|
||||
if (IsAsan()) __asan_verify_str(s);
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
const char *r;
|
||||
|
|
|
@ -32,8 +32,7 @@ static inline const char *strchrnul_pure(const char *s, int c) {
|
|||
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
dontasan static inline const char *strchrnul_sse(const char *s,
|
||||
unsigned char c) {
|
||||
static inline const char *strchrnul_sse(const char *s, unsigned char c) {
|
||||
unsigned k;
|
||||
unsigned m;
|
||||
const xmm_t *p;
|
||||
|
@ -54,7 +53,7 @@ dontasan static inline const char *strchrnul_sse(const char *s,
|
|||
}
|
||||
#endif
|
||||
|
||||
dontasan static const char *strchrnul_x64(const char *p, uint64_t c) {
|
||||
static const char *strchrnul_x64(const char *p, uint64_t c) {
|
||||
unsigned a, b;
|
||||
uint64_t w, x, y;
|
||||
for (c *= 0x0101010101010101;; p += 8) {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
* @return is <0, 0, or >0 based on uint8_t comparison
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan int strcmp(const char *a, const char *b) {
|
||||
int strcmp(const char *a, const char *b) {
|
||||
int c;
|
||||
size_t i = 0;
|
||||
uint64_t v, w;
|
||||
|
|
|
@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
|||
* @return original dest
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan char *strcpy(char *d, const char *s) {
|
||||
char *strcpy(char *d, const char *s) {
|
||||
size_t i = 0;
|
||||
if (IsAsan()) {
|
||||
__asan_verify_str(s);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// clang-format off
|
||||
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
dontasan dontubsan privileged
|
||||
privileged
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
// clang-format off
|
||||
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
dontasan dontubsan privileged
|
||||
privileged
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* @return number of bytes (excluding NUL)
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan size_t strlen(const char *s) {
|
||||
size_t strlen(const char *s) {
|
||||
if (IsAsan()) __asan_verify_str(s);
|
||||
#if defined(__x86_64__) && !defined(__chibicc__)
|
||||
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#ifndef __aarch64__
|
||||
|
||||
static dontasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
|
||||
static size_t strnlen_x64(const char *s, size_t n, size_t i) {
|
||||
uint64_t w;
|
||||
for (; i + 8 < n; i += 8) {
|
||||
w = *(uint64_t *)(s + i);
|
||||
|
@ -43,7 +43,7 @@ static dontasan size_t strnlen_x64(const char *s, size_t n, size_t i) {
|
|||
* @return byte length
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
dontasan size_t strnlen(const char *s, size_t n) {
|
||||
size_t strnlen(const char *s, size_t n) {
|
||||
size_t i;
|
||||
if (IsAsan() && n) __asan_verify(s, 1);
|
||||
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
|
||||
|
|
|
@ -31,6 +31,6 @@ char *strrchr(const char *s, int c) {
|
|||
return memrchr(s, c, strlen(s));
|
||||
}
|
||||
|
||||
__strong_reference(strrchr, rindex);
|
||||
__weak_reference(strrchr, rindex);
|
||||
|
||||
#endif /* __aarch64__ */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ntspawn.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/fd.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/calls/wincrash.internal.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/directmap.internal.h"
|
||||
#include "libc/intrin/handlock.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
|
@ -43,6 +45,7 @@
|
|||
#include "libc/nt/enum/processcreationflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
@ -313,6 +316,21 @@ textwindows void WinMainForked(void) {
|
|||
longjmp(jb, 1);
|
||||
}
|
||||
|
||||
static void __hand_inherit(bool32 bInherit) {
|
||||
for (int i = 0; i < _mmi.i; ++i) {
|
||||
if ((_mmi.p[i].flags & MAP_TYPE) == MAP_SHARED) {
|
||||
SetHandleInformation(_mmi.p[i].h, kNtHandleFlagInherit, bInherit);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind == kFdEmpty) continue;
|
||||
SetHandleInformation(g_fds.p[i].handle, kNtHandleFlagInherit, bInherit);
|
||||
if (g_fds.p[i].kind == kFdConsole) {
|
||||
SetHandleInformation(g_fds.p[i].extra, kNtHandleFlagInherit, bInherit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
||||
jmp_buf jb;
|
||||
uint32_t op;
|
||||
|
@ -357,8 +375,12 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
|
|||
args = args2;
|
||||
}
|
||||
#endif
|
||||
if (ntspawn(GetProgramExecutableName(), args, environ, forkvar, 0, 0,
|
||||
true, dwCreationFlags, 0, &startinfo, &procinfo) != -1) {
|
||||
__hand_inherit(true);
|
||||
int spawnrc =
|
||||
ntspawn(GetProgramExecutableName(), args, environ, forkvar, 0, 0,
|
||||
true, dwCreationFlags, 0, &startinfo, &procinfo);
|
||||
__hand_inherit(false);
|
||||
if (spawnrc != -1) {
|
||||
CloseHandle(procinfo.hThread);
|
||||
ok = WriteAll(writer, jb, sizeof(jb)) &&
|
||||
WriteAll(writer, &_mmi.i, sizeof(_mmi.i)) &&
|
||||
|
|
|
@ -127,7 +127,7 @@ __msabi static textwindows void DeduplicateStdioHandles(void) {
|
|||
int64_t h2 = __imp_GetStdHandle(kNtStdio[j]);
|
||||
if (h1 == h2) {
|
||||
int64_t h3, proc = __imp_GetCurrentProcess();
|
||||
__imp_DuplicateHandle(proc, h2, proc, &h3, 0, true,
|
||||
__imp_DuplicateHandle(proc, h2, proc, &h3, 0, false,
|
||||
kNtDuplicateSameAccess);
|
||||
__imp_SetStdHandle(kNtStdio[j], h3);
|
||||
}
|
||||
|
@ -159,11 +159,10 @@ __msabi static textwindows wontreturn void WinInit(const char16_t *cmdline) {
|
|||
_mmi.n = ARRAYLEN(_mmi.s);
|
||||
uintptr_t stackaddr = GetStaticStackAddr(0);
|
||||
size_t stacksize = GetStaticStackSize();
|
||||
__imp_MapViewOfFileEx((_mmi.p[0].h = __imp_CreateFileMappingW(
|
||||
-1, &kNtIsInheritable, kNtPageExecuteReadwrite,
|
||||
stacksize >> 32, stacksize, NULL)),
|
||||
kNtFileMapWrite | kNtFileMapExecute, 0, 0, stacksize,
|
||||
(void *)stackaddr);
|
||||
__imp_MapViewOfFileEx(
|
||||
(_mmi.p[0].h = __imp_CreateFileMappingW(
|
||||
-1, 0, kNtPageExecuteReadwrite, stacksize >> 32, stacksize, NULL)),
|
||||
kNtFileMapWrite | kNtFileMapExecute, 0, 0, stacksize, (void *)stackaddr);
|
||||
int prot = (intptr_t)ape_stack_prot;
|
||||
if (~prot & PROT_EXEC) {
|
||||
uint32_t old;
|
||||
|
@ -186,9 +185,8 @@ __msabi static textwindows wontreturn void WinInit(const char16_t *cmdline) {
|
|||
uintptr_t shallocend = ROUNDUP(shadowend, FRAMESIZE);
|
||||
uintptr_t shallocsize = shallocend - shallocaddr;
|
||||
__imp_MapViewOfFileEx(
|
||||
(_mmi.p[1].h =
|
||||
__imp_CreateFileMappingW(-1, &kNtIsInheritable, kNtPageReadwrite,
|
||||
shallocsize >> 32, shallocsize, NULL)),
|
||||
(_mmi.p[1].h = __imp_CreateFileMappingW(
|
||||
-1, 0, kNtPageReadwrite, shallocsize >> 32, shallocsize, NULL)),
|
||||
kNtFileMapWrite, 0, 0, shallocsize, (void *)shallocaddr);
|
||||
_mmi.p[1].x = shallocaddr >> 16;
|
||||
_mmi.p[1].y = (shallocaddr >> 16) + ((shallocsize - 1) >> 16);
|
||||
|
|
|
@ -64,16 +64,16 @@ textwindows int sys_socketpair_nt(int family, int type, int proto, int sv[2]) {
|
|||
if (writer != -1) __releasefd(writer);
|
||||
return -1;
|
||||
}
|
||||
if ((hpipe = CreateNamedPipe(
|
||||
pipename, kNtPipeAccessDuplex | kNtFileFlagOverlapped, mode, 1,
|
||||
65536, 65536, 0, &kNtIsInheritable)) == -1) {
|
||||
if ((hpipe = CreateNamedPipe(pipename,
|
||||
kNtPipeAccessDuplex | kNtFileFlagOverlapped,
|
||||
mode, 1, 65536, 65536, 0, 0)) == -1) {
|
||||
__releasefd(writer);
|
||||
__releasefd(reader);
|
||||
return -1;
|
||||
}
|
||||
|
||||
h1 = CreateFile(pipename, kNtGenericWrite | kNtGenericRead, 0,
|
||||
&kNtIsInheritable, kNtOpenExisting, kNtFileFlagOverlapped, 0);
|
||||
h1 = CreateFile(pipename, kNtGenericWrite | kNtGenericRead, 0, 0,
|
||||
kNtOpenExisting, kNtFileFlagOverlapped, 0);
|
||||
|
||||
__fds_lock();
|
||||
|
||||
|
|
|
@ -34,11 +34,13 @@
|
|||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/handlock.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nt/enum/processcreationflags.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/processinformation.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
|
@ -66,6 +68,14 @@ static void posix_spawn_cleanup3fds(int fds[3]) {
|
|||
}
|
||||
}
|
||||
|
||||
static void posix_spawn_inherit(int64_t hands[3], bool32 bInherit) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (hands[i] != -1) {
|
||||
SetHandleInformation(hands[i], kNtHandleFlagInherit, bInherit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const char *DescribePid(char buf[12], int err, int *pid) {
|
||||
if (err) return "n/a";
|
||||
if (!pid) return "NULL";
|
||||
|
@ -176,9 +186,13 @@ static textwindows errno_t posix_spawn_windows_impl(
|
|||
int rc, e = errno;
|
||||
struct NtProcessInformation procinfo;
|
||||
if (!envp) envp = environ;
|
||||
__hand_rlock();
|
||||
posix_spawn_inherit(stdio_handle, true);
|
||||
rc = ntspawn(path, argv, envp, v, 0, 0, bInheritHandles, dwCreationFlags, 0,
|
||||
&startinfo, &procinfo);
|
||||
posix_spawn_inherit(stdio_handle, false);
|
||||
posix_spawn_cleanup3fds(close_this_fd_later);
|
||||
__hand_runlock();
|
||||
if (rc == -1) {
|
||||
int err = errno;
|
||||
__releasefd(child);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/handlock.internal.h"
|
||||
#include "libc/intrin/leaky.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
@ -64,11 +65,13 @@ void _pthread_onfork_prepare(void) {
|
|||
_pthread_onfork(0);
|
||||
pthread_spin_lock(&_pthread_lock);
|
||||
__fds_lock();
|
||||
__hand_lock();
|
||||
__mmi_lock();
|
||||
}
|
||||
|
||||
void _pthread_onfork_parent(void) {
|
||||
__mmi_unlock();
|
||||
__hand_unlock();
|
||||
__fds_unlock();
|
||||
pthread_spin_unlock(&_pthread_lock);
|
||||
_pthread_onfork(1);
|
||||
|
@ -87,6 +90,7 @@ void _pthread_onfork_child(void) {
|
|||
atomic_store_explicit(&pt->cancelled, false, memory_order_relaxed);
|
||||
|
||||
// wipe core runtime locks
|
||||
__hand_init();
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
pthread_mutex_init(&__mmi_lock_obj, &attr);
|
||||
|
|
|
@ -252,7 +252,7 @@ void PosixSpawnWait(const char *prog) {
|
|||
}
|
||||
|
||||
BENCH(posix_spawn, bench) {
|
||||
long n = 128L * 1000 * 1000;
|
||||
long n = 1L * 1000 * 1000;
|
||||
memset(gc(malloc(n)), -1, n);
|
||||
creat("tiny64", 0755);
|
||||
write(3, kTinyLinuxExit, 128);
|
||||
|
|
Loading…
Reference in a new issue