mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-01 03:53:33 +00:00
e466dd0553
This change hardens the code for opening /zip/ files using the system call interface. Thread safety and signal safety has been improved for file descriptors in general. We now document fixed addresses that are needed for low level allocations.
127 lines
5.4 KiB
C
127 lines
5.4 KiB
C
/*-*- 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 2022 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/assert.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/dce.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/nexgen32e/threaded.h"
|
|
#include "libc/nt/thread.h"
|
|
#include "libc/nt/thunk/msabi.h"
|
|
#include "libc/sysv/consts/nrlinux.h"
|
|
|
|
#define __NR_sysarch 0x000000a5 // freebsd+netbsd
|
|
#define AMD64_SET_GSBASE 131 // freebsd
|
|
#define AMD64_SET_FSBASE 129 // freebsd
|
|
#define X86_SET_GSBASE 16 // netbsd
|
|
#define X86_SET_FSBASE 17 // netbsd
|
|
|
|
#define __NR___set_tcb 0x00000149
|
|
#define __NR__lwp_setprivate 0x0000013d
|
|
#define __NR_thread_fast_set_cthread_self 0x03000003
|
|
|
|
/**
|
|
* Initializes thread information block.
|
|
*
|
|
* Here's the layout your c library assumes:
|
|
*
|
|
* offset size description
|
|
* 0x0000 0x08 linear address pointer
|
|
* 0x0030 0x08 linear address pointer
|
|
* 0x0038 0x04 tid
|
|
* 0x003c 0x04 errno
|
|
*
|
|
*/
|
|
privileged void *__initialize_tls(char tib[64]) {
|
|
if (tib) {
|
|
*(intptr_t *)tib = (intptr_t)tib;
|
|
*(intptr_t *)(tib + 0x30) = (intptr_t)tib;
|
|
*(int *)(tib + 0x38) = -1; // tid
|
|
*(int *)(tib + 0x3c) = 0;
|
|
}
|
|
return tib;
|
|
}
|
|
|
|
/**
|
|
* Installs thread information block on main process.
|
|
*
|
|
* For example, to set up TLS correctly for the main thread, without
|
|
* creating any threads, then it's sufficient to say:
|
|
*
|
|
* __attribute__((__constructor__)) static void InitTls(void) {
|
|
* static char tls[64];
|
|
* __initialize_tls(tls);
|
|
* *(int *)(tls + 0x38) = gettid();
|
|
* *(int *)(tls + 0x3c) = __errno;
|
|
* __install_tls(tls);
|
|
* }
|
|
*
|
|
* We use a constructor here to make sure it only happens once. Please
|
|
* note that calling `clone` will do this automatically.
|
|
*
|
|
* Installing TLS causes the `__tls_enabled` variable to be set. This
|
|
* causes C library features such as `errno` and `gettid()` to use TLS.
|
|
* This can help things like recursive mutexes go significantly faster.
|
|
*
|
|
* To access your TLS storage, you can call `__get_tls()` or
|
|
* __get_tls_inline()` which return the address of the `tib`.
|
|
*
|
|
* @param tib is your thread information block, which must have at least
|
|
* 64 bytes on the righthand side of the tib pointer since those are
|
|
* the values your C library reserves for itself. memory on the left
|
|
* side of the pointer is reserved by the linker for _Thread_local.
|
|
*/
|
|
privileged void __install_tls(char tib[64]) {
|
|
int ax, dx;
|
|
assert(tib);
|
|
assert(!__tls_enabled);
|
|
assert(*(int *)(tib + 0x38) != -1);
|
|
if (IsWindows()) {
|
|
if (!__tls_index) {
|
|
__tls_index = TlsAlloc();
|
|
}
|
|
asm("mov\t%1,%%gs:%0" : "=m"(*((long *)0x1480 + __tls_index)) : "r"(tib));
|
|
} else if (IsFreebsd()) {
|
|
asm volatile("syscall"
|
|
: "=a"(ax)
|
|
: "0"(__NR_sysarch), "D"(AMD64_SET_FSBASE), "S"(tib)
|
|
: "rcx", "r11", "memory", "cc");
|
|
} else if (IsNetbsd()) {
|
|
asm volatile("syscall"
|
|
: "=a"(ax), "=d"(dx)
|
|
: "0"(__NR_sysarch), "D"(X86_SET_FSBASE), "S"(tib)
|
|
: "rcx", "r11", "memory", "cc");
|
|
} else if (IsXnu()) {
|
|
asm volatile("syscall"
|
|
: "=a"(ax)
|
|
: "0"(__NR_thread_fast_set_cthread_self),
|
|
"D"((intptr_t)tib - 0x30)
|
|
: "rcx", "r11", "memory", "cc");
|
|
} else if (IsOpenbsd()) {
|
|
asm volatile("syscall"
|
|
: "=a"(ax)
|
|
: "0"(__NR___set_tcb), "D"(tib)
|
|
: "rcx", "r11", "memory", "cc");
|
|
} else {
|
|
asm volatile("syscall"
|
|
: "=a"(ax)
|
|
: "0"(__NR_linux_arch_prctl), "D"(ARCH_SET_FS), "S"(tib)
|
|
: "rcx", "r11", "memory");
|
|
}
|
|
__tls_enabled = true;
|
|
}
|