Date: Sat, 18 Apr 2020 03:14:16 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r360067 - stable/12/libexec/rtld-elf Message-ID: <202004180314.03I3EGLS065134@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Sat Apr 18 03:14:16 2020 New Revision: 360067 URL: https://svnweb.freebsd.org/changeset/base/360067 Log: MFC r359634: Make p_vaddr % p_align == p_offset % p_align for (some) TLS segments. Modified: stable/12/libexec/rtld-elf/map_object.c stable/12/libexec/rtld-elf/rtld.c stable/12/libexec/rtld-elf/rtld.h stable/12/libexec/rtld-elf/xmalloc.c Directory Properties: stable/12/ (props changed) Modified: stable/12/libexec/rtld-elf/map_object.c ============================================================================== --- stable/12/libexec/rtld-elf/map_object.c Sat Apr 18 03:09:25 2020 (r360066) +++ stable/12/libexec/rtld-elf/map_object.c Sat Apr 18 03:14:16 2020 (r360067) @@ -308,6 +308,7 @@ map_object(int fd, const char *path, const struct stat obj->tlsindex = ++tls_max_index; obj->tlssize = phtls->p_memsz; obj->tlsalign = phtls->p_align; + obj->tlspoffset = phtls->p_offset; obj->tlsinitsize = phtls->p_filesz; obj->tlsinit = mapbase + phtls->p_vaddr; } Modified: stable/12/libexec/rtld-elf/rtld.c ============================================================================== --- stable/12/libexec/rtld-elf/rtld.c Sat Apr 18 03:09:25 2020 (r360066) +++ stable/12/libexec/rtld-elf/rtld.c Sat Apr 18 03:14:16 2020 (r360067) @@ -1454,6 +1454,7 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t e obj->tlsalign = ph->p_align; obj->tlsinitsize = ph->p_filesz; obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase); + obj->tlspoffset = ph->p_offset; break; case PT_GNU_STACK: @@ -4821,7 +4822,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcb Elf_Addr addr; Elf_Addr i; size_t extra_size, maxalign, post_size, pre_size, tls_block_size; - size_t tls_init_align; + size_t tls_init_align, tls_init_offset; if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) return (oldtcb); @@ -4838,7 +4839,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcb tls_block_size += pre_size + tls_static_space - TLS_TCB_SIZE - post_size; /* Allocate whole TLS block */ - tls_block = malloc_aligned(tls_block_size, maxalign); + tls_block = malloc_aligned(tls_block_size, maxalign, 0); tcb = (Elf_Addr **)(tls_block + pre_size + extra_size); if (oldtcb != NULL) { @@ -4862,15 +4863,21 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcb for (obj = globallist_curr(objs); obj != NULL; obj = globallist_next(obj)) { - if (obj->tlsoffset > 0) { - addr = (Elf_Addr)tcb + obj->tlsoffset; - if (obj->tlsinitsize > 0) - memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); - if (obj->tlssize > obj->tlsinitsize) - memset((void*)(addr + obj->tlsinitsize), 0, - obj->tlssize - obj->tlsinitsize); - dtv[obj->tlsindex + 1] = addr; + if (obj->tlsoffset == 0) + continue; + tls_init_offset = obj->tlspoffset & (obj->tlsalign - 1); + addr = (Elf_Addr)tcb + obj->tlsoffset; + if (tls_init_offset > 0) + memset((void *)addr, 0, tls_init_offset); + if (obj->tlsinitsize > 0) { + memcpy((void *)(addr + tls_init_offset), obj->tlsinit, + obj->tlsinitsize); } + if (obj->tlssize > obj->tlsinitsize) { + memset((void *)(addr + tls_init_offset + obj->tlsinitsize), + 0, obj->tlssize - obj->tlsinitsize - tls_init_offset); + } + dtv[obj->tlsindex + 1] = addr; } } @@ -4928,7 +4935,7 @@ allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcb size = round(tls_static_space, ralign) + round(tcbsize, ralign); assert(tcbsize >= 2*sizeof(Elf_Addr)); - tls = malloc_aligned(size, ralign); + tls = malloc_aligned(size, ralign, 0 /* XXX */); dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); segbase = (Elf_Addr)(tls + round(tls_static_space, ralign)); @@ -5021,25 +5028,24 @@ free_tls(void *tls, size_t tcbsize __unused, size_t t void * allocate_module_tls(int index) { - Obj_Entry* obj; - char* p; + Obj_Entry *obj; + char *p; - TAILQ_FOREACH(obj, &obj_list, next) { - if (obj->marker) - continue; - if (obj->tlsindex == index) - break; - } - if (!obj) { - _rtld_error("Can't find module with TLS index %d", index); - rtld_die(); - } + TAILQ_FOREACH(obj, &obj_list, next) { + if (obj->marker) + continue; + if (obj->tlsindex == index) + break; + } + if (obj == NULL) { + _rtld_error("Can't find module with TLS index %d", index); + rtld_die(); + } - p = malloc_aligned(obj->tlssize, obj->tlsalign); - memcpy(p, obj->tlsinit, obj->tlsinitsize); - memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); - - return p; + p = malloc_aligned(obj->tlssize, obj->tlsalign, obj->tlspoffset); + memcpy(p, obj->tlsinit, obj->tlsinitsize); + memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); + return (p); } bool Modified: stable/12/libexec/rtld-elf/rtld.h ============================================================================== --- stable/12/libexec/rtld-elf/rtld.h Sat Apr 18 03:09:25 2020 (r360066) +++ stable/12/libexec/rtld-elf/rtld.h Sat Apr 18 03:14:16 2020 (r360067) @@ -168,6 +168,7 @@ typedef struct Struct_Obj_Entry { size_t tlssize; /* Size of TLS block for this module */ size_t tlsoffset; /* Offset of static TLS block for this module */ size_t tlsalign; /* Alignment of static TLS block */ + size_t tlspoffset; /* p_offset of the static TLS block */ caddr_t relro_page; size_t relro_size; @@ -362,7 +363,7 @@ Obj_Entry *map_object(int, const char *, const struct void *xcalloc(size_t, size_t); void *xmalloc(size_t); char *xstrdup(const char *); -void *malloc_aligned(size_t size, size_t align); +void *malloc_aligned(size_t size, size_t align, size_t offset); void free_aligned(void *ptr); extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; extern Elf_Sym sym_zero; /* For resolving undefined weak refs. */ Modified: stable/12/libexec/rtld-elf/xmalloc.c ============================================================================== --- stable/12/libexec/rtld-elf/xmalloc.c Sat Apr 18 03:09:25 2020 (r360066) +++ stable/12/libexec/rtld-elf/xmalloc.c Sat Apr 18 03:14:16 2020 (r360067) @@ -27,6 +27,7 @@ * $FreeBSD$ */ +#include <sys/param.h> #include <stddef.h> #include <stdlib.h> #include <string.h> @@ -75,16 +76,21 @@ xstrdup(const char *str) } void * -malloc_aligned(size_t size, size_t align) +malloc_aligned(size_t size, size_t align, size_t offset) { - void *mem, *res; + char *mem, *res; + uintptr_t x; + offset &= align - 1; if (align < sizeof(void *)) align = sizeof(void *); - mem = xmalloc(size + sizeof(void *) + align - 1); - res = (void *)round((uintptr_t)mem + sizeof(void *), align); - *(void **)((uintptr_t)res - sizeof(void *)) = mem; + mem = xmalloc(size + 3 * align + offset); + x = roundup((uintptr_t)mem + sizeof(void *), align); + x += offset; + res = (void *)x; + x -= sizeof(void *); + memcpy((void *)x, &mem, sizeof(mem)); return (res); } @@ -98,6 +104,6 @@ free_aligned(void *ptr) return; x = (uintptr_t)ptr; x -= sizeof(void *); - mem = *(void **)x; + memcpy(&mem, (void *)x, sizeof(mem)); free(mem); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004180314.03I3EGLS065134>