Fix _Thread_local with fork() on Windows

This commit is contained in:
Justine Tunney 2022-08-21 15:51:44 -07:00
parent 99a92048b4
commit bf757c4646
5 changed files with 51 additions and 2 deletions

Binary file not shown.

View file

@ -29,11 +29,11 @@
#include "libc/sysv/consts/sicode.h" #include "libc/sysv/consts/sicode.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
privileged unsigned __wincrash(struct NtExceptionPointers *ep) { unsigned __wincrash(struct NtExceptionPointers *ep) {
int64_t rip; int64_t rip;
int sig, code; int sig, code;
ucontext_t ctx; ucontext_t ctx;
STRACE("__wincrash"); STRACE("__wincrash rip=%lx", ep->ContextRecord->Rip);
switch (ep->ExceptionRecord->ExceptionCode) { switch (ep->ExceptionRecord->ExceptionCode) {
case kNtSignalBreakpoint: case kNtSignalBreakpoint:

View file

@ -88,6 +88,7 @@ static inline textwindows ssize_t ForkIo(int64_t h, char *p, size_t n,
static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n, static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
bool32 (*fn)(), const char *sf) { bool32 (*fn)(), const char *sf) {
ssize_t rc = ForkIo(h, buf, n, fn); ssize_t rc = ForkIo(h, buf, n, fn);
__tls_enabled = false; // prevent tls crash in kprintf
NTTRACE("%s(%ld, %p, %'zu) → %'zd% m", sf, h, buf, n, rc); NTTRACE("%s(%ld, %p, %'zu) → %'zd% m", sf, h, buf, n, rc);
return rc != -1; return rc != -1;
} }
@ -218,6 +219,9 @@ textwindows void WinMainForked(void) {
AbortFork("CloseHandle"); AbortFork("CloseHandle");
} }
// turn tls back on
__enable_tls();
// rewrap the stdin named pipe hack // rewrap the stdin named pipe hack
// since the handles closed on fork // since the handles closed on fork
struct Fds *fds = VEIL("r", &g_fds); struct Fds *fds = VEIL("r", &g_fds);

View file

@ -27,6 +27,13 @@
#define XED_HINT_TAKEN 4 #define XED_HINT_TAKEN 4
#define XED_HINT_ALTER 6 #define XED_HINT_ALTER 6
#define XED_SEG_ES 1
#define XED_SEG_CS 2
#define XED_SEG_SS 3
#define XED_SEG_DS 4
#define XED_SEG_FS 5
#define XED_SEG_GS 6
#define xed_modrm_mod(M) (((M)&0xff) >> 6) #define xed_modrm_mod(M) (((M)&0xff) >> 6)
#define xed_modrm_reg(M) (((M)&0b00111000) >> 3) #define xed_modrm_reg(M) (((M)&0b00111000) >> 3)
#define xed_modrm_rm(M) ((M)&7) #define xed_modrm_rm(M) ((M)&7)

View file

@ -26,6 +26,7 @@
#include "libc/elf/struct/sym.h" #include "libc/elf/struct/sym.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/fmt/itoa.h" #include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/safemacros.internal.h" #include "libc/intrin/safemacros.internal.h"
#include "libc/log/check.h" #include "libc/log/check.h"
#include "libc/log/log.h" #include "libc/log/log.h"
@ -36,6 +37,7 @@
#include "libc/sysv/consts/o.h" #include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#include "third_party/getopt/getopt.h" #include "third_party/getopt/getopt.h"
#include "third_party/xed/x86.h"
/** /**
* @fileoverview GCC Codegen Fixer-Upper. * @fileoverview GCC Codegen Fixer-Upper.
@ -151,6 +153,41 @@ void OptimizeRelocations(Elf64_Ehdr *elf, size_t elfsize) {
} }
} }
void CheckForTlsInPrivileged(const char *path, Elf64_Ehdr *elf,
size_t elfsize) {
int err;
size_t m;
Elf64_Half i;
struct Op *op;
Elf64_Shdr *shdr;
unsigned char *p, *e;
Elf64_Xword symcount;
struct XedDecodedInst xedd;
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, elfsize, i);
if (shdr->sh_type == SHT_PROGBITS &&
startswith(GetElfSectionName(elf, elfsize, shdr), ".privileged")) {
p = (unsigned char *)((uintptr_t)elf + shdr->sh_offset);
e = p + shdr->sh_size;
for (; p < e; p += m) {
xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
err = xed_instruction_length_decode(&xedd, p, e - p);
if (err == XED_ERROR_NONE) {
m = xedd.length;
if (xedd.op.seg_ovd == XED_SEG_FS) {
kprintf("%s: thread local storage not allowed in privileged "
"functions\n",
path);
exit(1);
}
} else {
m = 1;
}
}
}
}
}
void RewriteObject(const char *path) { void RewriteObject(const char *path) {
int fd; int fd;
struct stat st; struct stat st;
@ -166,6 +203,7 @@ void RewriteObject(const char *path) {
0)) == MAP_FAILED) { 0)) == MAP_FAILED) {
SysExit(__COUNTER__ + 1, "mmap", path); SysExit(__COUNTER__ + 1, "mmap", path);
} }
CheckForTlsInPrivileged(path, elf, st.st_size);
OptimizeRelocations(elf, st.st_size); OptimizeRelocations(elf, st.st_size);
if (msync(elf, st.st_size, MS_ASYNC | MS_INVALIDATE)) { if (msync(elf, st.st_size, MS_ASYNC | MS_INVALIDATE)) {
SysExit(__COUNTER__ + 1, "msync", path); SysExit(__COUNTER__ + 1, "msync", path);