1From 864054a6cb971688a181316b8227ae0361b4d69e Mon Sep 17 00:00:00 2001 2From: Andreas Schwab <schwab@suse.de> 3Date: Wed, 9 Oct 2019 17:46:47 +0200 4Subject: [PATCH] ldconfig: handle .dynstr located in separate segment (bug 5 25087) 6 7To determine the load offset of the DT_STRTAB section search for the 8segment containing it, instead of using the load offset of the first 9segment. 10 11Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=58e8f5fd2ba47b6dc47fd4d0a35e4175c7c87aaa] 12 13Backported: ported to support endianness and 32/64 bits. 14Signed-off-by: Fabien Mahot <fabien.mahot@external.desouttertools.com> 15--- 16 readelflib.c | 86 +++++++++++++++++++++++++++++++--------------------- 17 1 file changed, 52 insertions(+), 34 deletions(-) 18 19diff --git a/readelflib.c b/readelflib.c 20index a01e1cede3..380aed563d 100644 21--- a/readelflib.c 22+++ b/readelflib.c 23@@ -80,7 +80,6 @@ process_elf_file32 (const char *file_name, const char *lib, int *flag, 24 { 25 int i; 26 unsigned int j; 27- Elf32_Addr loadaddr; 28 unsigned int dynamic_addr; 29 size_t dynamic_size; 30 char *program_interpreter; 31@@ -110,7 +109,6 @@ process_elf_file32 (const char *file_name, const char *lib, int *flag, 32 libc5/libc6. */ 33 *flag = FLAG_ELF; 34 35- loadaddr = -1; 36 dynamic_addr = 0; 37 dynamic_size = 0; 38 program_interpreter = NULL; 39@@ -121,11 +119,6 @@ process_elf_file32 (const char *file_name, const char *lib, int *flag, 40 41 switch (read32(segment->p_type, be)) 42 { 43- case PT_LOAD: 44- if (loadaddr == (Elf32_Addr) -1) 45- loadaddr = read32(segment->p_vaddr, be) - read32(segment->p_offset, be); 46- break; 47- 48 case PT_DYNAMIC: 49 if (dynamic_addr) 50 error (0, 0, _("more than one dynamic segment\n")); 51@@ -188,11 +181,6 @@ process_elf_file32 (const char *file_name, const char *lib, int *flag, 52 } 53 54 } 55- if (loadaddr == (Elf32_Addr) -1) 56- { 57- /* Very strange. */ 58- loadaddr = 0; 59- } 60 61 /* Now we can read the dynamic sections. */ 62 if (dynamic_size == 0) 63@@ -208,11 +196,32 @@ process_elf_file32 (const char *file_name, const char *lib, int *flag, 64 { 65 check_ptr (dyn_entry); 66 if (read32(dyn_entry->d_tag, be) == DT_STRTAB) 67- { 68- dynamic_strings = (char *) (file_contents + read32(dyn_entry->d_un.d_val, be) - loadaddr); 69- check_ptr (dynamic_strings); 70- break; 71- } 72+ { 73+ /* Find the file offset of the segment containing the dynamic 74+ string table. */ 75+ Elf32_Off loadoff = -1; 76+ for (i = 0, segment = elf_pheader; 77+ i < read16(elf_header->e_phnum, be); i++, segment++) 78+ { 79+ if (read32(segment->p_type, be) == PT_LOAD 80+ && read32(dyn_entry->d_un.d_val, be) >= read32(segment->p_vaddr, be) 81+ && (read32(dyn_entry->d_un.d_val, be) - read32(segment->p_vaddr, be) 82+ < read32(segment->p_filesz, be))) 83+ { 84+ loadoff = read32(segment->p_vaddr, be) - read32(segment->p_offset, be); 85+ break; 86+ } 87+ } 88+ if (loadoff == (Elf32_Off) -1) 89+ { 90+ /* Very strange. */ 91+ loadoff = 0; 92+ } 93+ 94+ dynamic_strings = (char *) (file_contents + read32(dyn_entry->d_un.d_val, be) - loadoff); 95+ check_ptr (dynamic_strings); 96+ break; 97+ } 98 } 99 100 if (dynamic_strings == NULL) 101@@ -269,7 +278,6 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag, 102 { 103 int i; 104 unsigned int j; 105- Elf64_Addr loadaddr; 106 Elf64_Addr dynamic_addr; 107 Elf64_Xword dynamic_size; 108 char *program_interpreter; 109@@ -347,7 +355,6 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag, 110 break; 111 } 112 113- loadaddr = -1; 114 dynamic_addr = 0; 115 dynamic_size = 0; 116 program_interpreter = NULL; 117@@ -358,11 +365,6 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag, 118 119 switch (read32(segment->p_type, be)) 120 { 121- case PT_LOAD: 122- if (loadaddr == (Elf64_Addr) -1) 123- loadaddr = read64(segment->p_vaddr, be) - read64(segment->p_offset, be); 124- break; 125- 126 case PT_DYNAMIC: 127 if (dynamic_addr) 128 error (0, 0, _("more than one dynamic segment\n")); 129@@ -426,11 +428,6 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag, 130 } 131 132 } 133- if (loadaddr == (Elf64_Addr) -1) 134- { 135- /* Very strange. */ 136- loadaddr = 0; 137- } 138 139 /* Now we can read the dynamic sections. */ 140 if (dynamic_size == 0) 141@@ -446,11 +443,32 @@ process_elf_file64 (const char *file_name, const char *lib, int *flag, 142 { 143 check_ptr (dyn_entry); 144 if (read64(dyn_entry->d_tag, be) == DT_STRTAB) 145- { 146- dynamic_strings = (char *) (file_contents + read64(dyn_entry->d_un.d_val, be) - loadaddr); 147- check_ptr (dynamic_strings); 148- break; 149- } 150+ { 151+ /* Find the file offset of the segment containing the dynamic 152+ string table. */ 153+ Elf64_Off loadoff = -1; 154+ for (i = 0, segment = elf_pheader; 155+ i < read16(elf_header->e_phnum, be); i++, segment++) 156+ { 157+ if (read64(segment->p_type, be) == PT_LOAD 158+ && read64(dyn_entry->d_un.d_val, be) >= read64(segment->p_vaddr, be) 159+ && (read64(dyn_entry->d_un.d_val, be) - read64(segment->p_vaddr, be) 160+ < read64(segment->p_filesz, be))) 161+ { 162+ loadoff = read64(segment->p_vaddr, be) - read64(segment->p_offset, be); 163+ break; 164+ } 165+ } 166+ if (loadoff == (Elf32_Off) -1) 167+ { 168+ /* Very strange. */ 169+ loadoff = 0; 170+ } 171+ 172+ dynamic_strings = (char *) (file_contents + read64(dyn_entry->d_un.d_val, be) - loadoff); 173+ check_ptr (dynamic_strings); 174+ break; 175+ } 176 } 177 178 if (dynamic_strings == NULL) 179