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 */