aboutsummaryrefslogtreecommitdiffstats
path: root/main/musl/0001-v1.0.0-to-2b74315d.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/musl/0001-v1.0.0-to-2b74315d.patch')
-rw-r--r--main/musl/0001-v1.0.0-to-2b74315d.patch810
1 files changed, 0 insertions, 810 deletions
diff --git a/main/musl/0001-v1.0.0-to-2b74315d.patch b/main/musl/0001-v1.0.0-to-2b74315d.patch
deleted file mode 100644
index 57ca3e469c..0000000000
--- a/main/musl/0001-v1.0.0-to-2b74315d.patch
+++ /dev/null
@@ -1,810 +0,0 @@
-git diff v1.0.0...2b74315d8a31ad8fbcd369116c82e055e0ec3fb7
-
-diff --git a/src/conf/confstr.c b/src/conf/confstr.c
-index 4332f72..6e9c23a 100644
---- a/src/conf/confstr.c
-+++ b/src/conf/confstr.c
-@@ -13,5 +13,5 @@ size_t confstr(int name, char *buf, size_t len)
- }
- // snprintf is overkill but avoid wasting code size to implement
- // this completely useless function and its truncation semantics
-- return snprintf(buf, len, "%s", s);
-+ return snprintf(buf, len, "%s", s) + 1;
- }
-diff --git a/src/env/__init_security.c b/src/env/__init_security.c
-index 6204c5e..da5ae94 100644
---- a/src/env/__init_security.c
-+++ b/src/env/__init_security.c
-@@ -15,9 +15,7 @@ void __init_security(size_t *aux)
- struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} };
- int i;
-
--#ifndef SHARED
- __init_ssp((void *)aux[AT_RANDOM]);
--#endif
-
- if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID]
- && !aux[AT_SECURE]) return;
-diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
-index 5c17681..8ac0036 100644
---- a/src/env/__init_tls.c
-+++ b/src/env/__init_tls.c
-@@ -5,9 +5,30 @@
- #include "pthread_impl.h"
- #include "libc.h"
- #include "atomic.h"
-+#include "syscall.h"
-+
-+int __init_tp(void *p)
-+{
-+ pthread_t td = p;
-+ td->self = td;
-+ if (__set_thread_area(TP_ADJ(p)) < 0)
-+ return -1;
-+ td->tid = td->pid = __syscall(SYS_set_tid_address, &td->tid);
-+ td->errno_ptr = &td->errno_val;
-+ /* Currently, both of these predicates depend in the same thing:
-+ * successful initialization of the thread pointer. However, in
-+ * the future, we may support setups where setting the thread
-+ * pointer is possible but threads other than the main thread
-+ * cannot work, so it's best to keep the predicates separate. */
-+ libc.has_thread_pointer = 1;
-+ libc.can_do_threads = 1;
-+ return 0;
-+}
-
- #ifndef SHARED
-
-+static long long builtin_tls[(sizeof(struct pthread) + 64)/sizeof(long long)];
-+
- struct tls_image {
- void *image;
- size_t len, size, align;
-@@ -61,10 +82,11 @@ typedef Elf64_Phdr Phdr;
-
- void __init_tls(size_t *aux)
- {
-- unsigned char *p, *mem;
-+ unsigned char *p;
- size_t n;
- Phdr *phdr, *tls_phdr=0;
- size_t base = 0;
-+ void *mem;
-
- libc.tls_size = sizeof(struct pthread);
-
-@@ -75,21 +97,38 @@ void __init_tls(size_t *aux)
- if (phdr->p_type == PT_TLS)
- tls_phdr = phdr;
- }
-- if (!tls_phdr) return;
-
-- T.image = (void *)(base + tls_phdr->p_vaddr);
-- T.len = tls_phdr->p_filesz;
-- T.size = tls_phdr->p_memsz;
-- T.align = tls_phdr->p_align;
-+ if (tls_phdr) {
-+ T.image = (void *)(base + tls_phdr->p_vaddr);
-+ T.len = tls_phdr->p_filesz;
-+ T.size = tls_phdr->p_memsz;
-+ T.align = tls_phdr->p_align;
-+ }
-
- T.size += (-T.size - (uintptr_t)T.image) & (T.align-1);
- if (T.align < 4*sizeof(size_t)) T.align = 4*sizeof(size_t);
-
- libc.tls_size = 2*sizeof(void *)+T.size+T.align+sizeof(struct pthread);
-
-- mem = __mmap(0, libc.tls_size, PROT_READ|PROT_WRITE,
-- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-- if (!__install_initial_tls(__copy_tls(mem))) a_crash();
-+ if (libc.tls_size > sizeof builtin_tls) {
-+ mem = (void *)__syscall(
-+#ifdef SYS_mmap2
-+ SYS_mmap2,
-+#else
-+ SYS_mmap,
-+#endif
-+ 0, libc.tls_size, PROT_READ|PROT_WRITE,
-+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-+ /* -4095...-1 cast to void * will crash on dereference anyway,
-+ * so don't bloat the init code checking for error codes and
-+ * explicitly calling a_crash(). */
-+ } else {
-+ mem = builtin_tls;
-+ }
-+
-+ /* Failure to initialize thread pointer is fatal if TLS is used. */
-+ if (__init_tp(__copy_tls(mem)) < 0 && tls_phdr)
-+ a_crash();
- }
- #else
- void __init_tls(size_t *auxv) { }
-diff --git a/src/env/__stack_chk_fail.c b/src/env/__stack_chk_fail.c
-index daa1b07..87ac473 100644
---- a/src/env/__stack_chk_fail.c
-+++ b/src/env/__stack_chk_fail.c
-@@ -1,18 +1,16 @@
- #include <string.h>
- #include <stdint.h>
- #include "pthread_impl.h"
--#include "atomic.h"
-
- uintptr_t __stack_chk_guard;
-
- void __init_ssp(void *entropy)
- {
-- pthread_t self = __pthread_self_init();
-- uintptr_t canary;
-- if (entropy) memcpy(&canary, entropy, sizeof canary);
-- else canary = (uintptr_t)&canary * 1103515245;
-- a_cas_l(&__stack_chk_guard, 0, canary);
-- self->canary = __stack_chk_guard;
-+ if (entropy) memcpy(&__stack_chk_guard, entropy, sizeof(uintptr_t));
-+ else __stack_chk_guard = (uintptr_t)&__stack_chk_guard * 1103515245;
-+
-+ if (libc.has_thread_pointer)
-+ __pthread_self()->canary = __stack_chk_guard;
- }
-
- void __stack_chk_fail(void)
-diff --git a/src/errno/__errno_location.c b/src/errno/__errno_location.c
-index 3e92d7c..8419107 100644
---- a/src/errno/__errno_location.c
-+++ b/src/errno/__errno_location.c
-@@ -3,6 +3,6 @@
- int *__errno_location(void)
- {
- static int e;
-- if (libc.main_thread) return __pthread_self()->errno_ptr;
-+ if (libc.has_thread_pointer) return __pthread_self()->errno_ptr;
- return &e;
- }
-diff --git a/src/internal/libc.h b/src/internal/libc.h
-index d625b56..fb4d9bc 100644
---- a/src/internal/libc.h
-+++ b/src/internal/libc.h
-@@ -6,12 +6,12 @@
- #include <limits.h>
-
- struct __libc {
-- void *main_thread;
-+ int has_thread_pointer;
-+ int can_do_threads;
- int threaded;
- int secure;
- size_t *auxv;
- volatile int threads_minus_1;
-- int canceldisable;
- FILE *ofl_head;
- int ofl_lock[2];
- size_t tls_size;
-diff --git a/src/internal/syscall_ret.c b/src/internal/syscall_ret.c
-index d99f4a5..a3f4713 100644
---- a/src/internal/syscall_ret.c
-+++ b/src/internal/syscall_ret.c
-@@ -1,4 +1,5 @@
- #include <errno.h>
-+#include "syscall.h"
-
- long __syscall_ret(unsigned long r)
- {
-diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
-index a1bdf0f..1517281 100644
---- a/src/ldso/dynlink.c
-+++ b/src/ldso/dynlink.c
-@@ -56,6 +56,7 @@ struct dso {
-
- Phdr *phdr;
- int phnum;
-+ size_t phentsize;
- int refcnt;
- Sym *syms;
- uint32_t *hashtab;
-@@ -74,6 +75,7 @@ struct dso {
- char *rpath_orig, *rpath;
- void *tls_image;
- size_t tls_len, tls_size, tls_align, tls_id, tls_offset;
-+ size_t relro_start, relro_end;
- void **new_dtv;
- unsigned char *new_tls;
- int new_dtv_idx, new_tls_idx;
-@@ -89,8 +91,7 @@ struct symdef {
-
- #include "reloc.h"
-
--void __init_ssp(size_t *);
--void *__install_initial_tls(void *);
-+int __init_tp(void *);
- void __init_libc(char **, char *);
-
- const char *__libc_get_version(void);
-@@ -98,7 +99,6 @@ const char *__libc_get_version(void);
- static struct dso *head, *tail, *ldso, *fini_head;
- static char *env_path, *sys_path;
- static unsigned long long gencnt;
--static int ssp_used;
- static int runtime;
- static int ldd_mode;
- static int ldso_fail;
-@@ -108,6 +108,7 @@ static pthread_rwlock_t lock;
- static struct debug debug;
- static size_t tls_cnt, tls_offset, tls_align = 4*sizeof(size_t);
- static pthread_mutex_t init_fini_lock = { ._m_type = PTHREAD_MUTEX_RECURSIVE };
-+static long long builtin_tls[(sizeof(struct pthread) + 64)/sizeof(long long)];
-
- struct debug *_dl_debug_addr = &debug;
-
-@@ -198,13 +199,6 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
- {
- uint32_t h = 0, gh = 0;
- struct symdef def = {0};
-- if (dso->ghashtab) {
-- gh = gnu_hash(s);
-- if (gh == 0x1f4039c9 && !strcmp(s, "__stack_chk_fail")) ssp_used = 1;
-- } else {
-- h = sysv_hash(s);
-- if (h == 0x595a4cc && !strcmp(s, "__stack_chk_fail")) ssp_used = 1;
-- }
- for (; dso; dso=dso->next) {
- Sym *sym;
- if (!dso->global) continue;
-@@ -280,27 +274,32 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
- * and "donate" them to the heap by setting up minimal malloc
- * structures and then freeing them. */
-
--static void reclaim(unsigned char *base, size_t start, size_t end)
-+static void reclaim(struct dso *dso, size_t start, size_t end)
- {
- size_t *a, *z;
-+ if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end;
-+ if (end >= dso->relro_start && end < dso->relro_end) end = dso->relro_start;
- start = start + 6*sizeof(size_t)-1 & -4*sizeof(size_t);
- end = (end & -4*sizeof(size_t)) - 2*sizeof(size_t);
- if (start>end || end-start < 4*sizeof(size_t)) return;
-- a = (size_t *)(base + start);
-- z = (size_t *)(base + end);
-+ a = (size_t *)(dso->base + start);
-+ z = (size_t *)(dso->base + end);
- a[-2] = 1;
- a[-1] = z[0] = end-start + 2*sizeof(size_t) | 1;
- z[1] = 1;
- free(a);
- }
-
--static void reclaim_gaps(unsigned char *base, Phdr *ph, size_t phent, size_t phcnt)
-+static void reclaim_gaps(struct dso *dso)
- {
-- for (; phcnt--; ph=(void *)((char *)ph+phent)) {
-+ Phdr *ph = dso->phdr;
-+ size_t phcnt = dso->phnum;
-+
-+ for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
- if (ph->p_type!=PT_LOAD) continue;
- if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
-- reclaim(base, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
-- reclaim(base, ph->p_vaddr+ph->p_memsz,
-+ reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
-+ reclaim(dso, ph->p_vaddr+ph->p_memsz,
- ph->p_vaddr+ph->p_memsz+PAGE_SIZE-1 & -PAGE_SIZE);
- }
- }
-@@ -343,13 +342,16 @@ static void *map_library(int fd, struct dso *dso)
- ph = ph0 = (void *)((char *)buf + eh->e_phoff);
- }
- for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) {
-- if (ph->p_type == PT_DYNAMIC)
-+ if (ph->p_type == PT_DYNAMIC) {
- dyn = ph->p_vaddr;
-- if (ph->p_type == PT_TLS) {
-+ } else if (ph->p_type == PT_TLS) {
- tls_image = ph->p_vaddr;
- dso->tls_align = ph->p_align;
- dso->tls_len = ph->p_filesz;
- dso->tls_size = ph->p_memsz;
-+ } else if (ph->p_type == PT_GNU_RELRO) {
-+ dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
-+ dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
- }
- if (ph->p_type != PT_LOAD) continue;
- if (ph->p_vaddr < addr_min) {
-@@ -393,6 +395,7 @@ static void *map_library(int fd, struct dso *dso)
- dso->phdr = (void *)(base + ph->p_vaddr
- + (eh->e_phoff-ph->p_offset));
- dso->phnum = eh->e_phnum;
-+ dso->phentsize = eh->e_phentsize;
- }
- /* Reuse the existing mapping for the lowest-address LOAD */
- if ((ph->p_vaddr & -PAGE_SIZE) == addr_min) continue;
-@@ -418,12 +421,12 @@ static void *map_library(int fd, struct dso *dso)
- goto error;
- break;
- }
-- if (!runtime) reclaim_gaps(base, ph0, eh->e_phentsize, eh->e_phnum);
- dso->map = map;
- dso->map_len = map_len;
- dso->base = base;
- dso->dynv = (void *)(base+dyn);
- if (dso->tls_size) dso->tls_image = (void *)(base+tls_image);
-+ if (!runtime) reclaim_gaps(dso);
- free(allocated_buf);
- return map;
- noexec:
-@@ -673,9 +676,10 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
- /* Add a shortname only if name arg was not an explicit pathname. */
- if (pathname != name) p->shortname = strrchr(p->name, '/')+1;
- if (p->tls_image) {
-- if (runtime && !__pthread_self_init()) {
-+ if (runtime && !libc.has_thread_pointer) {
- munmap(map, p->map_len);
- free(p);
-+ errno = ENOSYS;
- return 0;
- }
- p->tls_id = ++tls_cnt;
-@@ -764,22 +768,32 @@ static void reloc_all(struct dso *p)
- 2+(dyn[DT_PLTREL]==DT_RELA));
- do_relocs(p, (void *)(p->base+dyn[DT_REL]), dyn[DT_RELSZ], 2);
- do_relocs(p, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ], 3);
-+
-+ if (p->relro_start != p->relro_end &&
-+ mprotect(p->base+p->relro_start, p->relro_end-p->relro_start, PROT_READ) < 0) {
-+ snprintf(errbuf, sizeof errbuf,
-+ "Error relocating %s: RELRO protection failed: %m",
-+ p->name);
-+ if (runtime) longjmp(*rtld_fail, 1);
-+ dprintf(2, "%s\n", errbuf);
-+ ldso_fail = 1;
-+ }
-+
- p->relocated = 1;
- }
- }
-
--static size_t find_dyn(Phdr *ph, size_t cnt, size_t stride)
-+static void kernel_mapped_dso(struct dso *p)
- {
-- for (; cnt--; ph = (void *)((char *)ph + stride))
-- if (ph->p_type == PT_DYNAMIC)
-- return ph->p_vaddr;
-- return 0;
--}
--
--static void find_map_range(Phdr *ph, size_t cnt, size_t stride, struct dso *p)
--{
-- size_t min_addr = -1, max_addr = 0;
-- for (; cnt--; ph = (void *)((char *)ph + stride)) {
-+ size_t min_addr = -1, max_addr = 0, cnt;
-+ Phdr *ph = p->phdr;
-+ for (cnt = p->phnum; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
-+ if (ph->p_type == PT_DYNAMIC) {
-+ p->dynv = (void *)(p->base + ph->p_vaddr);
-+ } else if (ph->p_type == PT_GNU_RELRO) {
-+ p->relro_start = ph->p_vaddr & -PAGE_SIZE;
-+ p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
-+ }
- if (ph->p_type != PT_LOAD) continue;
- if (ph->p_vaddr < min_addr)
- min_addr = ph->p_vaddr;
-@@ -790,6 +804,7 @@ static void find_map_range(Phdr *ph, size_t cnt, size_t stride, struct dso *p)
- max_addr = (max_addr + PAGE_SIZE-1) & -PAGE_SIZE;
- p->map = p->base + min_addr;
- p->map_len = max_addr - min_addr;
-+ p->kernel_mapped = 1;
- }
-
- static void do_fini()
-@@ -866,10 +881,13 @@ void *__copy_tls(unsigned char *mem)
- pthread_t td;
- struct dso *p;
-
-- if (!tls_cnt) return mem;
--
- void **dtv = (void *)mem;
- dtv[0] = (void *)tls_cnt;
-+ if (!tls_cnt) {
-+ td = (void *)(dtv+1);
-+ td->dtv = dtv;
-+ return td;
-+ }
-
- #ifdef TLS_ABOVE_TP
- mem += sizeof(void *) * (tls_cnt+1);
-@@ -962,6 +980,7 @@ void *__dynlink(int argc, char **argv)
- size_t vdso_base;
- size_t *auxv;
- char **envp = argv+argc+1;
-+ void *initial_tls;
-
- /* Find aux vector just past environ[] */
- for (i=argc+1; argv[i]; i++)
-@@ -996,13 +1015,11 @@ void *__dynlink(int argc, char **argv)
- lib->base = (void *)aux[AT_BASE];
- lib->name = lib->shortname = "libc.so";
- lib->global = 1;
-- lib->kernel_mapped = 1;
- ehdr = (void *)lib->base;
- lib->phnum = ehdr->e_phnum;
- lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff);
-- find_map_range(lib->phdr, ehdr->e_phnum, ehdr->e_phentsize, lib);
-- lib->dynv = (void *)(lib->base + find_dyn(lib->phdr,
-- ehdr->e_phnum, ehdr->e_phentsize));
-+ lib->phentsize = ehdr->e_phentsize;
-+ kernel_mapped_dso(lib);
- decode_dyn(lib);
-
- if (aux[AT_PHDR]) {
-@@ -1011,6 +1028,7 @@ void *__dynlink(int argc, char **argv)
- /* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
- app->phdr = phdr = (void *)aux[AT_PHDR];
- app->phnum = aux[AT_PHNUM];
-+ app->phentsize = aux[AT_PHENT];
- for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
- if (phdr->p_type == PT_PHDR)
- app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
-@@ -1030,11 +1048,7 @@ void *__dynlink(int argc, char **argv)
- app->name = (char *)aux[AT_EXECFN];
- else
- app->name = argv[0];
-- app->kernel_mapped = 1;
-- app->dynv = (void *)(app->base + find_dyn(
-- (void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT]));
-- find_map_range((void *)aux[AT_PHDR],
-- aux[AT_PHNUM], aux[AT_PHENT], app);
-+ kernel_mapped_dso(app);
- } else {
- int fd;
- char *ldname = argv[0];
-@@ -1100,6 +1114,7 @@ void *__dynlink(int argc, char **argv)
- ehdr = (void *)vdso_base;
- vdso->phdr = phdr = (void *)(vdso_base + ehdr->e_phoff);
- vdso->phnum = ehdr->e_phnum;
-+ vdso->phentsize = ehdr->e_phentsize;
- for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
- if (phdr->p_type == PT_DYNAMIC)
- vdso->dynv = (void *)(vdso_base + phdr->p_offset);
-@@ -1127,10 +1142,8 @@ void *__dynlink(int argc, char **argv)
- /* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */
-
- /* Donate unused parts of app and library mapping to malloc */
-- reclaim_gaps(app->base, (void *)aux[AT_PHDR], aux[AT_PHENT], aux[AT_PHNUM]);
-- ehdr = (void *)lib->base;
-- reclaim_gaps(lib->base, (void *)(lib->base+ehdr->e_phoff),
-- ehdr->e_phentsize, ehdr->e_phnum);
-+ reclaim_gaps(app);
-+ reclaim_gaps(lib);
-
- /* Load preload/needed libraries, add their symbols to the global
- * namespace, and perform all remaining relocations. The main
-@@ -1140,19 +1153,29 @@ void *__dynlink(int argc, char **argv)
- load_deps(app);
- make_global(app);
-
-+#ifndef DYNAMIC_IS_RO
-+ for (i=0; app->dynv[i]; i+=2)
-+ if (app->dynv[i]==DT_DEBUG)
-+ app->dynv[i+1] = (size_t)&debug;
-+#endif
-+
- reloc_all(app->next);
- reloc_all(app);
-
- update_tls_size();
-- if (tls_cnt) {
-- void *mem = mmap(0, libc.tls_size, PROT_READ|PROT_WRITE,
-- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
-- if (mem==MAP_FAILED ||
-- !__install_initial_tls(__copy_tls(mem))) {
-+ if (libc.tls_size > sizeof builtin_tls) {
-+ initial_tls = calloc(libc.tls_size, 1);
-+ if (!initial_tls) {
- dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
- argv[0], libc.tls_size);
- _exit(127);
- }
-+ } else {
-+ initial_tls = builtin_tls;
-+ }
-+ if (__init_tp(__copy_tls(initial_tls)) < 0 && tls_cnt) {
-+ dprintf(2, "%s: Thread-local storage not supported by kernel.\n", argv[0]);
-+ _exit(127);
- }
-
- if (ldso_fail) _exit(127);
-@@ -1164,11 +1187,6 @@ void *__dynlink(int argc, char **argv)
- * all memory used by the dynamic linker. */
- runtime = 1;
-
--#ifndef DYNAMIC_IS_RO
-- for (i=0; app->dynv[i]; i+=2)
-- if (app->dynv[i]==DT_DEBUG)
-- app->dynv[i+1] = (size_t)&debug;
--#endif
- debug.ver = 1;
- debug.bp = _dl_debug_state;
- debug.head = head;
-@@ -1176,7 +1194,6 @@ void *__dynlink(int argc, char **argv)
- debug.state = 0;
- _dl_debug_state();
-
-- if (ssp_used) __init_ssp((void *)aux[AT_RANDOM]);
- __init_libc(envp, argv[0]);
- atexit(do_fini);
- errno = 0;
-@@ -1258,9 +1275,6 @@ void *dlopen(const char *file, int mode)
- }
-
- update_tls_size();
--
-- if (ssp_used) __init_ssp(libc.auxv);
--
- _dl_debug_state();
- orig_tail = tail;
- end:
-diff --git a/src/process/fork.c b/src/process/fork.c
-index 1a82f42..864c7d7 100644
---- a/src/process/fork.c
-+++ b/src/process/fork.c
-@@ -17,12 +17,11 @@ pid_t fork(void)
- __fork_handler(-1);
- __block_all_sigs(&set);
- ret = syscall(SYS_fork);
-- if (libc.main_thread && !ret) {
-+ if (libc.has_thread_pointer && !ret) {
- pthread_t self = __pthread_self();
-- self->tid = self->pid = syscall(SYS_getpid);
-+ self->tid = self->pid = __syscall(SYS_getpid);
- memset(&self->robust_list, 0, sizeof self->robust_list);
- libc.threads_minus_1 = 0;
-- libc.main_thread = self;
- }
- __restore_sigs(&set);
- __fork_handler(!ret);
-diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c
-index f7ff4a6..d5f4774 100644
---- a/src/signal/sigaction.c
-+++ b/src/signal/sigaction.c
-@@ -8,9 +8,7 @@
-
- void __restore(), __restore_rt();
-
--static pthread_t dummy(void) { return 0; }
--weak_alias(dummy, __pthread_self_def);
--
-+static int unmask_done;
- static unsigned long handler_set[_NSIG/(8*sizeof(long))];
-
- void __get_handler_set(sigset_t *set)
-@@ -29,7 +27,20 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
- if ((uintptr_t)sa->sa_handler > 1UL) {
- a_or_l(handler_set+(sig-1)/(8*sizeof(long)),
- 1UL<<(sig-1)%(8*sizeof(long)));
-- __pthread_self_def();
-+
-+ /* If pthread_create has not yet been called,
-+ * implementation-internal signals might not
-+ * yet have been unblocked. They must be
-+ * unblocked before any signal handler is
-+ * installed, so that an application cannot
-+ * receive an illegal sigset_t (with them
-+ * blocked) as part of the ucontext_t passed
-+ * to the signal handler. */
-+ if (!libc.threaded && !unmask_done) {
-+ __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
-+ SIGPT_SET, 0, _NSIG/8);
-+ unmask_done = 1;
-+ }
- }
- ksa.handler = sa->sa_handler;
- ksa.flags = sa->sa_flags | SA_RESTORER;
-diff --git a/src/stdio/__stdio_read.c b/src/stdio/__stdio_read.c
-index 05e56f9..6cd7b07 100644
---- a/src/stdio/__stdio_read.c
-+++ b/src/stdio/__stdio_read.c
-@@ -16,13 +16,9 @@ size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
- };
- ssize_t cnt;
-
-- if (libc.main_thread) {
-- pthread_cleanup_push(cleanup, f);
-- cnt = syscall_cp(SYS_readv, f->fd, iov, 2);
-- pthread_cleanup_pop(0);
-- } else {
-- cnt = syscall(SYS_readv, f->fd, iov, 2);
-- }
-+ pthread_cleanup_push(cleanup, f);
-+ cnt = syscall_cp(SYS_readv, f->fd, iov, 2);
-+ pthread_cleanup_pop(0);
- if (cnt <= 0) {
- f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
- f->rpos = f->rend = 0;
-diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c
-index e52e91a..8c89389 100644
---- a/src/stdio/__stdio_write.c
-+++ b/src/stdio/__stdio_write.c
-@@ -19,13 +19,9 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
- int iovcnt = 2;
- ssize_t cnt;
- for (;;) {
-- if (libc.main_thread) {
-- pthread_cleanup_push(cleanup, f);
-- cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt);
-- pthread_cleanup_pop(0);
-- } else {
-- cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
-- }
-+ pthread_cleanup_push(cleanup, f);
-+ cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt);
-+ pthread_cleanup_pop(0);
- if (cnt == rem) {
- f->wend = f->buf + f->buf_size;
- f->wpos = f->wbase = f->buf;
-diff --git a/src/thread/cancel_impl.c b/src/thread/cancel_impl.c
-index c835813..525d290 100644
---- a/src/thread/cancel_impl.c
-+++ b/src/thread/cancel_impl.c
-@@ -20,7 +20,7 @@ long (__syscall_cp)(syscall_arg_t nr,
- pthread_t self;
- long r;
-
-- if (!libc.main_thread || (self = __pthread_self())->canceldisable)
-+ if (!libc.has_thread_pointer || (self = __pthread_self())->canceldisable)
- return __syscall(nr, u, v, w, x, y, z);
-
- r = __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z);
-@@ -57,6 +57,7 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
-
- void __testcancel()
- {
-+ if (!libc.has_thread_pointer) return;
- pthread_t self = pthread_self();
- if (self->cancel && !self->canceldisable)
- __cancel();
-diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
-index ee6c31c..e0b5ef1 100644
---- a/src/thread/pthread_create.c
-+++ b/src/thread/pthread_create.c
-@@ -77,6 +77,7 @@ _Noreturn void pthread_exit(void *result)
-
- void __do_cleanup_push(struct __ptcb *cb)
- {
-+ if (!libc.has_thread_pointer) return;
- struct pthread *self = pthread_self();
- cb->__next = self->cancelbuf;
- self->cancelbuf = cb;
-@@ -84,6 +85,7 @@ void __do_cleanup_push(struct __ptcb *cb)
-
- void __do_cleanup_pop(struct __ptcb *cb)
- {
-+ if (!libc.has_thread_pointer) return;
- __pthread_self()->cancelbuf = cb->__next;
- }
-
-@@ -110,6 +112,8 @@ static int start(void *p)
- /* pthread_key_create.c overrides this */
- static const size_t dummy = 0;
- weak_alias(dummy, __pthread_tsd_size);
-+static void *const dummy_tsd[1] = { 0 };
-+weak_alias(dummy_tsd, __pthread_tsd_main);
-
- static FILE *const dummy_file = 0;
- weak_alias(dummy_file, __stdin_used);
-@@ -127,7 +131,7 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp
- {
- int ret;
- size_t size, guard;
-- struct pthread *self = pthread_self(), *new;
-+ struct pthread *self, *new;
- unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit;
- unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
- | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS
-@@ -135,13 +139,16 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp
- int do_sched = 0;
- pthread_attr_t attr = {0};
-
-- if (!self) return ENOSYS;
-+ if (!libc.can_do_threads) return ENOSYS;
-+ self = __pthread_self();
- if (!libc.threaded) {
- for (FILE *f=libc.ofl_head; f; f=f->next)
- init_file_lock(f);
- init_file_lock(__stdin_used);
- init_file_lock(__stdout_used);
- init_file_lock(__stderr_used);
-+ __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, SIGPT_SET, 0, _NSIG/8);
-+ self->tsd = (void **)__pthread_tsd_main;
- libc.threaded = 1;
- }
- if (attrp) attr = *attrp;
-diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c
-index c29935c..ef8a755 100644
---- a/src/thread/pthread_key_create.c
-+++ b/src/thread/pthread_key_create.c
-@@ -14,7 +14,13 @@ int pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
- unsigned i = (uintptr_t)&k / 16 % PTHREAD_KEYS_MAX;
- unsigned j = i;
-
-- __pthread_self_init();
-+ if (libc.has_thread_pointer) {
-+ pthread_t self = __pthread_self();
-+ /* This can only happen in the main thread before
-+ * pthread_create has been called. */
-+ if (!self->tsd) self->tsd = __pthread_tsd_main;
-+ }
-+
- if (!dtor) dtor = nodtor;
- do {
- if (!a_cas_p(keys+j, 0, (void *)dtor)) {
-diff --git a/src/thread/pthread_self.c b/src/thread/pthread_self.c
-index aed4b5f..5f9e651 100644
---- a/src/thread/pthread_self.c
-+++ b/src/thread/pthread_self.c
-@@ -1,45 +1,6 @@
- #include "pthread_impl.h"
-
--static struct pthread *main_thread = &(struct pthread){0};
--
--/* pthread_key_create.c overrides this */
--static const void *dummy[1] = { 0 };
--weak_alias(dummy, __pthread_tsd_main);
--
--static int init_main_thread()
--{
-- __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
-- SIGPT_SET, 0, _NSIG/8);
-- if (__set_thread_area(TP_ADJ(main_thread)) < 0) return -1;
-- main_thread->canceldisable = libc.canceldisable;
-- main_thread->tsd = (void **)__pthread_tsd_main;
-- main_thread->errno_ptr = __errno_location();
-- main_thread->self = main_thread;
-- main_thread->tid = main_thread->pid =
-- __syscall(SYS_set_tid_address, &main_thread->tid);
-- if (!main_thread->dtv)
-- main_thread->dtv = (void *)dummy;
-- libc.main_thread = main_thread;
-- return 0;
--}
--
--pthread_t __pthread_self_def()
-+pthread_t pthread_self()
- {
-- static int init, failed;
-- if (!init) {
-- if (failed) return 0;
-- if (init_main_thread() < 0) failed = 1;
-- if (failed) return 0;
-- init = 1;
-- }
- return __pthread_self();
- }
--
--weak_alias(__pthread_self_def, pthread_self);
--weak_alias(__pthread_self_def, __pthread_self_init);
--
--void *__install_initial_tls(void *p)
--{
-- main_thread = p;
-- return __pthread_self_def();
--}
-diff --git a/src/thread/pthread_setcancelstate.c b/src/thread/pthread_setcancelstate.c
-index ba2b231..060bcdc 100644
---- a/src/thread/pthread_setcancelstate.c
-+++ b/src/thread/pthread_setcancelstate.c
-@@ -3,13 +3,9 @@
- int pthread_setcancelstate(int new, int *old)
- {
- if (new > 1U) return EINVAL;
-- if (libc.main_thread) {
-- struct pthread *self = __pthread_self();
-- if (old) *old = self->canceldisable;
-- self->canceldisable = new;
-- } else {
-- if (old) *old = libc.canceldisable;
-- libc.canceldisable = new;
-- }
-+ if (!libc.has_thread_pointer) return ENOSYS;
-+ struct pthread *self = __pthread_self();
-+ if (old) *old = self->canceldisable;
-+ self->canceldisable = new;
- return 0;
- }