mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-12 09:17:53 +00:00
Avoid leaking handles across processes
This commit is contained in:
parent
a359de7893
commit
8a0008d985
44 changed files with 232 additions and 266 deletions
|
@ -61,7 +61,7 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
|
||||||
handle = g_fds.p[oldfd].handle;
|
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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) ||
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
62
libc/intrin/handlock.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/weaken.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/thread/tls.h"
|
||||||
|
#include "third_party/nsync/mu.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview r/w lock for maanging windows file inheritence
|
||||||
|
*/
|
||||||
|
|
||||||
|
static nsync_mu __hand_mu;
|
||||||
|
|
||||||
|
void __hand_init(void) {
|
||||||
|
if (!SupportsWindows()) return;
|
||||||
|
bzero(&__hand_mu, sizeof(__hand_mu));
|
||||||
|
}
|
||||||
|
|
||||||
|
void __hand_rlock(void) {
|
||||||
|
if (!IsWindows()) return;
|
||||||
|
if (_weaken(nsync_mu_rlock) && __threaded) {
|
||||||
|
_weaken(nsync_mu_rlock)(&__hand_mu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __hand_runlock(void) {
|
||||||
|
if (!IsWindows()) return;
|
||||||
|
if (_weaken(nsync_mu_runlock) && __threaded) {
|
||||||
|
_weaken(nsync_mu_runlock)(&__hand_mu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __hand_lock(void) {
|
||||||
|
if (!IsWindows()) return;
|
||||||
|
if (_weaken(nsync_mu_lock) && __threaded) {
|
||||||
|
_weaken(nsync_mu_lock)(&__hand_mu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __hand_unlock(void) {
|
||||||
|
if (!IsWindows()) return;
|
||||||
|
if (_weaken(nsync_mu_unlock) && __threaded) {
|
||||||
|
_weaken(nsync_mu_unlock)(&__hand_mu);
|
||||||
|
}
|
||||||
|
}
|
14
libc/intrin/handlock.internal.h
Normal file
14
libc/intrin/handlock.internal.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_INTRIN_HANDLOCK_INTERNAL_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_INTRIN_HANDLOCK_INTERNAL_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
void __hand_init(void);
|
||||||
|
void __hand_rlock(void);
|
||||||
|
void __hand_runlock(void);
|
||||||
|
void __hand_lock(void);
|
||||||
|
void __hand_unlock(void);
|
||||||
|
|
||||||
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_INTRIN_HANDLOCK_INTERNAL_H_ */
|
|
@ -46,31 +46,11 @@ $(LIBC_INTRIN_A).pkg: \
|
||||||
$(LIBC_INTRIN_A_OBJS) \
|
$(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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 "
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _NTTRACE
|
#if defined(SYSDEBUG) && _NTTRACE
|
||||||
dontasan dontubsan privileged
|
privileged
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
#if defined(SYSDEBUG) && _NTTRACE
|
#if defined(SYSDEBUG) && _NTTRACE
|
||||||
dontasan dontubsan privileged
|
privileged
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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)));
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
|
@ -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)) &&
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue