Merge "Support GNU_RELRO for static executables."
This commit is contained in:
commit
fe07ca04e4
1 changed files with 54 additions and 0 deletions
|
@ -48,6 +48,14 @@
|
|||
|
||||
#include <bionic_tls.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
// Returns the address of the page containing address 'x'.
|
||||
#define PAGE_START(x) ((x) & PAGE_MASK)
|
||||
|
||||
// Returns the address of the next page after address 'x', unless 'x' is
|
||||
// itself at the start of a page.
|
||||
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
|
||||
|
||||
static void call_array(void(**list)())
|
||||
{
|
||||
|
@ -57,6 +65,42 @@ static void call_array(void(**list)())
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the value of the AT_* variable passed to us by the kernel.
|
||||
*/
|
||||
static unsigned find_aux(unsigned *vecs, unsigned type) {
|
||||
while (vecs[0]) {
|
||||
if (vecs[0] == type) {
|
||||
return vecs[1];
|
||||
}
|
||||
vecs += 2;
|
||||
}
|
||||
|
||||
return 0; // should never happen
|
||||
}
|
||||
|
||||
static void apply_gnu_relro(unsigned *vecs) {
|
||||
Elf32_Phdr *phdr_start;
|
||||
unsigned phdr_ct;
|
||||
Elf32_Phdr *phdr;
|
||||
|
||||
phdr_start = (Elf32_Phdr *) find_aux(vecs, AT_PHDR);
|
||||
phdr_ct = find_aux(vecs, AT_PHNUM);
|
||||
|
||||
for (phdr = phdr_start; phdr < (phdr_start + phdr_ct); phdr++) {
|
||||
if (phdr->p_type != PT_GNU_RELRO)
|
||||
continue;
|
||||
|
||||
Elf32_Addr seg_page_start = PAGE_START(phdr->p_vaddr);
|
||||
Elf32_Addr seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz);
|
||||
|
||||
// Check return value here? What do we do if we fail?
|
||||
mprotect((void *) seg_page_start,
|
||||
seg_page_end - seg_page_start,
|
||||
PROT_READ);
|
||||
}
|
||||
}
|
||||
|
||||
__noreturn void __libc_init(uintptr_t *elfdata,
|
||||
void (*onexit)(void),
|
||||
int (*slingshot)(int, char**, char**),
|
||||
|
@ -64,6 +108,7 @@ __noreturn void __libc_init(uintptr_t *elfdata,
|
|||
{
|
||||
int argc;
|
||||
char **argv, **envp;
|
||||
unsigned *vecs;
|
||||
|
||||
__libc_init_tls(NULL);
|
||||
|
||||
|
@ -84,6 +129,14 @@ __noreturn void __libc_init(uintptr_t *elfdata,
|
|||
argv = (char**)(elfdata + 1);
|
||||
envp = argv + argc + 1;
|
||||
|
||||
// The auxiliary vector is at the end of the environment block
|
||||
vecs = (unsigned *) envp;
|
||||
while (vecs[0] != 0) {
|
||||
vecs++;
|
||||
}
|
||||
/* The end of the environment block is marked by two NULL pointers */
|
||||
vecs++;
|
||||
|
||||
/* The executable may have its own destructors listed in its .fini_array
|
||||
* so we need to ensure that these are called when the program exits
|
||||
* normally.
|
||||
|
@ -91,5 +144,6 @@ __noreturn void __libc_init(uintptr_t *elfdata,
|
|||
if (structors->fini_array)
|
||||
__cxa_atexit(__libc_fini,structors->fini_array,NULL);
|
||||
|
||||
apply_gnu_relro(vecs);
|
||||
exit(slingshot(argc, argv, envp));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue