diff options
Diffstat (limited to 'ldso/ldso/ldso.c')
-rw-r--r-- | ldso/ldso/ldso.c | 657 |
1 files changed, 54 insertions, 603 deletions
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 04dbdcae5..013895227 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -1,12 +1,11 @@ /* vi: set sw=4 ts=4: */ -/* Program to load an ELF binary on a linux system, and run it +/* + * Program to load an ELF binary on a linux system, and run it * after resolving ELF shared library symbols * - * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org> + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, * David Engel, Hongjiu Lu and Mitch D'Souza - * Copyright (C) 2001-2002, Erik Andersen - * - * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,621 +29,67 @@ * SUCH DAMAGE. */ -// Support a list of library preloads in /etc/ld.so.preload -//#define SUPPORT_LDSO_PRELOAD_FILE - - -/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have - I ever taken any courses on internals. This program was developed using - information available through the book "UNIX SYSTEM V RELEASE 4, - Programmers guide: Ansi C and Programming Support Tools", which did - a more than adequate job of explaining everything required to get this - working. */ - -/* - * The main trick with this program is that initially, we ourselves are - * not dynamicly linked. This means that we cannot access any global - * variables or call any functions. No globals initially, since the - * Global Offset Table (GOT) is initialized by the linker assuming a - * virtual address of 0, and no function calls initially since the - * Procedure Linkage Table (PLT) is not yet initialized. - * - * There are additional initial restrictions - we cannot use large - * switch statements, since the compiler generates tables of addresses - * and jumps through them. We can use inline functions, because these - * do not transfer control to a new address, but they must be static so - * that they are not exported from the modules. We cannot use normal - * syscall stubs, because these all reference the errno global variable - * which is not yet initialized. We can use all of the local stack - * variables that we want. - * - * Life is further complicated by the fact that initially we do not - * want to do a complete dynamic linking. We want to allow the user to - * supply new functions to override symbols (i.e. weak symbols and/or - * LD_PRELOAD). So initially, we only perform relocations for - * variables that start with "_dl_" since ANSI specifies that the user - * is not supposed to redefine any of these variables. - * - * Fortunately, the linker itself leaves a few clues lying around, and - * when the kernel starts the image, there are a few further clues. - * First of all, there is Auxiliary Vector Table information sitting on - * which is provided to us by the kernel, and which includes - * information about the load address that the program interpreter was - * loaded at, the number of sections, the address the application was - * loaded at and so forth. Here this information is stored in the - * array auxvt. For details see linux/fs/binfmt_elf.c where it calls - * NEW_AUX_ENT() a bunch of time.... - * - * Next, we need to find the GOT. On most arches there is a register - * pointing to the GOT, but just in case (and for new ports) I've added - * some (slow) C code to locate the GOT for you. - * - * This code was originally written for SVr4, and there the kernel - * would load all text pages R/O, so they needed to call mprotect a - * zillion times to mark all text pages as writable so dynamic linking - * would succeed. Then when they were done, they would change the - * protections for all the pages back again. Well, under Linux - * everything is loaded writable (since Linux does copy on write - * anyways) so all the mprotect stuff has been disabled. - * - * Initially, we do not have access to _dl_malloc since we can't yet - * make function calls, so we mmap one page to use as scratch space. - * Later on, when we can call _dl_malloc we reuse this this memory. - * This is also beneficial, since we do not want to use the same memory - * pool as malloc anyway - esp if the user redefines malloc to do - * something funky. - * - * Our first task is to perform a minimal linking so that we can call - * other portions of the dynamic linker. Once we have done this, we - * then build the list of modules that the application requires, using - * LD_LIBRARY_PATH if this is not a suid program (/usr/lib otherwise). - * Once this is done, we can do the dynamic linking as required, and we - * must omit the things we did to get the dynamic linker up and running - * in the first place. After we have done this, we just have a few - * housekeeping chores and we can transfer control to the user's - * application. - */ #include "ldso.h" - #define ALLOW_ZERO_PLTGOT -/* Some arches may need to override this in boot1_arch.h */ -#define ELFMAGIC ELFMAG +/* Pull in the value of _dl_progname */ +#include "_dl_progname.h" + +/* Global variables used within the shared library loader */ +char *_dl_library_path = 0; /* Where we look for libraries */ +char *_dl_preload = 0; /* Things to be loaded before the libs */ +char *_dl_ldsopath = 0; /* Location of the shared lib loader */ +unsigned char *_dl_malloc_addr = 0; /* Lets _dl_malloc use the already allocated memory page */ +unsigned char *_dl_mmap_zero = 0; /* Also used by _dl_malloc */ +unsigned long *_dl_brkp = 0; /* The end of the data segment for brk and sbrk */ +unsigned long *_dl_envp = 0; /* The environment address */ +int _dl_secure = 1; /* Are we dealing with setuid stuff? */ + -/* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */ -#define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ; REALIGN(); -/* - * Make sure that the malloc buffer is aligned on 4 byte boundary. For 64 bit - * platforms we may need to increase this to 8, but this is good enough for - * now. This is typically called after LD_MALLOC. - */ -#define REALIGN() malloc_buffer = (unsigned char *) (((unsigned long) malloc_buffer + 3) & ~(3)) -char *_dl_library_path = 0; /* Where we look for libraries */ -char *_dl_preload = 0; /* Things to be loaded before the libs. */ -char *_dl_ldsopath = 0; #ifdef __SUPPORT_LD_DEBUG__ -char *_dl_debug = 0; -char *_dl_debug_symbols = 0; -char *_dl_debug_move = 0; -char *_dl_debug_reloc = 0; -char *_dl_debug_detail = 0; +char *_dl_debug = 0; +char *_dl_debug_symbols = 0; +char *_dl_debug_move = 0; +char *_dl_debug_reloc = 0; +char *_dl_debug_detail = 0; char *_dl_debug_nofixups = 0; char *_dl_debug_bindings = 0; -int _dl_debug_file = 2; -#else -#define _dl_debug_file 2 -#endif -static unsigned char *_dl_malloc_addr, *_dl_mmap_zero; - -static int _dl_secure = 0; -static int (*_dl_elf_main) (int, char **, char **); -struct r_debug *_dl_debug_addr = NULL; -unsigned long *_dl_brkp; -unsigned long *_dl_envp; -int _dl_fixup(struct dyn_elf *rpnt, int flag); -void _dl_debug_state(void); -char *_dl_get_last_path_component(char *path); - -#include "boot1_arch.h" -#include "_dl_progname.h" /* Pull in the value of _dl_progname */ - -/* When we enter this piece of code, the program stack looks like this: - argc argument counter (integer) - argv[0] program name (pointer) - argv[1...N] program args (pointers) - argv[argc-1] end of args (integer) - NULL - env[0...N] environment variables (pointers) - NULL - auxvt[0...N] Auxiliary Vector Table elements (mixed types) -*/ - -LD_BOOT(unsigned long args) __attribute__ ((unused)); -LD_BOOT(unsigned long args) -{ - unsigned int argc; - char **argv, **envp; - unsigned long load_addr; - unsigned long *got; - unsigned long *aux_dat; - int goof = 0; - ElfW(Ehdr) *header; - struct elf_resolve *tpnt; - struct elf_resolve *app_tpnt; - Elf32_auxv_t auxvt[AT_EGID + 1]; - unsigned char *malloc_buffer, *mmap_zero; - Elf32_Dyn *dpnt; - unsigned long *hash_addr; - struct r_debug *debug_addr = NULL; - int indx; - int status; - - - /* WARNING! -- we cannot make _any_ funtion calls until we have - * taken care of fixing up our own relocations. Making static - * inline calls is ok, but _no_ function calls. Not yet - * anyways. */ - - /* First obtain the information on the stack that tells us more about - what binary is loaded, where it is loaded, etc, etc */ - GET_ARGV(aux_dat, args); -#if defined (__arm__) || defined (__mips__) || defined (__cris__) - aux_dat += 1; -#endif - argc = *(aux_dat - 1); - argv = (char **) aux_dat; - aux_dat += argc; /* Skip over the argv pointers */ - aux_dat++; /* Skip over NULL at end of argv */ - envp = (char **) aux_dat; - while (*aux_dat) - aux_dat++; /* Skip over the envp pointers */ - aux_dat++; /* Skip over NULL at end of envp */ - - /* Place -1 here as a checkpoint. We later check if it was changed - * when we read in the auxvt */ - auxvt[AT_UID].a_type = -1; - - /* The junk on the stack immediately following the environment is - * the Auxiliary Vector Table. Read out the elements of the auxvt, - * sort and store them in auxvt for later use. */ - while (*aux_dat) { - Elf32_auxv_t *auxv_entry = (Elf32_auxv_t *) aux_dat; - - if (auxv_entry->a_type <= AT_EGID) { - _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(Elf32_auxv_t)); - } - aux_dat += 2; - } - - /* locate the ELF header. We need this done as soon as possible - * (esp since SEND_STDERR() needs this on some platforms... */ - load_addr = auxvt[AT_BASE].a_un.a_val; - header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; - - /* Check the ELF header to make sure everything looks ok. */ - if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 || - header->e_ident[EI_VERSION] != EV_CURRENT -#if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__) - || _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0 -#else - || header->e_ident[EI_MAG0] != ELFMAG0 - || header->e_ident[EI_MAG1] != ELFMAG1 - || header->e_ident[EI_MAG2] != ELFMAG2 - || header->e_ident[EI_MAG3] != ELFMAG3 -#endif - ) { - SEND_STDERR("Invalid ELF header\n"); - _dl_exit(0); - } -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("ELF header="); - SEND_ADDRESS_STDERR(load_addr, 1); -#endif - - - /* Locate the global offset table. Since this code must be PIC - * we can take advantage of the magic offset register, if we - * happen to know what that is for this architecture. If not, - * we can always read stuff out of the ELF file to find it... */ -#if defined(__i386__) - __asm__("\tmovl %%ebx,%0\n\t":"=a"(got)); -#elif defined(__m68k__) - __asm__("movel %%a5,%0":"=g"(got)); -#elif defined(__sparc__) - __asm__("\tmov %%l7,%0\n\t":"=r"(got)); -#elif defined(__arm__) - __asm__("\tmov %0, r10\n\t":"=r"(got)); -#elif defined(__powerpc__) - __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got)); -#elif defined(__mips__) - __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got)); -#elif defined(__sh__) && !defined(__SH5__) - __asm__( -" mov.l 1f, %0\n" -" mova 1f, r0\n" -" bra 2f\n" -" add r0, %0\n" -" .balign 4\n" -"1: .long _GLOBAL_OFFSET_TABLE_\n" -"2:" : "=r" (got) : : "r0"); -#elif defined(__cris__) - __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%0\n\t":"=r"(got)); -#else - /* Do things the slow way in C */ - { - unsigned long tx_reloc; - Elf32_Dyn *dynamic = NULL; - Elf32_Shdr *shdr; - Elf32_Phdr *pt_load; - -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("Finding the GOT using C code to read the ELF file\n"); -#endif - /* Find where the dynamic linking information section is hiding */ - shdr = (Elf32_Shdr *) (header->e_shoff + (char *) header); - for (indx = header->e_shnum; --indx >= 0; ++shdr) { - if (shdr->sh_type == SHT_DYNAMIC) { - goto found_dynamic; - } - } - SEND_STDERR("missing dynamic linking information section \n"); - _dl_exit(0); - - found_dynamic: - dynamic = (Elf32_Dyn *) (shdr->sh_offset + (char *) header); - - /* Find where PT_LOAD is hiding */ - pt_load = (Elf32_Phdr *) (header->e_phoff + (char *) header); - for (indx = header->e_phnum; --indx >= 0; ++pt_load) { - if (pt_load->p_type == PT_LOAD) { - goto found_pt_load; - } - } - SEND_STDERR("missing loadable program segment\n"); - _dl_exit(0); - - found_pt_load: - /* Now (finally) find where DT_PLTGOT is hiding */ - tx_reloc = pt_load->p_vaddr - pt_load->p_offset; - for (; DT_NULL != dynamic->d_tag; ++dynamic) { - if (dynamic->d_tag == DT_PLTGOT) { - goto found_got; - } - } - SEND_STDERR("missing global offset table\n"); - _dl_exit(0); - - found_got: - got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc + - (char *) header); - } -#endif - - /* Now, finally, fix up the location of the dynamic stuff */ - dpnt = (Elf32_Dyn *) (*got + load_addr); -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("First Dynamic section entry="); - SEND_ADDRESS_STDERR(dpnt, 1); -#endif - - - /* Call mmap to get a page of writable memory that can be used - * for _dl_malloc throughout the shared lib loader. */ - mmap_zero = malloc_buffer = _dl_mmap((void *) 0, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); - if (_dl_mmap_check_error(mmap_zero)) { - SEND_STDERR("dl_boot: mmap of a spare page failed!\n"); - _dl_exit(13); - } - - tpnt = LD_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); - app_tpnt = LD_MALLOC(sizeof(struct elf_resolve)); - _dl_memset(app_tpnt, 0, sizeof(struct elf_resolve)); - -#ifdef __UCLIBC_PIE_SUPPORT__ - /* Find the runtime load address of the main executable, this may be - * different from what the ELF header says for ET_DYN/PIE executables. - */ - { - ElfW(Phdr) *ppnt; - int i; - - ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; - for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) - if (ppnt->p_type == PT_PHDR) { - app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr); - break; - } - } - -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("app_tpnt->loadaddr="); - SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1); -#endif -#endif - - /* - * This is used by gdb to locate the chain of shared libraries that are currently loaded. - */ - debug_addr = LD_MALLOC(sizeof(struct r_debug)); - _dl_memset(debug_addr, 0, sizeof(struct r_debug)); - - /* OK, that was easy. Next scan the DYNAMIC section of the image. - We are only doing ourself right now - we will have to do the rest later */ -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("scanning DYNAMIC section\n"); -#endif - while (dpnt->d_tag) { -#if defined(__mips__) - if (dpnt->d_tag == DT_MIPS_GOTSYM) - tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val; - if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) - tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val; - if (dpnt->d_tag == DT_MIPS_SYMTABNO) - tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val; -#endif - if (dpnt->d_tag < 24) { - tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; - if (dpnt->d_tag == DT_TEXTREL) { - tpnt->dynamic_info[DT_TEXTREL] = 1; - } - } - dpnt++; - } - - { - ElfW(Phdr) *ppnt; - int i; - - ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; - for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) - if (ppnt->p_type == PT_DYNAMIC) { -#ifndef __UCLIBC_PIE_SUPPORT__ - dpnt = (Elf32_Dyn *) ppnt->p_vaddr; -#else - dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr); -#endif - while (dpnt->d_tag) { -#if defined(__mips__) - if (dpnt->d_tag == DT_MIPS_GOTSYM) - app_tpnt->mips_gotsym = - (unsigned long) dpnt->d_un.d_val; - if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) - app_tpnt->mips_local_gotno = - (unsigned long) dpnt->d_un.d_val; - if (dpnt->d_tag == DT_MIPS_SYMTABNO) - app_tpnt->mips_symtabno = - (unsigned long) dpnt->d_un.d_val; - if (dpnt->d_tag > DT_JMPREL) { - dpnt++; - continue; - } - app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; - -#warning "Debugging threads on mips won't work till someone fixes this..." -#if 0 - if (dpnt->d_tag == DT_DEBUG) { - dpnt->d_un.d_val = (unsigned long) debug_addr; - } -#endif - -#else - if (dpnt->d_tag > DT_JMPREL) { - dpnt++; - continue; - } - app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; - if (dpnt->d_tag == DT_DEBUG) { - dpnt->d_un.d_val = (unsigned long) debug_addr; - } -#endif - if (dpnt->d_tag == DT_TEXTREL) - app_tpnt->dynamic_info[DT_TEXTREL] = 1; - dpnt++; - } - } - } - -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("done scanning DYNAMIC section\n"); -#endif - - /* Get some more of the information that we will need to dynamicly link - this module to itself */ - - hash_addr = (unsigned long *) (tpnt->dynamic_info[DT_HASH] + load_addr); - tpnt->nbucket = *hash_addr++; - tpnt->nchain = *hash_addr++; - tpnt->elf_buckets = hash_addr; - hash_addr += tpnt->nbucket; - -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("done grabbing link information\n"); -#endif - -#ifndef FORCE_SHAREABLE_TEXT_SEGMENTS - /* Ugly, ugly. We need to call mprotect to change the protection of - the text pages so that we can do the dynamic linking. We can set the - protection back again once we are done */ - - { - ElfW(Phdr) *ppnt; - int i; - -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("calling mprotect on the shared library/dynamic linker\n"); -#endif - - /* First cover the shared library/dynamic linker. */ - if (tpnt->dynamic_info[DT_TEXTREL]) { - header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr; - ppnt = (ElfW(Phdr) *) ((int)auxvt[AT_BASE].a_un.a_ptr + - header->e_phoff); - for (i = 0; i < header->e_phnum; i++, ppnt++) { - if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { - _dl_mprotect((void *) (load_addr + (ppnt->p_vaddr & PAGE_ALIGN)), - (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, - PROT_READ | PROT_WRITE | PROT_EXEC); - } - } - } - -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("calling mprotect on the application program\n"); -#endif - /* Now cover the application program. */ - if (app_tpnt->dynamic_info[DT_TEXTREL]) { - ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr; - for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { - if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) -#ifndef __UCLIBC_PIE_SUPPORT__ - _dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN), - (ppnt->p_vaddr & ADDR_ALIGN) + -#else - _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN), - ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) + -#endif - (unsigned long) ppnt->p_filesz, - PROT_READ | PROT_WRITE | PROT_EXEC); - } - } - } -#endif - -#if defined(__mips__) -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("About to do MIPS specific GOT bootstrap\n"); -#endif - /* For MIPS we have to do stuff to the GOT before we do relocations. */ - PERFORM_BOOTSTRAP_GOT(got); -#endif - - /* OK, now do the relocations. We do not do a lazy binding here, so - that once we are done, we have considerably more flexibility. */ -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("About to do library loader relocations\n"); -#endif - - goof = 0; - for (indx = 0; indx < 2; indx++) { - unsigned int i; - ELF_RELOC *rpnt; - unsigned long *reloc_addr; - unsigned long symbol_addr; - int symtab_index; - unsigned long rel_addr, rel_size; - - - 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; - - /* Now parse the relocation information */ - rpnt = (ELF_RELOC *) (rel_addr + load_addr); - for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { - reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset); - symtab_index = ELF32_R_SYM(rpnt->r_info); - symbol_addr = 0; - if (symtab_index) { - char *strtab; - Elf32_Sym *symtab; - - symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr); - strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr); - - /* We only do a partial dynamic linking right now. The user - is not supposed to redefine any symbols that start with - a '_', so we can do this with confidence. */ - if (!_dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - symbol_addr = load_addr + symtab[symtab_index].st_value; - - if (!symbol_addr) { - /* This will segfault - you cannot call a function until - * we have finished the relocations. - */ - SEND_STDERR("ELF dynamic loader - unable to self-bootstrap - symbol "); - SEND_STDERR(strtab + symtab[symtab_index].st_name); - SEND_STDERR(" undefined.\n"); - goof++; - } -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - SEND_STDERR("About to fixup symbol: "); - SEND_STDERR(strtab + symtab[symtab_index].st_name); - SEND_STDERR("\n"); -#endif - PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, &symtab[symtab_index]); - } else { - /* - * Use this machine-specific macro to perform the actual relocation. - */ - PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, NULL); - } - } - } - - if (goof) { - _dl_exit(14); - } -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - /* Wahoo!!! */ - _dl_dprintf(_dl_debug_file, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n"); +int _dl_debug_file = 2; #endif - if (argv[0]) { - _dl_progname = argv[0]; - } - - /* Start to build the tables of the modules that are required for - * this beast to run. We start with the basic executable, and then - * go from there. Eventually we will run across ourself, and we - * will need to properly deal with that as well. */ - - /* Make it so _dl_malloc can use the page of memory we have already - * allocated, so we shouldn't need to grab any more memory */ - _dl_malloc_addr = malloc_buffer; - _dl_mmap_zero = mmap_zero; +/* Forward function declarations */ +static void debug_fini (int status, void *arg); +static int _dl_suid_ok(void); +/* + * This stub function is used by some debuggers. The idea is that they + * can set an internal breakpoint on it, so that we are notified when the + * address mapping is changed in some way. + */ +void _dl_debug_state(void) +{ +} +/* This global variable is also to communicate with debuggers such as gdb. */ +struct r_debug *_dl_debug_addr = NULL; - /* Now we have done the mandatory linking of some things. We are now - free to start using global variables, since these things have all been - fixed up by now. Still no function calls outside of this library , - since the dynamic resolver is not yet ready. */ - _dl_get_ready_to_run(tpnt, app_tpnt, load_addr, hash_addr, - auxvt, envp, debug_addr, malloc_buffer, mmap_zero, argv); - /* Transfer control to the application. */ - status = 0; /* Used on x86, but not on other arches */ -#if defined (__SUPPORT_LD_DEBUG__) - if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ntransfering control: %s\n\n", _dl_progname); -#endif - _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn; - START(); -} - #if defined (__SUPPORT_LD_DEBUG__) static void debug_fini (int status, void *arg) { (void)status; _dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg); } -#endif +#endif void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt, unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], char **envp, struct r_debug *debug_addr, unsigned char *malloc_buffer, unsigned char *mmap_zero, char **argv) - { ElfW(Phdr) *ppnt; char *lpntstr; @@ -658,6 +103,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*); #endif + #ifdef __SUPPORT_LD_DEBUG_EARLY__ /* Wahoo!!! */ SEND_STDERR("Cool, we managed to make a function call.\n"); @@ -673,7 +119,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt * free to start using global variables, since these things have all been * fixed up by now. Still no function calls outside of this library , * since the dynamic resolver is not yet ready. */ - if (argv[0]) { _dl_progname = argv[0]; } @@ -702,7 +147,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt /* OK, this was a big step, now we need to scan all of the user images and load them properly. */ - { ElfW(Ehdr) *epnt; ElfW(Phdr) *myppnt; @@ -1275,15 +719,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt _dl_debug_state(); } -/* - * This stub function is used by some debuggers. The idea is that they - * can set an internal breakpoint on it, so that we are notified when the - * address mapping is changed in some way. - */ -void _dl_debug_state(void) -{ -} - char *_dl_getenv(const char *symbol, char **envp) { char *pnt; @@ -1317,5 +752,21 @@ void _dl_unsetenv(const char *symbol, char **envp) return; } +static int _dl_suid_ok(void) +{ + __kernel_uid_t uid, euid; + __kernel_gid_t gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + + if(uid == euid && gid == egid) { + return 1; + } + return 0; +} + #include "hash.c" #include "readelflib1.c" |