aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-load.c7
-rw-r--r--elf/dl-reloc.c20
-rw-r--r--elf/elf.h3
-rw-r--r--elf/rtld.c84
4 files changed, 74 insertions, 40 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index c7e3716..dc993a5 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1,5 +1,5 @@
/* Map in a shared object's segments from the file.
- Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004 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
@@ -1065,6 +1065,11 @@ cannot allocate TLS data structures for initial thread");
case PT_GNU_STACK:
stack_flags = ph->p_flags;
break;
+
+ case PT_GNU_RELRO:
+ l->l_relro_addr = ph->p_vaddr;
+ l->l_relro_size = ph->p_memsz;
+ break;
}
if (__builtin_expect (nloadcmds == 0, 0))
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index e5abba4..21d1871 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -1,5 +1,5 @@
/* Relocate a shared object and resolve its references to other loaded objects.
- Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004 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
@@ -307,6 +307,24 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
textrels = textrels->next;
}
+
+ /* In case we can protect the data now that the relocations are
+ done, do it. */
+ if (l->l_relro_size != 0)
+ {
+ ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
+ & ~(GL(dl_pagesize) - 1));
+ ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
+ & ~(GL(dl_pagesize) - 1));
+
+ if (start != end
+ && __mprotect ((void *) start, end - start, PROT_READ) < 0)
+ {
+ errstring = N_("\
+cannot apply additional memory protection after relocation");
+ goto call_error;
+ }
+ }
}
INTDEF (_dl_relocate_object)
diff --git a/elf/elf.h b/elf/elf.h
index 56b711d..9a4da65 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1,5 +1,5 @@
/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2003, 2004 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
@@ -567,6 +567,7 @@ typedef struct
#define PT_LOOS 0x60000000 /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
+#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
diff --git a/elf/rtld.c b/elf/rtld.c
index 392ccb6..4273a6f 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1,5 +1,5 @@
/* Run time dynamic linker.
- Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995-2002, 2003, 2004 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
@@ -332,13 +332,14 @@ _dl_start (void *arg)
bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
#endif
-#if USE___THREAD
/* Get the dynamic linker's own program header. First we need the ELF
file header. The `_begin' symbol created by the linker script points
to it. When we have something like GOTOFF relocs, we can use a plain
reference to find the runtime address. Without that, we have to rely
on the `l_addr' value, which is not the value we want when prelinked. */
+#if USE___THREAD
dtv_t initdtv[3];
+#endif /* USE___THREAD */
ElfW(Ehdr) *ehdr
# ifdef DONT_USE_BOOTSTRAP_MAP
= (ElfW(Ehdr) *) &_begin;
@@ -348,6 +349,7 @@ _dl_start (void *arg)
ElfW(Phdr) *phdr = (ElfW(Phdr) *) ((void *) ehdr + ehdr->e_phoff);
size_t cnt = ehdr->e_phnum; /* PT_TLS is usually the last phdr. */
while (cnt-- > 0)
+#if USE___THREAD
if (phdr[cnt].p_type == PT_TLS)
{
void *tlsblock;
@@ -442,11 +444,14 @@ _dl_start (void *arg)
/* So far this is module number one. */
bootstrap_map.l_tls_modid = 1;
-
- /* There can only be one PT_TLS entry. */
- break;
}
+ else
#endif /* USE___THREAD */
+ if (phdr[cnt].p_type == PT_GNU_RELRO)
+ {
+ bootstrap_map.l_relro_addr = phdr[cnt].p_vaddr;
+ bootstrap_map.l_relro_size = phdr[cnt].p_memsz;
+ }
#ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
@@ -777,6 +782,11 @@ of this helper program; chances are you did not intend to run this program.\n\
GL(dl_stack_flags) = ph->p_flags;
break;
}
+ else if (ph->p_type == PT_GNU_RELRO)
+ {
+ GL(dl_loaded)->l_relro_addr = ph->p_vaddr;
+ GL(dl_loaded)->l_relro_size = ph->p_memsz;
+ }
if (__builtin_expect (mode, normal) == verify)
{
@@ -1598,6 +1608,35 @@ cannot allocate TLS data structures for initial thread");
_dl_printf ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
}
+
+ /* Initialize _r_debug. */
+ struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr);
+ {
+ struct link_map *l;
+
+ l = GL(dl_loaded);
+
+#ifdef ELF_MACHINE_DEBUG_SETUP
+
+ /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */
+
+ ELF_MACHINE_DEBUG_SETUP (l, r);
+ ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r);
+
+#else
+
+ if (l->l_info[DT_DEBUG] != NULL)
+ /* There is a DT_DEBUG entry in the dynamic section. Fill it in
+ with the run-time address of the r_debug structure */
+ l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+
+ /* Fill in the pointer in the dynamic linker's own dynamic section, in
+ case you run gdb on the dynamic linker directly. */
+ if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL)
+ GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+#endif
+ }
+
if (prelinked)
{
struct link_map *l;
@@ -1738,38 +1777,9 @@ cannot allocate TLS data structures for initial thread");
#endif
NONTLS_INIT_TP;
- {
- /* Initialize _r_debug. */
- struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr);
- struct link_map *l;
-
- l = GL(dl_loaded);
-
-#ifdef ELF_MACHINE_DEBUG_SETUP
-
- /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */
-
- ELF_MACHINE_DEBUG_SETUP (l, r);
- ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r);
-
-#else
-
- if (l->l_info[DT_DEBUG] != NULL)
- /* There is a DT_DEBUG entry in the dynamic section. Fill it in
- with the run-time address of the r_debug structure */
- l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
-
- /* Fill in the pointer in the dynamic linker's own dynamic section, in
- case you run gdb on the dynamic linker directly. */
- if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL)
- GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
-
-#endif
-
- /* Notify the debugger that all objects are now mapped in. */
- r->r_state = RT_ADD;
- INTUSE(_dl_debug_state) ();
- }
+ /* Notify the debugger that all objects are now mapped in. */
+ r->r_state = RT_ADD;
+ INTUSE(_dl_debug_state) ();
#ifndef MAP_COPY
/* We must munmap() the cache file. */