OSDN Git Service

Don't allow text relocations on 64-bit.
authorElliott Hughes <enh@google.com>
Mon, 28 Oct 2013 21:19:05 +0000 (14:19 -0700)
committerElliott Hughes <enh@google.com>
Mon, 28 Oct 2013 21:34:56 +0000 (14:34 -0700)
I've also updated our <sys/exec_elf.h> to match upstream.

Change-Id: I52f9fce3167541811208d273ff23ceaa112f7135

libc/include/sys/exec_elf.h
linker/dlfcn.cpp
linker/linker.cpp
linker/linker.h

index 6d445bf..ec54a60 100644 (file)
@@ -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
index 166efac..09f3ddf 100644 (file)
@@ -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,
 };
index 5a4f20f..6bf18ac 100755 (executable)
@@ -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) {
index 4ba354d..b9e1237 100644 (file)
@@ -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 <sys/exec_elf.h> 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 <sys/exec_elf.h>.
-#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);