From e4d792adb8d6f9228b9ac9dc1ad7f43b271f085f Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 28 Oct 2013 14:19:05 -0700 Subject: [PATCH] Don't allow text relocations on 64-bit. I've also updated our to match upstream. Change-Id: I52f9fce3167541811208d273ff23ceaa112f7135 --- libc/include/sys/exec_elf.h | 44 +++++++++++++++++++++++++++++-------- linker/dlfcn.cpp | 2 ++ linker/linker.cpp | 27 ++++++++++++++--------- linker/linker.h | 19 +++++++++------- 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/libc/include/sys/exec_elf.h b/libc/include/sys/exec_elf.h index 6d445bfd0..ec54a601a 100644 --- a/libc/include/sys/exec_elf.h +++ b/libc/include/sys/exec_elf.h @@ -1,4 +1,4 @@ -/* $NetBSD: exec_elf.h,v 1.126 2012/08/05 01:43:59 matt Exp $ */ +/* $NetBSD: exec_elf.h,v 1.129 2013/09/10 16:24:02 matt Exp $ */ /*- * Copyright (c) 1994 The NetBSD Foundation, Inc. @@ -429,6 +429,13 @@ typedef struct { #define SHT_HIOS 0x6fffffff #define SHT_LOPROC 0x70000000 /* Processor-specific range */ #define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_ARM_EXIDX 0x70000001 /* exception index table */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking + * pre-emption map */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility + * attributes */ +#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details */ +#define SHT_ARM_OVERLAYSECTION 0x70000005 #define SHT_HIPROC 0x7fffffff #define SHT_LOUSER 0x80000000 /* Application-specific range */ #define SHT_HIUSER 0xffffffff @@ -668,7 +675,12 @@ typedef struct { #define DT_FINI_ARRAY 26 /* Size, in bytes, of DT_INIT_ARRAY array */ #define DT_INIT_ARRAYSZ 27 /* Address of termination function array */ #define DT_FINI_ARRAYSZ 28 /* Size, in bytes, of DT_FINI_ARRAY array*/ -#define DT_NUM 29 +#define DT_RUNPATH 29 /* overrides DT_RPATH */ +#define DT_FLAGS 30 /* Encodes ORIGIN, SYMBOLIC, TEXTREL, BIND_NOW, STATIC_TLS */ +#define DT_ENCODING 31 /* ??? */ +#define DT_PREINIT_ARRAY 32 /* Address of pre-init function array */ +#define DT_PREINIT_ARRAYSZ 33 /* Size, in bytes, of DT_PREINIT_ARRAY array */ +#define DT_NUM 34 #define DT_LOOS 0x60000000 /* Operating system specific range */ #define DT_VERSYM 0x6ffffff0 /* Symbol versions */ @@ -802,7 +814,7 @@ typedef struct { * GNU-specific note type: Build ID generated by ld * name: GNU\0 * desc: - * word[0..4] SHA1 [default] + * word[0..4] SHA1 [default] * or * word[0..3] md5 or uuid * descsz: 16 or 20 @@ -829,7 +841,7 @@ typedef struct { /* SuSE-specific note type: version * name: SuSE\0\0\0\0 * namesz: 8 - * desc: + * desc: * word[0] = VVTTMMmm * * V = version of following data @@ -848,7 +860,7 @@ typedef struct { /* NetBSD-specific note type: Emulation name. * name: NetBSD\0\0 * namesz: 8 - * desc: + * desc: * word[0]: MMmmrrpp00 * * M = major version @@ -864,7 +876,7 @@ typedef struct { /* NetBSD-specific note name */ #define ELF_NOTE_NETBSD_NAME "NetBSD\0\0" -/* NetBSD-specific note type: Checksum. +/* NetBSD-specific note type: Checksum. * There should be 1 NOTE per PT_LOAD section. * name: ??? * namesz: ??? @@ -953,6 +965,20 @@ struct netbsd_elfcore_procinfo { int32_t cpi_siglwp; /* LWP target of killing signal */ }; +/* + * NetBSD-specific note type: MACHINE_ARCH. + * There should be 1 NOTE per executable. + * name: NetBSD\0 + * namesz: 7 + * desc: string + * descsz: variable + */ +#define ELF_NOTE_TYPE_MARCH_TAG 5 +/* NetBSD-specific note name and description sizes */ +#define ELF_NOTE_MARCH_NAMESZ ELF_NOTE_NETBSD_NAMESZ +/* NetBSD-specific note name */ +#define ELF_NOTE_MARCH_NAME ELF_NOTE_NETBSD_NAME + #if !defined(ELFSIZE) && defined(ARCH_ELFSIZE) #define ELFSIZE ARCH_ELFSIZE #endif @@ -1067,7 +1093,7 @@ typedef struct { #define SYMINFO_NUM 2 /* - * These constants are used for Elf32_Verdef struct's version number. + * These constants are used for Elf32_Verdef struct's version number. */ #define VER_DEF_NONE 0 #define VER_DEF_CURRENT 1 @@ -1078,7 +1104,7 @@ typedef struct { #define VER_DEF_IDX(x) VER_NDX(x) /* - * These constants are used for Elf32_Verdef struct's vd_flags. + * These constants are used for Elf32_Verdef struct's vd_flags. */ #define VER_FLG_BASE 0x1 #define VER_FLG_WEAK 0x2 @@ -1091,7 +1117,7 @@ typedef struct { #define VER_NDX_GIVEN 2 /* - * These constants are used for Elf32_Verneed struct's version number. + * These constants are used for Elf32_Verneed struct's version number. */ #define VER_NEED_NONE 0 #define VER_NEED_CURRENT 1 diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp index 166efacf6..09f3ddffd 100644 --- a/linker/dlfcn.cpp +++ b/linker/dlfcn.cpp @@ -295,6 +295,8 @@ soinfo libdl_info = { { .l_addr = 0, .l_name = 0, .l_ld = 0, .l_next = 0, .l_prev = 0, }, .constructors_called = false, .load_bias = 0, +#if !defined(__LP64__) .has_text_relocations = false, +#endif .has_DT_SYMBOLIC = true, }; diff --git a/linker/linker.cpp b/linker/linker.cpp index 5a4f20f6b..6bf18ac9b 100755 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -1548,25 +1548,32 @@ static bool soinfo_link_image(soinfo* si) { si->preinit_array_count = ((unsigned)d->d_un.d_val) / sizeof(Elf_Addr); break; case DT_TEXTREL: +#if defined(__LP64__) + DL_ERR("text relocations (DT_TEXTREL) found in 64-bit ELF file \"%s\"", si->name); + return false; +#else si->has_text_relocations = true; break; +#endif case DT_SYMBOLIC: si->has_DT_SYMBOLIC = true; break; case DT_NEEDED: ++needed_count; break; -#if defined DT_FLAGS - // TODO: why is DT_FLAGS not defined? case DT_FLAGS: if (d->d_un.d_val & DF_TEXTREL) { +#if defined(__LP64__) + DL_ERR("text relocations (DF_TEXTREL) found in 64-bit ELF file \"%s\"", si->name); + return false; +#else si->has_text_relocations = true; +#endif } if (d->d_un.d_val & DF_SYMBOLIC) { si->has_DT_SYMBOLIC = true; } break; -#endif #if defined(__mips__) case DT_STRSZ: case DT_SYMENT: @@ -1661,12 +1668,10 @@ static bool soinfo_link_image(soinfo* si) { } *pneeded = NULL; +#if !defined(__LP64__) if (si->has_text_relocations) { - /* Unprotect the segments, i.e. make them writable, to allow - * text relocations to work properly. We will later call - * phdr_table_protect_segments() after all of them are applied - * and all constructors are run. - */ + // Make segments writable to allow text relocations to work properly. We will later call + // phdr_table_protect_segments() after all of them are applied and all constructors are run. DL_WARN("%s has text relocations. This is wasting memory and prevents " "security hardening. Please fix.", si->name); if (phdr_table_unprotect_segments(si->phdr, si->phnum, si->load_bias) < 0) { @@ -1675,6 +1680,7 @@ static bool soinfo_link_image(soinfo* si) { return false; } } +#endif #if defined(USE_RELA) if (si->plt_rela != NULL) { @@ -1713,15 +1719,16 @@ static bool soinfo_link_image(soinfo* si) { si->flags |= FLAG_LINKED; DEBUG("[ finished linking %s ]", si->name); +#if !defined(__LP64__) if (si->has_text_relocations) { - /* All relocations are done, we can protect our segments back to - * read-only. */ + // All relocations are done, we can protect our segments back to read-only. if (phdr_table_protect_segments(si->phdr, si->phnum, si->load_bias) < 0) { DL_ERR("can't protect segments for \"%s\": %s", si->name, strerror(errno)); return false; } } +#endif /* We can also turn on GNU RELRO protection */ if (phdr_table_protect_gnu_relro(si->phdr, si->phnum, si->load_bias) < 0) { diff --git a/linker/linker.h b/linker/linker.h index 4ba354d8f..b9e12377e 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -183,7 +183,9 @@ struct soinfo { // value to get the corresponding address in the process' address space. Elf_Addr load_bias; +#if !defined(__LP64__) bool has_text_relocations; +#endif bool has_DT_SYMBOLIC; void CallConstructors(); @@ -195,15 +197,16 @@ struct soinfo { void CallFunction(const char* function_name, linker_function_t function); }; -extern soinfo libdl_info; +// The possible DT_FLAGS bits are in +// http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#dynamic_section +// but not in the upstream NetBSD header file ours is based on. +#define DF_ORIGIN 0x1 +#define DF_SYMBOLIC 0x2 +#define DF_TEXTREL 0x4 +#define DF_BIND_NOW 0x8 +#define DF_STATIC_TLS 0x10 -// These aren't defined in . -#ifndef DT_PREINIT_ARRAY -#define DT_PREINIT_ARRAY 32 -#endif -#ifndef DT_PREINIT_ARRAYSZ -#define DT_PREINIT_ARRAYSZ 33 -#endif +extern soinfo libdl_info; void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path); soinfo* do_dlopen(const char* name, int flags);