Avoid leaking handles across processes

This commit is contained in:
Justine Tunney 2023-09-12 01:07:51 -07:00
parent a359de7893
commit 8a0008d985
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
44 changed files with 232 additions and 266 deletions

View file

@ -61,7 +61,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
handle = g_fds.p[oldfd].handle; handle = g_fds.p[oldfd].handle;
proc = GetCurrentProcess(); 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)) { kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind; g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].mode = g_fds.p[oldfd].mode; g_fds.p[newfd].mode = g_fds.p[oldfd].mode;

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h" #include "libc/calls/ntspawn.h"
#include "libc/calls/struct/fd.internal.h"
#include "libc/calls/struct/sigaction.internal.h" #include "libc/calls/struct/sigaction.internal.h"
#include "libc/calls/syscall-nt.internal.h" #include "libc/calls/syscall-nt.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
@ -37,6 +38,7 @@
#include "libc/nt/enum/threadaccess.h" #include "libc/nt/enum/threadaccess.h"
#include "libc/nt/enum/wait.h" #include "libc/nt/enum/wait.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
@ -65,6 +67,7 @@
// clang-format off // clang-format off
__msabi extern typeof(CloseHandle) *const __imp_CloseHandle; __msabi extern typeof(CloseHandle) *const __imp_CloseHandle;
__msabi extern typeof(DuplicateHandle) *const __imp_DuplicateHandle;
__msabi extern typeof(ExitProcess) *const __imp_ExitProcess; __msabi extern typeof(ExitProcess) *const __imp_ExitProcess;
__msabi extern typeof(GenerateConsoleCtrlEvent) *const __imp_GenerateConsoleCtrlEvent; __msabi extern typeof(GenerateConsoleCtrlEvent) *const __imp_GenerateConsoleCtrlEvent;
__msabi extern typeof(GetCurrentThreadId) *const __imp_GetCurrentThreadId; __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(GetLastError) *const __imp_GetLastError;
__msabi extern typeof(OpenThread) *const __imp_OpenThread; __msabi extern typeof(OpenThread) *const __imp_OpenThread;
__msabi extern typeof(SetConsoleCtrlHandler) *const __imp_SetConsoleCtrlHandler; __msabi extern typeof(SetConsoleCtrlHandler) *const __imp_SetConsoleCtrlHandler;
__msabi extern typeof(SetHandleInformation) *const __imp_SetHandleInformation;
__msabi extern typeof(TerminateThread) *const __imp_TerminateThread; __msabi extern typeof(TerminateThread) *const __imp_TerminateThread;
__msabi extern typeof(UnmapViewOfFile) *const __imp_UnmapViewOfFile; __msabi extern typeof(UnmapViewOfFile) *const __imp_UnmapViewOfFile;
__msabi extern typeof(WaitForSingleObject) *const __imp_WaitForSingleObject; __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(__sigchld_thread));
PurgeThread(*_weaken(__sigwinch_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 // pass bitmask telling child which fds are sockets
int bits; int bits;
char buf[32], *v = 0; char buf[32], *v = 0;
@ -205,10 +192,16 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
struct NtStartupInfo si = { struct NtStartupInfo si = {
.cb = sizeof(struct NtStartupInfo), .cb = sizeof(struct NtStartupInfo),
.dwFlags = kNtStartfUsestdhandles, .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 // launch the process
struct NtProcessInformation pi; struct NtProcessInformation pi;
@ -223,6 +216,11 @@ keywords int sys_execve_nt(const char *program, char *const argv[],
} }
PurgeHandle(pi.hThread); PurgeHandle(pi.hThread);
// remove duplicate handles
for (i = 0; i <= 2; ++i) {
PurgeHandle(si.stdiofds[i]);
}
// retreat to original win32-provided stack memory // retreat to original win32-provided stack memory
__switch_stacks(pi.hProcess, 0, 0, 0, sys_execve_nt_relay, __oldstack); __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 // close more handles
__imp_SetConsoleCtrlHandler((void *)sys_execve_nt_event, 1); __imp_SetConsoleCtrlHandler((void *)sys_execve_nt_event, 1);
PurgeThread(g_fds.stdin.thread); // wasn't inherited by ntspawn PurgeThread(g_fds.stdin.thread);
PurgeHandle(g_fds.stdin.reader); // wasn't inherited by ntspawn PurgeHandle(g_fds.stdin.reader);
PurgeHandle(g_fds.stdin.writer); // wasn't inherited by ntspawn PurgeHandle(g_fds.stdin.writer);
PurgeHandle(g_fds.p[0].handle); // was inherited via startinfo for (i = 0; i < g_fds.n; ++i) {
PurgeHandle(g_fds.p[1].handle); // was inherited via startinfo if (g_fds.p[i].kind != kFdEmpty) {
PurgeHandle(g_fds.p[2].handle); // was inherited via startinfo PurgeHandle(g_fds.p[i].handle);
if (g_fds.p[i].kind == kFdConsole) {
PurgeHandle(g_fds.p[i].extra);
}
}
}
if (_weaken(__klog_handle)) { if (_weaken(__klog_handle)) {
PurgeHandle(*_weaken(__klog_handle)); // wasn't inherited by ntspawn PurgeHandle(*_weaken(__klog_handle));
} }
// free all the memory mmap created // free all the memory mmap created
for (i = 0; i < _mmi.i; ++i) { for (i = 0; i < _mmi.i; ++i) {
__imp_UnmapViewOfFile((void *)((uintptr_t)_mmi.p[i].x << 16)); __imp_UnmapViewOfFile((void *)((uintptr_t)_mmi.p[i].x << 16));
PurgeHandle(_mmi.p[i].h);
} }
// wait for process to terminate // wait for process to terminate

View file

@ -130,12 +130,11 @@ static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
// open the file, following symlinks // open the file, following symlinks
int e = errno; int e = errno;
int64_t hand = CreateFile(path16, perm | extra_perm, share, &kNtIsInheritable, int64_t hand = CreateFile(path16, perm | extra_perm, share, 0, disp,
disp, attr | extra_attr, 0); attr | extra_attr, 0);
if (hand == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) { if (hand == -1 && errno == EACCES && (flags & O_ACCMODE) == O_RDONLY) {
errno = e; errno = e;
hand = CreateFile(path16, perm, share, &kNtIsInheritable, disp, hand = CreateFile(path16, perm, share, 0, disp, attr | extra_attr, 0);
attr | extra_attr, 0);
} }
return __fix_enotdir(hand, path16); return __fix_enotdir(hand, path16);

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/state.internal.h" #include "libc/calls/state.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/intrin/handlock.internal.h"
#include "libc/nt/createfile.h" #include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h" #include "libc/nt/enum/creationdisposition.h"
@ -52,11 +53,11 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
} }
__fds_unlock(); __fds_unlock();
hin = CreateNamedPipe(pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped, hin = CreateNamedPipe(pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped,
mode, 1, PIPE_BUF, PIPE_BUF, 0, &kNtIsInheritable); mode, 1, PIPE_BUF, PIPE_BUF, 0, 0);
__fds_lock(); __fds_lock();
if (hin != -1) { if (hin != -1) {
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, &kNtIsInheritable, if ((hout = CreateFile(pipename, kNtGenericWrite, 0, 0, kNtOpenExisting,
kNtOpenExisting, kNtFileFlagOverlapped, 0)) != -1) { kNtFileFlagOverlapped, 0)) != -1) {
g_fds.p[reader].kind = kFdFile; g_fds.p[reader].kind = kFdFile;
g_fds.p[reader].flags = O_RDONLY | flags; g_fds.p[reader].flags = O_RDONLY | flags;
g_fds.p[reader].mode = 0010444; g_fds.p[reader].mode = 0010444;

View file

@ -33,8 +33,8 @@ textwindows int sys_statfs_nt(const char *path, struct statfs *sf) {
if (__mkntpath(path, path16) == -1) return -1; if (__mkntpath(path, path16) == -1) return -1;
h = __fix_enotdir( h = __fix_enotdir(
CreateFile(path16, kNtFileGenericRead, CreateFile(path16, kNtFileGenericRead,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
&kNtIsInheritable, kNtOpenExisting, kNtOpenExisting,
kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0), kNtFileAttributeNormal | kNtFileFlagBackupSemantics, 0),
path16); path16);
if (h == -1) return -1; if (h == -1) return -1;

View file

@ -28,7 +28,7 @@
* @see System Five Application Binary Interface § 3.4.3 * @see System Five Application Binary Interface § 3.4.3
* @asyncsignalsafe * @asyncsignalsafe
*/ */
dontasan struct AuxiliaryValue __getauxval(unsigned long at) { struct AuxiliaryValue __getauxval(unsigned long at) {
unsigned long *ap; unsigned long *ap;
for (ap = __auxv; ap[0]; ap += 2) { for (ap = __auxv; ap[0]; ap += 2) {
if (at == ap[0]) { if (at == ap[0]) {

View file

@ -22,7 +22,7 @@
#define ToUpper(c) \ #define ToUpper(c) \
(IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (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; char *t;
int i, j; int i, j;
for (i = 0; (t = p[i]); ++i) { for (i = 0; (t = p[i]); ++i) {

View file

@ -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; const unsigned char *p = x;
struct ReportOriginHeap *t = a; struct ReportOriginHeap *t = a;
if ((p <= t->a && t->a < p + n) || if ((p <= t->a && t->a < p + n) ||

View file

@ -25,8 +25,8 @@
#define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__) #define append(...) o += ksnprintf(buf + o, N - o, __VA_ARGS__)
dontinstrument dontasan const char *(DescribeBacktrace)(char buf[N], dontinstrument const char *(DescribeBacktrace)(char buf[N],
struct StackFrame *fr) { struct StackFrame *fr) {
bool gotsome = false; bool gotsome = false;
char *p = buf; char *p = buf;
char *pe = p + N; char *pe = p + N;

View file

@ -24,7 +24,6 @@
const char *( const char *(
DescribeNtSecurityAttributes)(char buf[32], DescribeNtSecurityAttributes)(char buf[32],
const struct NtSecurityAttributes *p) { const struct NtSecurityAttributes *p) {
if (p == &kNtIsInheritable) return "&kNtIsInheritable";
FormatInt64(buf, (uintptr_t)p); FormatInt64(buf, (uintptr_t)p);
return buf; return buf;
} }

View file

@ -32,15 +32,15 @@
static uint64_t sys_mmap_metal_break; static uint64_t sys_mmap_metal_break;
dontasan static struct DirectMap bad_mmap(void) { static struct DirectMap bad_mmap(void) {
struct DirectMap res; struct DirectMap res;
res.addr = (void *)-1; res.addr = (void *)-1;
res.maphandle = -1; res.maphandle = -1;
return res; return res;
} }
dontasan struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot, struct DirectMap sys_mmap_metal(void *vaddr, size_t size, int prot, int flags,
int flags, int fd, int64_t off) { int fd, int64_t off) {
/* asan runtime depends on this function */ /* asan runtime depends on this function */
size_t i; size_t i;
struct mman *mm; struct mman *mm;

View file

@ -42,13 +42,6 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
handle = g_fds.p[fd].handle; 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 // nt will whine under many circumstances if we change the execute bit
// later using mprotect(). the workaround is to always request execute // later using mprotect(). the workaround is to always request execute
// and then virtualprotect() it away until we actually need it. please // 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; int e = errno;
struct DirectMap dm; struct DirectMap dm;
TryAgain: TryAgain:
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1, if ((dm.maphandle = CreateFileMapping(handle, 0, fl.flags1,
(size + off) >> 32, (size + off), 0))) { (size + off) >> 32, (size + off), 0))) {
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off, if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
size, addr))) { size, addr))) {

View file

@ -32,7 +32,7 @@
#define G FRAMESIZE #define G FRAMESIZE
static dontasan void *_mapframe(void *p, int f) { static void *_mapframe(void *p, int f) {
int rc, prot, flags; int rc, prot, flags;
struct DirectMap dm; struct DirectMap dm;
prot = PROT_READ | PROT_WRITE; 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 * @return new value for `e` or null w/ errno
* @raise ENOMEM if we require more vespene gas * @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; char *q;
unassert(!((uintptr_t)SHADOW(p) & (G - 1))); unassert(!((uintptr_t)SHADOW(p) & (G - 1)));
unassert((uintptr_t)p + (G << kAsanScale) <= h); unassert((uintptr_t)p + (G << kAsanScale) <= h);

View file

@ -18,7 +18,7 @@
*/ */
#include "libc/runtime/memtrack.internal.h" #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; unsigned l, m, r;
l = 0; l = 0;
r = mm->i; r = mm->i;

View file

@ -25,7 +25,7 @@
* @param delta is added to enabled state * @param delta is added to enabled state
* @return enabled state before `delta` was applied * @return enabled state before `delta` was applied
*/ */
dontasan dontubsan dontinstrument int ftrace_enabled(int delta) { dontinstrument int ftrace_enabled(int delta) {
int res; int res;
struct CosmoTib *tib; struct CosmoTib *tib;
if (__tls_enabled) { if (__tls_enabled) {

View file

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

62
libc/intrin/handlock.c Normal file
View 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);
}
}

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

View file

@ -46,31 +46,11 @@ $(LIBC_INTRIN_A).pkg: \
$(LIBC_INTRIN_A_OBJS) \ $(LIBC_INTRIN_A_OBJS) \
$(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_INTRIN_A_DIRECTDEPS),$($(x)_A).pkg)
# we can't use asan because: o/$(MODE)/libc/intrin/mman.greg.o: private COPTS += -Os
# __strace_init() calls this before asan is initialized
o/$(MODE)/libc/intrin/strace_enabled.o: private \
COPTS += \
-fno-sanitize=address
# we can't use asan because: $(LIBC_INTRIN_A_OBJS): private \
# 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 \
CFLAGS += \ CFLAGS += \
-x-no-pg \
-ffreestanding \ -ffreestanding \
-fno-sanitize=all \ -fno-sanitize=all \
-fno-stack-protector -fno-stack-protector
@ -81,121 +61,6 @@ o/$(MODE)/libc/intrin/asan.o: private \
-finline \ -finline \
-finline-functions -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 \ o//libc/intrin/memmove.o: private \
CFLAGS += \ CFLAGS += \
-fno-toplevel-reorder -fno-toplevel-reorder

View file

@ -32,7 +32,7 @@
#define kBufSize 1024 #define kBufSize 1024
#define kPid "TracerPid:\t" #define kPid "TracerPid:\t"
static textwindows dontasan bool IsBeingDebugged(void) { static textwindows bool IsBeingDebugged(void) {
return !!NtGetPeb()->BeingDebugged; return !!NtGetPeb()->BeingDebugged;
} }

View file

@ -36,9 +36,8 @@ static inline const unsigned char *memchr_pure(const unsigned char *s,
} }
#if defined(__x86_64__) && !defined(__chibicc__) #if defined(__x86_64__) && !defined(__chibicc__)
dontasan static inline const unsigned char *memchr_sse(const unsigned char *s, static inline const unsigned char *memchr_sse(const unsigned char *s,
unsigned char c, unsigned char c, size_t n) {
size_t n) {
size_t i; size_t i;
unsigned m; unsigned m;
xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c}; 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 * @return is pointer to first instance of c or NULL if not found
* @asyncsignalsafe * @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__) #if defined(__x86_64__) && !defined(__chibicc__)
const void *r; const void *r;
if (IsAsan()) __asan_verify(s, n); if (IsAsan()) __asan_verify(s, n);

View file

@ -37,9 +37,8 @@ static inline const unsigned char *memrchr_pure(const unsigned char *s,
} }
#if defined(__x86_64__) && !defined(__chibicc__) #if defined(__x86_64__) && !defined(__chibicc__)
dontasan static inline const unsigned char *memrchr_sse(const unsigned char *s, static inline const unsigned char *memrchr_sse(const unsigned char *s,
unsigned char c, unsigned char c, size_t n) {
size_t n) {
size_t i; size_t i;
unsigned m; unsigned m;
xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c}; xmm_t v, t = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};

View file

@ -54,7 +54,7 @@ struct ReclaimedPage {
/** /**
* Allocates new page of physical memory. * 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; uint64_t p = mm->frp;
if (p != NOPAGE) { if (p != NOPAGE) {
uint64_t q; 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. * Returns pointer to page table entry for page at virtual address.
* Additional page tables are allocated if needed as a side-effect. * Additional page tables are allocated if needed as a side-effect.
*/ */
dontasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t, textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t, int64_t vaddr,
int64_t vaddr, bool maketables) { bool maketables) {
uint64_t *e, p; uint64_t *e, p;
unsigned char h; unsigned char h;
for (h = 39;; h -= 9) { 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. * 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 a, b;
uint64_t x, y; uint64_t x, y;
unsigned i, j, n; 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. * Identity maps an area of physical memory to its negative address.
*/ */
dontasan textreal uint64_t *__invert_memory_area(struct mman *mm, textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t,
uint64_t *pml4t, uint64_t ps, uint64_t ps, uint64_t size,
uint64_t size, uint64_t pte_flags) {
uint64_t pte_flags) {
uint64_t pe = ps + size, p, *m = NULL; uint64_t pe = ps + size, p, *m = NULL;
ps = ROUNDDOWN(ps, 4096); ps = ROUNDDOWN(ps, 4096);
pe = ROUNDUP(pe, 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. * 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; uint64_t *m, e;
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD); m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
if (m) { 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. * Increments the reference counts for an area of physical memory.
*/ */
dontasan void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps, void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps, uint64_t size) {
uint64_t size) {
uint64_t p = ROUNDDOWN(ps, 4096), e = ROUNDUP(ps + size, 4096); uint64_t p = ROUNDDOWN(ps, 4096), e = ROUNDUP(ps + size, 4096);
while (p != e) { while (p != e) {
__ref_page(mm, pml4t, p); __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. * 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); struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
unassert(p == (p & PAGE_TA)); unassert(p == (p & PAGE_TA));
rp->next = mm->frp; 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) * page if there are no virtual addresses (excluding the negative space)
* referring to it. * 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; uint64_t *m, e;
m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD); m = __invert_memory_area(mm, pml4t, p, 4096, PAGE_RW | PAGE_XD);
if (m) { 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. * Identity maps all usable physical memory to its negative address.
*/ */
static dontasan textreal void __invert_memory(struct mman *mm, static textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
uint64_t *pml4t) {
uint64_t i; uint64_t i;
for (i = 0; i < mm->e820n; ++i) { for (i = 0; i < mm->e820n; ++i) {
uint64_t ps = mm->e820[i].addr, size = mm->e820[i].size; 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))); \ : "i"(offsetof(type, member))); \
} while (0) } while (0)
dontasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t, textreal void __setup_mman(struct mman *mm, uint64_t *pml4t, uint64_t top) {
uint64_t top) {
export_offsetof(struct mman, pc_drive_base_table); export_offsetof(struct mman, pc_drive_base_table);
export_offsetof(struct mman, pc_drive_last_sector); export_offsetof(struct mman, pc_drive_last_sector);
export_offsetof(struct mman, pc_drive_last_head); 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. * 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, textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
uint64_t top) { uint64_t top) {
uint64_t i, f, v, m; uint64_t i, f, v, m;
struct Elf64_Phdr *p; struct Elf64_Phdr *p;
extern char ape_phdrs[] __attribute__((__weak__)); 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 * Reclaims memory pages which were used at boot time but which can now be
* made available for the application. * made available for the application.
*/ */
dontasan textreal void __reclaim_boot_pages(struct mman *mm, textreal void __reclaim_boot_pages(struct mman *mm, uint64_t skip_start,
uint64_t skip_start, uint64_t skip_end) {
uint64_t skip_end) {
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, i, n = mm->e820n, b, e; uint64_t p = mm->frp, q = IMAGE_BASE_REAL, i, n = mm->e820n, b, e;
for (i = 0; i < n; ++i) { for (i = 0; i < n; ++i) {
b = mm->e820[i].addr; b = mm->e820[i].addr;

View file

@ -48,9 +48,8 @@
*/ */
bool __nocolor; bool __nocolor;
optimizesize textstartup dontasan void __nocolor_init(int argc, char **argv, optimizesize textstartup void __nocolor_init(int argc, char **argv, char **envp,
char **envp, intptr_t *auxv) {
intptr_t *auxv) {
char *s; char *s;
__nocolor = (IsWindows() && !IsAtLeastWindows10()) || __nocolor = (IsWindows() && !IsAtLeastWindows10()) ||
((s = getenv("TERM")) && IsDumb(s)); ((s = getenv("TERM")) && IsDumb(s));

View file

@ -27,7 +27,7 @@
* *
* @see IsAtLeastWindows10() * @see IsAtLeastWindows10()
*/ */
textwindows dontasan int NtGetVersion(void) { textwindows int NtGetVersion(void) {
return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion; return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion;
} }

View file

@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return pointer to nul byte * @return pointer to nul byte
* @asyncsignalsafe * @asyncsignalsafe
*/ */
dontasan char *stpcpy(char *d, const char *s) { char *stpcpy(char *d, const char *s) {
size_t i = 0; size_t i = 0;
if (IsAsan()) { if (IsAsan()) {
__asan_verify(d, strlen(s) + 1); __asan_verify(d, strlen(s) + 1);

View file

@ -4,11 +4,11 @@
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#define _KERNTRACE 0 /* not configurable w/ flag yet */ #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 _DATATRACE 1 /* not configurable w/ flag yet */
#define _STDIOTRACE 0 /* not configurable w/ flag yet */ #define _STDIOTRACE 0 /* not configurable w/ flag yet */
#define _LOCKTRACE 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 " #define STRACE_PROLOGUE "%rSYS %6P %'18T "

View file

@ -25,7 +25,7 @@
* @param delta is added to enabled state * @param delta is added to enabled state
* @return enabled state before `delta` was applied * @return enabled state before `delta` was applied
*/ */
dontasan dontubsan dontinstrument int strace_enabled(int delta) { dontinstrument int strace_enabled(int delta) {
int res; int res;
struct CosmoTib *tib; struct CosmoTib *tib;
if (__tls_enabled) { if (__tls_enabled) {

View file

@ -32,7 +32,7 @@ static inline const char *strchr_pure(const char *s, int c) {
#if defined(__x86_64__) && !defined(__chibicc__) #if defined(__x86_64__) && !defined(__chibicc__)
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16))); 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 k;
unsigned m; unsigned m;
const xmm_t *p; const xmm_t *p;
@ -56,7 +56,7 @@ dontasan static inline const char *strchr_sse(const char *s, unsigned char c) {
} }
#endif #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; unsigned a, b;
uint64_t w, x, y; uint64_t w, x, y;
for (c *= 0x0101010101010101;; p += 8) { for (c *= 0x0101010101010101;; p += 8) {
@ -95,7 +95,7 @@ static dontasan inline const char *strchr_x64(const char *p, uint64_t c) {
* @asyncsignalsafe * @asyncsignalsafe
* @vforksafe * @vforksafe
*/ */
dontasan char *strchr(const char *s, int c) { char *strchr(const char *s, int c) {
if (IsAsan()) __asan_verify_str(s); if (IsAsan()) __asan_verify_str(s);
#if defined(__x86_64__) && !defined(__chibicc__) #if defined(__x86_64__) && !defined(__chibicc__)
const char *r; const char *r;

View file

@ -32,8 +32,7 @@ static inline const char *strchrnul_pure(const char *s, int c) {
#if defined(__x86_64__) && !defined(__chibicc__) #if defined(__x86_64__) && !defined(__chibicc__)
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16))); typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
dontasan static inline const char *strchrnul_sse(const char *s, static inline const char *strchrnul_sse(const char *s, unsigned char c) {
unsigned char c) {
unsigned k; unsigned k;
unsigned m; unsigned m;
const xmm_t *p; const xmm_t *p;
@ -54,7 +53,7 @@ dontasan static inline const char *strchrnul_sse(const char *s,
} }
#endif #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; unsigned a, b;
uint64_t w, x, y; uint64_t w, x, y;
for (c *= 0x0101010101010101;; p += 8) { for (c *= 0x0101010101010101;; p += 8) {

View file

@ -29,7 +29,7 @@
* @return is <0, 0, or >0 based on uint8_t comparison * @return is <0, 0, or >0 based on uint8_t comparison
* @asyncsignalsafe * @asyncsignalsafe
*/ */
dontasan int strcmp(const char *a, const char *b) { int strcmp(const char *a, const char *b) {
int c; int c;
size_t i = 0; size_t i = 0;
uint64_t v, w; uint64_t v, w;

View file

@ -33,7 +33,7 @@ typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
* @return original dest * @return original dest
* @asyncsignalsafe * @asyncsignalsafe
*/ */
dontasan char *strcpy(char *d, const char *s) { char *strcpy(char *d, const char *s) {
size_t i = 0; size_t i = 0;
if (IsAsan()) { if (IsAsan()) {
__asan_verify_str(s); __asan_verify_str(s);

View file

@ -25,7 +25,7 @@
// clang-format off // clang-format off
#if defined(SYSDEBUG) && _NTTRACE #if defined(SYSDEBUG) && _NTTRACE
dontasan dontubsan privileged privileged
#endif #endif
/** /**

View file

@ -30,7 +30,7 @@
// clang-format off // clang-format off
#if defined(SYSDEBUG) && _NTTRACE #if defined(SYSDEBUG) && _NTTRACE
dontasan dontubsan privileged privileged
#endif #endif
/** /**

View file

@ -28,7 +28,7 @@
* @return number of bytes (excluding NUL) * @return number of bytes (excluding NUL)
* @asyncsignalsafe * @asyncsignalsafe
*/ */
dontasan size_t strlen(const char *s) { size_t strlen(const char *s) {
if (IsAsan()) __asan_verify_str(s); if (IsAsan()) __asan_verify_str(s);
#if defined(__x86_64__) && !defined(__chibicc__) #if defined(__x86_64__) && !defined(__chibicc__)
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16))); typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(16)));

View file

@ -23,7 +23,7 @@
#include "libc/str/str.h" #include "libc/str/str.h"
#ifndef __aarch64__ #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; uint64_t w;
for (; i + 8 < n; i += 8) { for (; i + 8 < n; i += 8) {
w = *(uint64_t *)(s + i); 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 * @return byte length
* @asyncsignalsafe * @asyncsignalsafe
*/ */
dontasan size_t strnlen(const char *s, size_t n) { size_t strnlen(const char *s, size_t n) {
size_t i; size_t i;
if (IsAsan() && n) __asan_verify(s, 1); if (IsAsan() && n) __asan_verify(s, 1);
for (i = 0; (uintptr_t)(s + i) & 7; ++i) { for (i = 0; (uintptr_t)(s + i) & 7; ++i) {

View file

@ -31,6 +31,6 @@ char *strrchr(const char *s, int c) {
return memrchr(s, c, strlen(s)); return memrchr(s, c, strlen(s));
} }
__strong_reference(strrchr, rindex); __weak_reference(strrchr, rindex);
#endif /* __aarch64__ */ #endif /* __aarch64__ */

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h" #include "libc/calls/ntspawn.h"
#include "libc/calls/state.internal.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-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h" #include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/wincrash.internal.h" #include "libc/calls/wincrash.internal.h"
@ -26,6 +27,7 @@
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h" #include "libc/intrin/atomic.h"
#include "libc/intrin/directmap.internal.h" #include "libc/intrin/directmap.internal.h"
#include "libc/intrin/handlock.internal.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h" #include "libc/intrin/weaken.h"
@ -43,6 +45,7 @@
#include "libc/nt/enum/processcreationflags.h" #include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/enum/startf.h" #include "libc/nt/enum/startf.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
#include "libc/nt/files.h"
#include "libc/nt/ipc.h" #include "libc/nt/ipc.h"
#include "libc/nt/memory.h" #include "libc/nt/memory.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
@ -313,6 +316,21 @@ textwindows void WinMainForked(void) {
longjmp(jb, 1); 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) { textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
jmp_buf jb; jmp_buf jb;
uint32_t op; uint32_t op;
@ -357,8 +375,12 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
args = args2; args = args2;
} }
#endif #endif
if (ntspawn(GetProgramExecutableName(), args, environ, forkvar, 0, 0, __hand_inherit(true);
true, dwCreationFlags, 0, &startinfo, &procinfo) != -1) { int spawnrc =
ntspawn(GetProgramExecutableName(), args, environ, forkvar, 0, 0,
true, dwCreationFlags, 0, &startinfo, &procinfo);
__hand_inherit(false);
if (spawnrc != -1) {
CloseHandle(procinfo.hThread); CloseHandle(procinfo.hThread);
ok = WriteAll(writer, jb, sizeof(jb)) && ok = WriteAll(writer, jb, sizeof(jb)) &&
WriteAll(writer, &_mmi.i, sizeof(_mmi.i)) && WriteAll(writer, &_mmi.i, sizeof(_mmi.i)) &&

View file

@ -127,7 +127,7 @@ __msabi static textwindows void DeduplicateStdioHandles(void) {
int64_t h2 = __imp_GetStdHandle(kNtStdio[j]); int64_t h2 = __imp_GetStdHandle(kNtStdio[j]);
if (h1 == h2) { if (h1 == h2) {
int64_t h3, proc = __imp_GetCurrentProcess(); int64_t h3, proc = __imp_GetCurrentProcess();
__imp_DuplicateHandle(proc, h2, proc, &h3, 0, true, __imp_DuplicateHandle(proc, h2, proc, &h3, 0, false,
kNtDuplicateSameAccess); kNtDuplicateSameAccess);
__imp_SetStdHandle(kNtStdio[j], h3); __imp_SetStdHandle(kNtStdio[j], h3);
} }
@ -159,11 +159,10 @@ __msabi static textwindows wontreturn void WinInit(const char16_t *cmdline) {
_mmi.n = ARRAYLEN(_mmi.s); _mmi.n = ARRAYLEN(_mmi.s);
uintptr_t stackaddr = GetStaticStackAddr(0); uintptr_t stackaddr = GetStaticStackAddr(0);
size_t stacksize = GetStaticStackSize(); size_t stacksize = GetStaticStackSize();
__imp_MapViewOfFileEx((_mmi.p[0].h = __imp_CreateFileMappingW( __imp_MapViewOfFileEx(
-1, &kNtIsInheritable, kNtPageExecuteReadwrite, (_mmi.p[0].h = __imp_CreateFileMappingW(
stacksize >> 32, stacksize, NULL)), -1, 0, kNtPageExecuteReadwrite, stacksize >> 32, stacksize, NULL)),
kNtFileMapWrite | kNtFileMapExecute, 0, 0, stacksize, kNtFileMapWrite | kNtFileMapExecute, 0, 0, stacksize, (void *)stackaddr);
(void *)stackaddr);
int prot = (intptr_t)ape_stack_prot; int prot = (intptr_t)ape_stack_prot;
if (~prot & PROT_EXEC) { if (~prot & PROT_EXEC) {
uint32_t old; 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 shallocend = ROUNDUP(shadowend, FRAMESIZE);
uintptr_t shallocsize = shallocend - shallocaddr; uintptr_t shallocsize = shallocend - shallocaddr;
__imp_MapViewOfFileEx( __imp_MapViewOfFileEx(
(_mmi.p[1].h = (_mmi.p[1].h = __imp_CreateFileMappingW(
__imp_CreateFileMappingW(-1, &kNtIsInheritable, kNtPageReadwrite, -1, 0, kNtPageReadwrite, shallocsize >> 32, shallocsize, NULL)),
shallocsize >> 32, shallocsize, NULL)),
kNtFileMapWrite, 0, 0, shallocsize, (void *)shallocaddr); kNtFileMapWrite, 0, 0, shallocsize, (void *)shallocaddr);
_mmi.p[1].x = shallocaddr >> 16; _mmi.p[1].x = shallocaddr >> 16;
_mmi.p[1].y = (shallocaddr >> 16) + ((shallocsize - 1) >> 16); _mmi.p[1].y = (shallocaddr >> 16) + ((shallocsize - 1) >> 16);

View file

@ -64,16 +64,16 @@ textwindows int sys_socketpair_nt(int family, int type, int proto, int sv[2]) {
if (writer != -1) __releasefd(writer); if (writer != -1) __releasefd(writer);
return -1; return -1;
} }
if ((hpipe = CreateNamedPipe( if ((hpipe = CreateNamedPipe(pipename,
pipename, kNtPipeAccessDuplex | kNtFileFlagOverlapped, mode, 1, kNtPipeAccessDuplex | kNtFileFlagOverlapped,
65536, 65536, 0, &kNtIsInheritable)) == -1) { mode, 1, 65536, 65536, 0, 0)) == -1) {
__releasefd(writer); __releasefd(writer);
__releasefd(reader); __releasefd(reader);
return -1; return -1;
} }
h1 = CreateFile(pipename, kNtGenericWrite | kNtGenericRead, 0, h1 = CreateFile(pipename, kNtGenericWrite | kNtGenericRead, 0, 0,
&kNtIsInheritable, kNtOpenExisting, kNtFileFlagOverlapped, 0); kNtOpenExisting, kNtFileFlagOverlapped, 0);
__fds_lock(); __fds_lock();

View file

@ -34,11 +34,13 @@
#include "libc/fmt/magnumstrs.internal.h" #include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h" #include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/handlock.internal.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"
#include "libc/intrin/weaken.h" #include "libc/intrin/weaken.h"
#include "libc/mem/alloca.h" #include "libc/mem/alloca.h"
#include "libc/nt/enum/processcreationflags.h" #include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/enum/startf.h" #include "libc/nt/enum/startf.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/struct/processinformation.h" #include "libc/nt/struct/processinformation.h"
#include "libc/nt/struct/startupinfo.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) { static const char *DescribePid(char buf[12], int err, int *pid) {
if (err) return "n/a"; if (err) return "n/a";
if (!pid) return "NULL"; if (!pid) return "NULL";
@ -176,9 +186,13 @@ static textwindows errno_t posix_spawn_windows_impl(
int rc, e = errno; int rc, e = errno;
struct NtProcessInformation procinfo; struct NtProcessInformation procinfo;
if (!envp) envp = environ; if (!envp) envp = environ;
__hand_rlock();
posix_spawn_inherit(stdio_handle, true);
rc = ntspawn(path, argv, envp, v, 0, 0, bInheritHandles, dwCreationFlags, 0, rc = ntspawn(path, argv, envp, v, 0, 0, bInheritHandles, dwCreationFlags, 0,
&startinfo, &procinfo); &startinfo, &procinfo);
posix_spawn_inherit(stdio_handle, false);
posix_spawn_cleanup3fds(close_this_fd_later); posix_spawn_cleanup3fds(close_this_fd_later);
__hand_runlock();
if (rc == -1) { if (rc == -1) {
int err = errno; int err = errno;
__releasefd(child); __releasefd(child);

View file

@ -24,6 +24,7 @@
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/atomic.h" #include "libc/intrin/atomic.h"
#include "libc/intrin/dll.h" #include "libc/intrin/dll.h"
#include "libc/intrin/handlock.internal.h"
#include "libc/intrin/leaky.internal.h" #include "libc/intrin/leaky.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/memtrack.internal.h" #include "libc/runtime/memtrack.internal.h"
@ -64,11 +65,13 @@ void _pthread_onfork_prepare(void) {
_pthread_onfork(0); _pthread_onfork(0);
pthread_spin_lock(&_pthread_lock); pthread_spin_lock(&_pthread_lock);
__fds_lock(); __fds_lock();
__hand_lock();
__mmi_lock(); __mmi_lock();
} }
void _pthread_onfork_parent(void) { void _pthread_onfork_parent(void) {
__mmi_unlock(); __mmi_unlock();
__hand_unlock();
__fds_unlock(); __fds_unlock();
pthread_spin_unlock(&_pthread_lock); pthread_spin_unlock(&_pthread_lock);
_pthread_onfork(1); _pthread_onfork(1);
@ -87,6 +90,7 @@ void _pthread_onfork_child(void) {
atomic_store_explicit(&pt->cancelled, false, memory_order_relaxed); atomic_store_explicit(&pt->cancelled, false, memory_order_relaxed);
// wipe core runtime locks // wipe core runtime locks
__hand_init();
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&__mmi_lock_obj, &attr); pthread_mutex_init(&__mmi_lock_obj, &attr);

View file

@ -252,7 +252,7 @@ void PosixSpawnWait(const char *prog) {
} }
BENCH(posix_spawn, bench) { BENCH(posix_spawn, bench) {
long n = 128L * 1000 * 1000; long n = 1L * 1000 * 1000;
memset(gc(malloc(n)), -1, n); memset(gc(malloc(n)), -1, n);
creat("tiny64", 0755); creat("tiny64", 0755);
write(3, kTinyLinuxExit, 128); write(3, kTinyLinuxExit, 128);