diff --git a/libc/calls/dup-nt.c b/libc/calls/dup-nt.c index b0bbec3cc..23887098f 100644 --- a/libc/calls/dup-nt.c +++ b/libc/calls/dup-nt.c @@ -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; diff --git a/libc/calls/execve-nt.greg.c b/libc/calls/execve-nt.greg.c index e7535b32b..cb3ec3749 100644 --- a/libc/calls/execve-nt.greg.c +++ b/libc/calls/execve-nt.greg.c @@ -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 diff --git a/libc/calls/open-nt.c b/libc/calls/open-nt.c index df5314a4a..70939298c 100644 --- a/libc/calls/open-nt.c +++ b/libc/calls/open-nt.c @@ -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); diff --git a/libc/calls/pipe-nt.c b/libc/calls/pipe-nt.c index 1321343ef..f40d48657 100644 --- a/libc/calls/pipe-nt.c +++ b/libc/calls/pipe-nt.c @@ -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; diff --git a/libc/calls/statfs-nt.c b/libc/calls/statfs-nt.c index 4b656416d..bc78dadcb 100644 --- a/libc/calls/statfs-nt.c +++ b/libc/calls/statfs-nt.c @@ -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; diff --git a/libc/intrin/__getauxval.c b/libc/intrin/__getauxval.c index 312f3e4c0..38c81128c 100644 --- a/libc/intrin/__getauxval.c +++ b/libc/intrin/__getauxval.c @@ -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]) { diff --git a/libc/intrin/__getenv.c b/libc/intrin/__getenv.c index c5a6d02b1..2610347ac 100644 --- a/libc/intrin/__getenv.c +++ b/libc/intrin/__getenv.c @@ -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) { diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 9509c9f71..0cf16d802 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -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) || diff --git a/libc/intrin/describebacktrace.c b/libc/intrin/describebacktrace.c index 444b48a39..fbf70a66f 100644 --- a/libc/intrin/describebacktrace.c +++ b/libc/intrin/describebacktrace.c @@ -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; diff --git a/libc/intrin/describentsecurityattributes.c b/libc/intrin/describentsecurityattributes.c index 601c37500..e4eeb191a 100644 --- a/libc/intrin/describentsecurityattributes.c +++ b/libc/intrin/describentsecurityattributes.c @@ -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; } diff --git a/libc/intrin/directmap-metal.c b/libc/intrin/directmap-metal.c index 463ac7637..61f9af589 100644 --- a/libc/intrin/directmap-metal.c +++ b/libc/intrin/directmap-metal.c @@ -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; diff --git a/libc/intrin/directmap-nt.c b/libc/intrin/directmap-nt.c index d7c91d98f..0261dd904 100644 --- a/libc/intrin/directmap-nt.c +++ b/libc/intrin/directmap-nt.c @@ -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))) { diff --git a/libc/intrin/extend.c b/libc/intrin/extend.c index ac3e4a635..a6ca27f69 100644 --- a/libc/intrin/extend.c +++ b/libc/intrin/extend.c @@ -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); diff --git a/libc/intrin/findmemoryinterval.c b/libc/intrin/findmemoryinterval.c index 60e089bae..97cd261aa 100644 --- a/libc/intrin/findmemoryinterval.c +++ b/libc/intrin/findmemoryinterval.c @@ -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; diff --git a/libc/intrin/ftrace_enabled.c b/libc/intrin/ftrace_enabled.c index 287c20245..1e448fbe6 100644 --- a/libc/intrin/ftrace_enabled.c +++ b/libc/intrin/ftrace_enabled.c @@ -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) { diff --git a/libc/intrin/getpid.c b/libc/intrin/getpid.c index 128a173bd..94b0fb4f1 100644 --- a/libc/intrin/getpid.c +++ b/libc/intrin/getpid.c @@ -41,7 +41,7 @@ * @threadsafe * @vforksafe */ -dontasan int getpid(void) { +int getpid(void) { int rc; if (IsMetal()) { rc = 1; diff --git a/libc/intrin/handlock.c b/libc/intrin/handlock.c new file mode 100644 index 000000000..742ea4ad6 --- /dev/null +++ b/libc/intrin/handlock.c @@ -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); + } +} diff --git a/libc/intrin/handlock.internal.h b/libc/intrin/handlock.internal.h new file mode 100644 index 000000000..b66405d2d --- /dev/null +++ b/libc/intrin/handlock.internal.h @@ -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_ */ diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk index 373d6fd13..d2181541b 100644 --- a/libc/intrin/intrin.mk +++ b/libc/intrin/intrin.mk @@ -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 diff --git a/libc/intrin/isdebuggerpresent.c b/libc/intrin/isdebuggerpresent.c index bbb48840f..96ecf5ec0 100644 --- a/libc/intrin/isdebuggerpresent.c +++ b/libc/intrin/isdebuggerpresent.c @@ -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; } diff --git a/libc/intrin/memchr.c b/libc/intrin/memchr.c index db81b498d..4b98db885 100644 --- a/libc/intrin/memchr.c +++ b/libc/intrin/memchr.c @@ -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); diff --git a/libc/intrin/memrchr.c b/libc/intrin/memrchr.c index f47f36bfc..aee1d67f5 100644 --- a/libc/intrin/memrchr.c +++ b/libc/intrin/memrchr.c @@ -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}; diff --git a/libc/intrin/mman.greg.c b/libc/intrin/mman.greg.c index 1319b5d4f..f6f9ae3b6 100644 --- a/libc/intrin/mman.greg.c +++ b/libc/intrin/mman.greg.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; diff --git a/libc/intrin/nocolor.c b/libc/intrin/nocolor.c index 60ad3efa9..09109427f 100644 --- a/libc/intrin/nocolor.c +++ b/libc/intrin/nocolor.c @@ -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)); diff --git a/libc/intrin/ntgetversion.c b/libc/intrin/ntgetversion.c index 5b88bce1c..e57b09ca3 100644 --- a/libc/intrin/ntgetversion.c +++ b/libc/intrin/ntgetversion.c @@ -27,7 +27,7 @@ * * @see IsAtLeastWindows10() */ -textwindows dontasan int NtGetVersion(void) { +textwindows int NtGetVersion(void) { return (NtGetPeb()->OSMajorVersion & 0xff) << 8 | NtGetPeb()->OSMinorVersion; } diff --git a/libc/intrin/stpcpy.c b/libc/intrin/stpcpy.c index ba7b97a63..475dcdc2c 100644 --- a/libc/intrin/stpcpy.c +++ b/libc/intrin/stpcpy.c @@ -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); diff --git a/libc/intrin/strace.internal.h b/libc/intrin/strace.internal.h index 55455e4bc..141b50308 100644 --- a/libc/intrin/strace.internal.h +++ b/libc/intrin/strace.internal.h @@ -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 " diff --git a/libc/intrin/strace_enabled.c b/libc/intrin/strace_enabled.c index c5c42a1f1..e3783b36c 100644 --- a/libc/intrin/strace_enabled.c +++ b/libc/intrin/strace_enabled.c @@ -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) { diff --git a/libc/intrin/strchr.c b/libc/intrin/strchr.c index 4651a4ffe..cfad794a9 100644 --- a/libc/intrin/strchr.c +++ b/libc/intrin/strchr.c @@ -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; diff --git a/libc/intrin/strchrnul.c b/libc/intrin/strchrnul.c index 5ab232bda..1addf586c 100644 --- a/libc/intrin/strchrnul.c +++ b/libc/intrin/strchrnul.c @@ -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) { diff --git a/libc/intrin/strcmp.c b/libc/intrin/strcmp.c index 8e085acdd..a6a164ee7 100644 --- a/libc/intrin/strcmp.c +++ b/libc/intrin/strcmp.c @@ -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; diff --git a/libc/intrin/strcpy.c b/libc/intrin/strcpy.c index ad5986fed..5176c47a1 100644 --- a/libc/intrin/strcpy.c +++ b/libc/intrin/strcpy.c @@ -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); diff --git a/libc/intrin/strerror_r.c b/libc/intrin/strerror_r.c index 77d91074a..0a22a8d6e 100644 --- a/libc/intrin/strerror_r.c +++ b/libc/intrin/strerror_r.c @@ -25,7 +25,7 @@ // clang-format off #if defined(SYSDEBUG) && _NTTRACE -dontasan dontubsan privileged +privileged #endif /** diff --git a/libc/intrin/strerror_wr.greg.c b/libc/intrin/strerror_wr.greg.c index 38a98a9a2..df65d2f9f 100644 --- a/libc/intrin/strerror_wr.greg.c +++ b/libc/intrin/strerror_wr.greg.c @@ -30,7 +30,7 @@ // clang-format off #if defined(SYSDEBUG) && _NTTRACE -dontasan dontubsan privileged +privileged #endif /** diff --git a/libc/intrin/strlen.c b/libc/intrin/strlen.c index 1b0f77433..9004a1949 100644 --- a/libc/intrin/strlen.c +++ b/libc/intrin/strlen.c @@ -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))); diff --git a/libc/intrin/strnlen.c b/libc/intrin/strnlen.c index 02dd4aee4..f8bb64328 100644 --- a/libc/intrin/strnlen.c +++ b/libc/intrin/strnlen.c @@ -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) { diff --git a/libc/intrin/strrchr.c b/libc/intrin/strrchr.c index 59a230c71..bcbbf34f3 100644 --- a/libc/intrin/strrchr.c +++ b/libc/intrin/strrchr.c @@ -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__ */ diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c index 845ccbda2..4caefa948 100644 --- a/libc/runtime/fork-nt.c +++ b/libc/runtime/fork-nt.c @@ -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)) && diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index f07723e8a..7d1325310 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -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); diff --git a/libc/sock/socketpair-nt.c b/libc/sock/socketpair-nt.c index c5180d5fc..dffeced49 100644 --- a/libc/sock/socketpair-nt.c +++ b/libc/sock/socketpair-nt.c @@ -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(); diff --git a/libc/stdio/posix_spawn.c b/libc/stdio/posix_spawn.c index 3ca50e6c7..bade9ef96 100644 --- a/libc/stdio/posix_spawn.c +++ b/libc/stdio/posix_spawn.c @@ -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); diff --git a/libc/thread/pthread_atfork.c b/libc/thread/pthread_atfork.c index ce6674ada..4ce0519fb 100644 --- a/libc/thread/pthread_atfork.c +++ b/libc/thread/pthread_atfork.c @@ -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); diff --git a/test/libc/stdio/posix_spawn_test.c b/test/libc/stdio/posix_spawn_test.c index ba149861f..390426d59 100644 --- a/test/libc/stdio/posix_spawn_test.c +++ b/test/libc/stdio/posix_spawn_test.c @@ -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); diff --git a/test/libc/intrin/pthread_atfork_test.c b/test/libc/thread/pthread_atfork_test.c similarity index 100% rename from test/libc/intrin/pthread_atfork_test.c rename to test/libc/thread/pthread_atfork_test.c