Module Name: src
Committed By: christos
Date: Tue Jun 14 13:06:41 UTC 2016
Modified Files:
src/libexec/ld.elf_so: Makefile headers.c map_object.c reloc.c rtld.h
Log Message:
Add support for GNU RELRO headers from Matthias Weckbecker.
To generate a diff of this commit:
cvs rdiff -u -r1.130 -r1.131 src/libexec/ld.elf_so/Makefile
cvs rdiff -u -r1.60 -r1.61 src/libexec/ld.elf_so/headers.c
cvs rdiff -u -r1.53 -r1.54 src/libexec/ld.elf_so/map_object.c
cvs rdiff -u -r1.108 -r1.109 src/libexec/ld.elf_so/reloc.c
cvs rdiff -u -r1.124 -r1.125 src/libexec/ld.elf_so/rtld.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/libexec/ld.elf_so/Makefile
diff -u src/libexec/ld.elf_so/Makefile:1.130 src/libexec/ld.elf_so/Makefile:1.131
--- src/libexec/ld.elf_so/Makefile:1.130 Sat Jan 23 16:22:47 2016
+++ src/libexec/ld.elf_so/Makefile Tue Jun 14 09:06:41 2016
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.130 2016/01/23 21:22:47 christos Exp $
+# $NetBSD: Makefile,v 1.131 2016/06/14 13:06:41 christos Exp $
#
# NOTE: when changing ld.so, ensure that ldd still compiles.
#
@@ -93,6 +93,7 @@ BINDIR= ${SHLINKINSTALLDIR}
CPPFLAGS+= -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\"
CPPFLAGS+= -I${.CURDIR} -I. -D_KERNTYPES
CPPFLAGS+= -DRTLD_LOADER
+CPPFLAGS+= -DGNU_RELRO
CPPFLAGS+= -D_RTLD_SOURCE
CPPFLAGS+= -DCOMBRELOC
#CPPFLAGS+= -DDEBUG
Index: src/libexec/ld.elf_so/headers.c
diff -u src/libexec/ld.elf_so/headers.c:1.60 src/libexec/ld.elf_so/headers.c:1.61
--- src/libexec/ld.elf_so/headers.c:1.60 Sun May 22 15:28:39 2016
+++ src/libexec/ld.elf_so/headers.c Tue Jun 14 09:06:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: headers.c,v 1.60 2016/05/22 19:28:39 joerg Exp $ */
+/* $NetBSD: headers.c,v 1.61 2016/06/14 13:06:41 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.60 2016/05/22 19:28:39 joerg Exp $");
+__RCSID("$NetBSD: headers.c,v 1.61 2016/06/14 13:06:41 christos Exp $");
#endif /* not lint */
#include <err.h>
@@ -432,6 +432,17 @@ _rtld_digest_phdr(const Elf_Phdr *phdr,
ph->p_memsz));
break;
+#ifdef GNU_RELRO
+ case PT_GNU_RELRO:
+ obj->relro_page = obj->relocbase
+ + round_down(ph->p_vaddr);
+ obj->relro_size = round_up(ph->p_memsz);
+ dbg(("headers: %s %p phsize %" PRImemsz,
+ "PT_GNU_RELRO", (void *)(uintptr_t)vaddr,
+ ph->p_memsz));
+ break;
+#endif
+
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
case PT_TLS:
obj->tlsindex = 1;
Index: src/libexec/ld.elf_so/map_object.c
diff -u src/libexec/ld.elf_so/map_object.c:1.53 src/libexec/ld.elf_so/map_object.c:1.54
--- src/libexec/ld.elf_so/map_object.c:1.53 Thu Oct 30 03:53:41 2014
+++ src/libexec/ld.elf_so/map_object.c Tue Jun 14 09:06:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: map_object.c,v 1.53 2014/10/30 07:53:41 martin Exp $ */
+/* $NetBSD: map_object.c,v 1.54 2016/06/14 13:06:41 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: map_object.c,v 1.53 2014/10/30 07:53:41 martin Exp $");
+__RCSID("$NetBSD: map_object.c,v 1.54 2016/06/14 13:06:41 christos Exp $");
#endif /* not lint */
#include <errno.h>
@@ -103,6 +103,10 @@ _rtld_map_object(const char *path, int f
caddr_t clear_addr;
size_t nclear;
#endif
+#ifdef GNU_RELRO
+ Elf_Addr relro_page;
+ size_t relro_size;
+#endif
if (sb != NULL && sb->st_size < (off_t)sizeof (Elf_Ehdr)) {
_rtld_error("%s: not ELF file (too short)", path);
@@ -173,6 +177,10 @@ _rtld_map_object(const char *path, int f
#endif
phsize = ehdr->e_phnum * sizeof(phdr[0]);
obj->phdr = NULL;
+#ifdef GNU_RELRO
+ relro_page = 0;
+ relro_size = 0;
+#endif
phdr_vaddr = EA_UNDEF;
phdr_memsz = 0;
phlimit = phdr + ehdr->e_phnum;
@@ -200,6 +208,13 @@ _rtld_map_object(const char *path, int f
(void *)(uintptr_t)phdr->p_vaddr, phdr->p_memsz));
break;
+#ifdef GNU_RELRO
+ case PT_GNU_RELRO:
+ relro_page = phdr->p_vaddr;
+ relro_size = phdr->p_memsz;
+ break;
+#endif
+
case PT_DYNAMIC:
obj->dynamic = (void *)(uintptr_t)phdr->p_vaddr;
dbg(("%s: %s %p phsize %" PRImemsz, obj->path, "PT_DYNAMIC",
@@ -267,6 +282,11 @@ _rtld_map_object(const char *path, int f
obj->vaddrbase = base_vaddr;
obj->isdynamic = ehdr->e_type == ET_DYN;
+#ifdef GNU_RELRO
+ obj->relro_page = obj->relocbase + round_down(relro_page);
+ obj->relro_size = round_up(relro_size);
+#endif
+
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
if (phtls != NULL) {
++_rtld_tls_dtv_generation;
Index: src/libexec/ld.elf_so/reloc.c
diff -u src/libexec/ld.elf_so/reloc.c:1.108 src/libexec/ld.elf_so/reloc.c:1.109
--- src/libexec/ld.elf_so/reloc.c:1.108 Tue Apr 12 15:10:48 2016
+++ src/libexec/ld.elf_so/reloc.c Tue Jun 14 09:06:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: reloc.c,v 1.108 2016/04/12 19:10:48 christos Exp $ */
+/* $NetBSD: reloc.c,v 1.109 2016/06/14 13:06:41 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.108 2016/04/12 19:10:48 christos Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.109 2016/06/14 13:06:41 christos Exp $");
#endif /* not lint */
#include <err.h>
@@ -223,6 +223,17 @@ _rtld_relocate_objects(Obj_Entry *first,
/* Set the special PLTGOT entries. */
if (obj->pltgot != NULL)
_rtld_setup_pltgot(obj);
+#ifdef GNU_RELRO
+ if (obj->relro_size > 0) {
+ if (mprotect(obj->relro_page, obj->relro_size,
+ PROT_READ) == -1) {
+ _rtld_error("%s: Cannot enforce relro "
+ "protection: %s", obj->path,
+ xstrerror(errno));
+ return -1;
+ }
+ }
+#endif
}
return 0;
Index: src/libexec/ld.elf_so/rtld.h
diff -u src/libexec/ld.elf_so/rtld.h:1.124 src/libexec/ld.elf_so/rtld.h:1.125
--- src/libexec/ld.elf_so/rtld.h:1.124 Fri Sep 19 13:43:33 2014
+++ src/libexec/ld.elf_so/rtld.h Tue Jun 14 09:06:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.124 2014/09/19 17:43:33 matt Exp $ */
+/* $NetBSD: rtld.h,v 1.125 2016/06/14 13:06:41 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -276,6 +276,12 @@ typedef struct Struct_Obj_Entry {
size_t tlsalign; /* Needed alignment for static TLS */
#endif
+#ifdef GNU_RELRO
+ /* relocation readonly */
+ void *relro_page;
+ size_t relro_size;
+#endif
+
/* symbol versioning */
const Elf_Verneed *verneed; /* Required versions. */
Elf_Word verneednum; /* Number of entries in verneed table */