diff options
Diffstat (limited to 'libc/misc/internals')
-rw-r--r-- | libc/misc/internals/Makefile.in | 3 | ||||
-rw-r--r-- | libc/misc/internals/__uClibc_main.c | 31 | ||||
-rw-r--r-- | libc/misc/internals/reloc_static_pie.c | 115 | ||||
-rw-r--r-- | libc/misc/internals/tempname.c | 15 |
4 files changed, 137 insertions, 27 deletions
diff --git a/libc/misc/internals/Makefile.in b/libc/misc/internals/Makefile.in index a8e4e36f9..908b18321 100644 --- a/libc/misc/internals/Makefile.in +++ b/libc/misc/internals/Makefile.in @@ -17,7 +17,7 @@ MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC-y)) MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC-y)) CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS) - +CFLAGS-reloc_static_pie.c := $(SSP_DISABLE_FLAGS) -DL_rcrt1 libc-y += $(MISC_INTERNALS_OBJ) ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y) @@ -34,6 +34,7 @@ libc-static-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += \ libc-static-$(UCLIBC_FORMAT_SHARED_FLAT) += \ $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \ $(MISC_INTERNALS_OUT)/shared_flat_add_library.o +libc-static-$(STATIC_PIE) += $(MISC_INTERNALS_OUT)/reloc_static_pie.o libc-shared-$(UCLIBC_FORMAT_SHARED_FLAT) += \ $(MISC_INTERNALS_OUT)/shared_flat_initfini.os \ $(MISC_INTERNALS_OUT)/shared_flat_add_library.os diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index 849bca8d4..60695b6ed 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -43,7 +43,7 @@ /* Are we in a secure process environment or are we dealing * with setuid stuff? If we are dynamically linked, then we * already have _dl_secure, otherwise we need to re-examine - * auxvt[] below. + * _dl_auxvt[] below. */ int _pe_secure = 0; libc_hidden_data_def(_pe_secure) @@ -84,6 +84,8 @@ static void fdpic_init_array_jump(void *addr) #ifndef SHARED void *__libc_stack_end = NULL; +#include "dl-auxvt.h" + # ifdef __UCLIBC_HAS_SSP__ # include <dl-osinfo.h> static uintptr_t stack_chk_guard; @@ -109,7 +111,7 @@ void internal_function _dl_aux_init (ElfW(auxv_t) *av); * in or linker will disregard these weaks. */ -static int __pthread_return_0 (pthread_mutex_t *unused) { return 0; } +static int __pthread_return_0 (pthread_mutex_t *unused) { (void)unused; return 0; } weak_alias (__pthread_return_0, __pthread_mutex_lock) weak_alias (__pthread_return_0, __pthread_mutex_trylock) weak_alias (__pthread_return_0, __pthread_mutex_unlock) @@ -117,6 +119,7 @@ weak_alias (__pthread_return_0, __pthread_mutex_unlock) int weak_function __pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { + (void)mutex; (void)attr; return 0; } @@ -370,9 +373,8 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, char **argv, void (*app_init)(void), void (*app_fini)(void), void (*rtld_fini)(void), void *stack_end attribute_unused) { -#if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED +#ifndef SHARED unsigned long *aux_dat; - ElfW(auxv_t) auxvt[AT_EGID + 1]; #endif #ifdef __UCLIBC_HAS_THREADS_NATIVE__ @@ -396,25 +398,16 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, __environ = &argv[argc]; } -#if !defined __ARCH_HAS_NO_LDSO__ && !defined SHARED +#ifndef SHARED /* Pull stuff from the ELF header when possible */ - memset(auxvt, 0x00, sizeof(auxvt)); aux_dat = (unsigned long*)__environ; while (*aux_dat) { aux_dat++; } aux_dat++; - while (*aux_dat) { - ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; - if (auxv_entry->a_type <= AT_EGID) { - memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); - } - aux_dat += 2; - } /* Get the program headers (_dl_phdr) from the aux vector It will be used into __libc_setup_tls. */ - - _dl_aux_init (auxvt); + _dl_aux_init ((ElfW(auxv_t) *)aux_dat); #endif /* We need to initialize uClibc. If we are dynamically linked this @@ -430,10 +423,10 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, #ifndef SHARED /* Prevent starting SUID binaries where the stdin. stdout, and * stderr file descriptors are not already opened. */ - if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) || - (auxvt[AT_UID].a_un.a_val != (size_t)-1 && - (auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val || - auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val))) + if ((_dl_auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) || + (_dl_auxvt[AT_UID].a_un.a_val != (size_t)-1 && + (_dl_auxvt[AT_UID].a_un.a_val != _dl_auxvt[AT_EUID].a_un.a_val || + _dl_auxvt[AT_GID].a_un.a_val != _dl_auxvt[AT_EGID].a_un.a_val))) #else if (_dl_secure) #endif diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c new file mode 100644 index 000000000..3bbdef18e --- /dev/null +++ b/libc/misc/internals/reloc_static_pie.c @@ -0,0 +1,115 @@ +/* Support for relocating static PIE. + Copyright (C) 2017-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ +#define IS_IN_rtld // force inline function calls +#include <link.h> +#include <elf.h> +#include <dl-elf.h> + +#include <ldso.h> +#if defined(__m68k__) || defined(__mips__) || defined(__xtensa__) +#include <dl-startup.h> +#endif + +extern ElfW(Addr) _dl_load_base; + +void +reloc_static_pie (ElfW(Addr) load_addr); + +void +reloc_static_pie(ElfW(Addr) load_addr) +{ + int indx; + ElfW(Addr) got; + ElfW(Dyn) *dpnt; + struct elf_resolve tpnt_tmp; + struct elf_resolve *tpnt = &tpnt_tmp; + + DL_BOOT_COMPUTE_GOT(got); + DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)load_addr); + + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); + tpnt->loadaddr = load_addr; + tpnt->dynamic_addr = dpnt; + + __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); + +#if defined(PERFORM_BOOTSTRAP_GOT) + /* some arches (like MIPS) we have to tweak the GOT before relocations */ + PERFORM_BOOTSTRAP_GOT(tpnt); +#endif + +#if !defined(__FDPIC__) + DL_RELOCATE_RELR(tpnt); +#endif + +#if defined(ELF_MACHINE_PLTREL_OVERLAP) +# define INDX_MAX 1 +#else +# define INDX_MAX 2 +#endif + + for (indx = 0; indx < INDX_MAX; indx++) { + unsigned long rel_addr, rel_size; + ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + + rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : + tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]); + rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : + tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]); + + if (!rel_addr) + continue; + + if((0 == indx) && relative_count) { + rel_size -= relative_count * sizeof(ELF_RELOC); + elf_machine_relative(load_addr, rel_addr, relative_count); + rel_addr += relative_count * sizeof(ELF_RELOC); + } + +#ifdef ARCH_NEEDS_BOOTSTRAP_RELOCS + { + ELF_RELOC *rpnt; + unsigned int i; + ElfW(Sym) *sym; + unsigned long symbol_addr; + int symtab_index; + unsigned long *reloc_addr; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { + reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym = NULL; + if (symtab_index) { + ElfW(Sym) *symtab; + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + sym = &symtab[symtab_index]; + symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value); + } + /* Use this machine-specific macro to perform the actual relocation. */ + PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); + } + } +#else + (void)rel_size; +#endif + } + _dl_load_base = load_addr; +} diff --git a/libc/misc/internals/tempname.c b/libc/misc/internals/tempname.c index ca87b0c06..f9b714a68 100644 --- a/libc/misc/internals/tempname.c +++ b/libc/misc/internals/tempname.c @@ -152,12 +152,12 @@ static void brain_damaged_fillrand(unsigned char *buf, unsigned int len) for (i = 0; i < len; ++i) { rh = high % NUM_LETTERS; high /= NUM_LETTERS; -#define L ((UINT32_MAX % NUM_LETTERS + 1) % NUM_LETTERS) - k = (low % NUM_LETTERS) + (L * rh); -#undef L -#define H ((UINT32_MAX / NUM_LETTERS) + ((UINT32_MAX % NUM_LETTERS + 1) / NUM_LETTERS)) - low = (low / NUM_LETTERS) + (H * rh) + (k / NUM_LETTERS); -#undef H +#define _L ((UINT32_MAX % NUM_LETTERS + 1) % NUM_LETTERS) + k = (low % NUM_LETTERS) + (_L * rh); +#undef _L +#define _H ((UINT32_MAX / NUM_LETTERS) + ((UINT32_MAX % NUM_LETTERS + 1) / NUM_LETTERS)) + low = (low / NUM_LETTERS) + (_H * rh) + (k / NUM_LETTERS); +#undef _H k %= NUM_LETTERS; buf[i] = letters[k]; } @@ -218,7 +218,8 @@ int attribute_hidden __gen_tempname (char *tmpl, int kind, int flags, /* Give up now. */ return -1; } else - fd = 0; + /* File already exists, so return with non-zero value */ + return -1; } case __GT_FILE: fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | flags, mode); |