Branch data Line data Source code
1 : : /* Reconstruct an ELF file by reading the segments out of remote memory.
2 : : Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #include <config.h>
30 : : #include "libelfP.h"
31 : :
32 : : #include "libdwflP.h"
33 : :
34 : : #include <gelf.h>
35 : : #include <sys/types.h>
36 : : #include <stdbool.h>
37 : : #include <stdlib.h>
38 : : #include <string.h>
39 : :
40 : : /* Reconstruct an ELF file by reading the segments out of remote memory
41 : : based on the ELF file header at EHDR_VMA and the ELF program headers it
42 : : points to. If not null, *LOADBASEP is filled in with the difference
43 : : between the addresses from which the segments were read, and the
44 : : addresses the file headers put them at.
45 : :
46 : : The function READ_MEMORY is called to copy at least MINREAD and at most
47 : : MAXREAD bytes from the remote memory at target address ADDRESS into the
48 : : local buffer at DATA; it should return -1 for errors (with code in
49 : : `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
50 : : the number of bytes read if >= MINREAD. ARG is passed through.
51 : :
52 : : PAGESIZE is the minimum page size and alignment used for the PT_LOAD
53 : : segments. */
54 : :
55 : : Elf *
56 : 20 : elf_from_remote_memory (GElf_Addr ehdr_vma,
57 : : GElf_Xword pagesize,
58 : : GElf_Addr *loadbasep,
59 : : ssize_t (*read_memory) (void *arg, void *data,
60 : : GElf_Addr address,
61 : : size_t minread,
62 : : size_t maxread),
63 : : void *arg)
64 : : {
65 : : /* We might have to reserve some memory for the phdrs. Set to NULL
66 : : here so we can always safely free it. */
67 : 20 : void *phdrsp = NULL;
68 : :
69 : : /* First read in the file header and check its sanity. */
70 : :
71 : 20 : const size_t initial_bufsize = 256;
72 : 20 : unsigned char *buffer = malloc (initial_bufsize);
73 [ - + ]: 20 : if (unlikely (buffer == NULL))
74 : : {
75 : 0 : no_memory:
76 : 0 : __libdwfl_seterrno (DWFL_E_NOMEM);
77 : 0 : return NULL;
78 : : }
79 : :
80 : 20 : ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
81 : : sizeof (Elf32_Ehdr), initial_bufsize);
82 [ - + ]: 20 : if (nread <= 0)
83 : : {
84 : 0 : read_error:
85 : 2 : free (buffer);
86 : 2 : free (phdrsp);
87 [ + - ]: 2 : __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
88 : 2 : return NULL;
89 : : }
90 : :
91 [ - + ]: 20 : if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
92 : : {
93 : 0 : bad_elf:
94 : 0 : free (buffer);
95 : 0 : free (phdrsp);
96 : 0 : __libdwfl_seterrno (DWFL_E_BADELF);
97 : 0 : return NULL;
98 : : }
99 : :
100 : : /* Extract the information we need from the file header. */
101 : :
102 : 20 : union
103 : : {
104 : : Elf32_Ehdr e32;
105 : : Elf64_Ehdr e64;
106 : : } ehdr;
107 : 20 : Elf_Data xlatefrom =
108 : : {
109 : : .d_type = ELF_T_EHDR,
110 : : .d_buf = buffer,
111 : : .d_version = EV_CURRENT,
112 : : };
113 : 20 : Elf_Data xlateto =
114 : : {
115 : : .d_type = ELF_T_EHDR,
116 : : .d_buf = &ehdr,
117 : : .d_size = sizeof ehdr,
118 : : .d_version = EV_CURRENT,
119 : : };
120 : :
121 : 20 : GElf_Off phoff;
122 : 20 : uint_fast16_t phnum;
123 : 20 : uint_fast16_t phentsize;
124 : 20 : GElf_Off shdrs_end;
125 : :
126 [ - + - ]: 20 : switch (buffer[EI_CLASS])
127 : : {
128 : 0 : case ELFCLASS32:
129 : 0 : xlatefrom.d_size = sizeof (Elf32_Ehdr);
130 [ # # ]: 0 : if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
131 : : {
132 : 0 : libelf_error:
133 : 0 : __libdwfl_seterrno (DWFL_E_LIBELF);
134 : 0 : return NULL;
135 : : }
136 : 0 : phoff = ehdr.e32.e_phoff;
137 : 0 : phnum = ehdr.e32.e_phnum;
138 : 0 : phentsize = ehdr.e32.e_phentsize;
139 [ # # ]: 0 : if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
140 : 0 : goto bad_elf;
141 : : /* NOTE if the number of sections is > 0xff00 then e_shnum
142 : : is zero and the actual number would come from the section
143 : : zero sh_size field. We ignore this here because getting shdrs
144 : : is just a nice bonus (see below where we trim the last phdrs
145 : : PT_LOAD segment). */
146 : 0 : shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
147 : 0 : break;
148 : :
149 : 20 : case ELFCLASS64:
150 : 20 : xlatefrom.d_size = sizeof (Elf64_Ehdr);
151 [ - + ]: 20 : if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
152 : 0 : goto libelf_error;
153 : 20 : phoff = ehdr.e64.e_phoff;
154 : 20 : phnum = ehdr.e64.e_phnum;
155 : 20 : phentsize = ehdr.e64.e_phentsize;
156 [ - + ]: 20 : if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
157 : 0 : goto bad_elf;
158 : : /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum. */
159 : 20 : shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
160 : 20 : break;
161 : :
162 : 0 : default:
163 : 0 : goto bad_elf;
164 : : }
165 : :
166 : :
167 : : /* The file header tells where to find the program headers.
168 : : These are what we use to actually choose what to read. */
169 : :
170 : 20 : xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
171 : 20 : xlatefrom.d_size = phnum * phentsize;
172 : :
173 [ + + ]: 20 : if (phoff <= (size_t) nread
174 [ + + ]: 18 : && (size_t) phnum * phentsize <= (size_t) nread - phoff)
175 : : /* We already have all the phdrs from the initial read. */
176 : 2 : xlatefrom.d_buf = buffer + phoff;
177 : : else
178 : : {
179 : : /* Read in the program headers. */
180 : :
181 [ + + ]: 18 : if (initial_bufsize < (size_t)phnum * phentsize)
182 : : {
183 : 2 : unsigned char *newbuf = realloc (buffer, phnum * phentsize);
184 [ - + ]: 2 : if (newbuf == NULL)
185 : : {
186 : 0 : free (buffer);
187 : 0 : free (phdrsp);
188 : 0 : goto no_memory;
189 : : }
190 : : buffer = newbuf;
191 : : }
192 : 18 : nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
193 : : phnum * phentsize, phnum * phentsize);
194 [ + + ]: 18 : if (nread <= 0)
195 : 2 : goto read_error;
196 : :
197 : 16 : xlatefrom.d_buf = buffer;
198 : : }
199 : :
200 : 18 : bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
201 [ + - ]: 18 : size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
202 [ - + ]: 18 : if (unlikely (phnum > SIZE_MAX / phdr_size))
203 : : {
204 : 0 : free (buffer);
205 : 0 : goto no_memory;
206 : : }
207 : 18 : const size_t phdrsp_bytes = phnum * phdr_size;
208 : 18 : phdrsp = malloc (phdrsp_bytes);
209 [ - + ]: 18 : if (unlikely (phdrsp == NULL))
210 : : {
211 : 0 : free (buffer);
212 : 0 : goto no_memory;
213 : : }
214 : :
215 : 18 : xlateto.d_buf = phdrsp;
216 : 18 : xlateto.d_size = phdrsp_bytes;
217 : :
218 : : /* Scan for PT_LOAD segments to find the total size of the file image. */
219 : 18 : size_t contents_size = 0;
220 : 18 : GElf_Off segments_end = 0;
221 : 18 : GElf_Off segments_end_mem = 0;
222 : 18 : GElf_Addr loadbase = ehdr_vma;
223 : 18 : bool found_base = false;
224 : 18 : Elf32_Phdr (*p32)[phnum] = phdrsp;
225 : 18 : Elf64_Phdr (*p64)[phnum] = phdrsp;
226 : :
227 [ - + ]: 18 : if (class32)
228 : : {
229 [ # # ]: 0 : if (! elf32_xlatetom (&xlateto, &xlatefrom, ehdr.e32.e_ident[EI_DATA]))
230 : 0 : goto libelf_error;
231 : : }
232 : : else
233 : : {
234 [ - + ]: 18 : if (! elf64_xlatetom (&xlateto, &xlatefrom, ehdr.e64.e_ident[EI_DATA]))
235 : 0 : goto libelf_error;
236 : : }
237 : :
238 [ + + ]: 94 : for (uint_fast16_t i = 0; i < phnum; ++i)
239 : : {
240 [ - + ]: 76 : GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
241 : :
242 [ + + ]: 76 : if (type != PT_LOAD)
243 : 52 : continue;
244 : :
245 [ - + ]: 24 : GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
246 : 24 : GElf_Xword memsz = class32 ? (*p32)[i].p_memsz : (*p64)[i].p_memsz;
247 : 24 : GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
248 : 24 : GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
249 : :
250 : : /* Sanity check the segment load aligns with the pagesize. */
251 [ - + ]: 24 : if (((vaddr - offset) & (pagesize - 1)) != 0)
252 : 0 : goto bad_elf;
253 : :
254 : 24 : GElf_Off segment_end = ((offset + filesz + pagesize - 1)
255 : 24 : & -pagesize);
256 : :
257 : 24 : if (segment_end > (GElf_Off) contents_size)
258 : : contents_size = segment_end;
259 : :
260 [ + + + - ]: 24 : if (!found_base && (offset & -pagesize) == 0)
261 : : {
262 : 18 : loadbase = ehdr_vma - (vaddr & -pagesize);
263 : 18 : found_base = true;
264 : : }
265 : :
266 : 24 : segments_end = offset + filesz;
267 : 24 : segments_end_mem = offset + memsz;
268 : : }
269 : :
270 : : /* Trim the last segment so we don't bother with zeros in the last page
271 : : that are off the end of the file. However, if the extra bit in that
272 : : page includes the section headers and the memory isn't extended (which
273 : : might indicate it will have been reused otherwise), keep them. */
274 : 18 : if ((GElf_Off) contents_size > segments_end
275 [ + + ]: 18 : && (GElf_Off) contents_size >= shdrs_end
276 [ + - ]: 16 : && segments_end == segments_end_mem)
277 : : {
278 : 16 : contents_size = segments_end;
279 : 16 : if ((GElf_Off) contents_size < shdrs_end)
280 : 18 : contents_size = shdrs_end;
281 : : }
282 : : else
283 : : contents_size = segments_end;
284 : :
285 : 18 : free (buffer);
286 : :
287 : : /* Now we know the size of the whole image we want read in. */
288 : 18 : buffer = calloc (1, contents_size);
289 [ - + ]: 18 : if (buffer == NULL)
290 : : {
291 : 0 : free (phdrsp);
292 : 0 : goto no_memory;
293 : : }
294 : :
295 [ + + ]: 94 : for (uint_fast16_t i = 0; i < phnum; ++i)
296 : : {
297 [ - + ]: 76 : GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
298 : :
299 [ + + ]: 76 : if (type != PT_LOAD)
300 : 52 : continue;
301 : :
302 [ - + ]: 24 : GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
303 : 24 : GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
304 : 24 : GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
305 : :
306 : 24 : GElf_Off start = offset & -pagesize;
307 : 24 : GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
308 : : /* The final contents_size is the trimmed last segment's end, which
309 : : may be smaller than an earlier segment's start (segments_end above
310 : : tracks the last PT_LOAD, not the maximum). Skip any segment that
311 : : falls entirely past it: otherwise buffer + start would be out of
312 : : bounds and end - start would underflow into a huge read length.
313 : : Mirrors the file_trimmed_end check in dwfl_segment_report_module. */
314 [ - + ]: 24 : if (start >= (GElf_Off) contents_size)
315 : 0 : continue;
316 : 24 : if (end > (GElf_Off) contents_size)
317 : : end = contents_size;
318 : 48 : nread = (*read_memory) (arg, buffer + start,
319 : 24 : (loadbase + vaddr) & -pagesize,
320 : : end - start, end - start);
321 [ - + ]: 24 : if (nread <= 0)
322 : 0 : goto read_error;
323 : : }
324 : :
325 : : /* If the segments visible in memory didn't include the section
326 : : headers, then clear them from the file header. */
327 [ + + ]: 18 : if (contents_size < shdrs_end)
328 : : {
329 [ - + ]: 2 : if (class32)
330 : : {
331 : 0 : ehdr.e32.e_shoff = 0;
332 : 0 : ehdr.e32.e_shnum = 0;
333 : 0 : ehdr.e32.e_shstrndx = 0;
334 : : }
335 : : else
336 : : {
337 : 2 : ehdr.e64.e_shoff = 0;
338 : 2 : ehdr.e64.e_shnum = 0;
339 : 2 : ehdr.e64.e_shstrndx = 0;
340 : : }
341 : : }
342 : :
343 : : /* This will normally have been in the first PT_LOAD segment. But it
344 : : conceivably could be missing, and we might have just changed it. */
345 : 18 : xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
346 : 18 : xlateto.d_buf = buffer;
347 [ - + ]: 18 : if (class32)
348 : : {
349 : 0 : xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
350 : 0 : xlatefrom.d_buf = &ehdr.e32;
351 [ # # ]: 0 : if (elf32_xlatetof (&xlateto, &xlatefrom,
352 : 0 : ehdr.e32.e_ident[EI_DATA]) == NULL)
353 : 0 : goto libelf_error;
354 : : }
355 : : else
356 : : {
357 : 18 : xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
358 : 18 : xlatefrom.d_buf = &ehdr.e64;
359 [ - + ]: 18 : if (elf64_xlatetof (&xlateto, &xlatefrom,
360 : 18 : ehdr.e64.e_ident[EI_DATA]) == NULL)
361 : 0 : goto libelf_error;
362 : : }
363 : :
364 : 18 : free (phdrsp);
365 : 18 : phdrsp = NULL;
366 : :
367 : : /* Now we have the image. Open libelf on it. */
368 : :
369 : 18 : Elf *elf = elf_memory ((char *) buffer, contents_size);
370 [ - + ]: 18 : if (elf == NULL)
371 : : {
372 : 0 : free (buffer);
373 : 0 : goto libelf_error;
374 : : }
375 : :
376 : 18 : elf->flags |= ELF_F_MALLOCED;
377 [ - + ]: 18 : if (loadbasep != NULL)
378 : 0 : *loadbasep = loadbase;
379 : : return elf;
380 : : }
|