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