• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include "linker_phdr.h"
30 
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/mman.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 
38 #include "linker.h"
39 #include "linker_debug.h"
40 
GetTargetElfMachine()41 static int GetTargetElfMachine() {
42 #if defined(__arm__)
43   return EM_ARM;
44 #elif defined(__aarch64__)
45   return EM_AARCH64;
46 #elif defined(__i386__)
47   return EM_386;
48 #elif defined(__mips__)
49   return EM_MIPS;
50 #elif defined(__x86_64__)
51   return EM_X86_64;
52 #endif
53 }
54 
55 /**
56   TECHNICAL NOTE ON ELF LOADING.
57 
58   An ELF file's program header table contains one or more PT_LOAD
59   segments, which corresponds to portions of the file that need to
60   be mapped into the process' address space.
61 
62   Each loadable segment has the following important properties:
63 
64     p_offset  -> segment file offset
65     p_filesz  -> segment file size
66     p_memsz   -> segment memory size (always >= p_filesz)
67     p_vaddr   -> segment's virtual address
68     p_flags   -> segment flags (e.g. readable, writable, executable)
69 
70   We will ignore the p_paddr and p_align fields of ElfW(Phdr) for now.
71 
72   The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz)
73   ranges of virtual addresses. A few rules apply:
74 
75   - the virtual address ranges should not overlap.
76 
77   - if a segment's p_filesz is smaller than its p_memsz, the extra bytes
78     between them should always be initialized to 0.
79 
80   - ranges do not necessarily start or end at page boundaries. Two distinct
81     segments can have their start and end on the same page. In this case, the
82     page inherits the mapping flags of the latter segment.
83 
84   Finally, the real load addrs of each segment is not p_vaddr. Instead the
85   loader decides where to load the first segment, then will load all others
86   relative to the first one to respect the initial range layout.
87 
88   For example, consider the following list:
89 
90     [ offset:0,      filesz:0x4000, memsz:0x4000, vaddr:0x30000 ],
91     [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ],
92 
93   This corresponds to two segments that cover these virtual address ranges:
94 
95        0x30000...0x34000
96        0x40000...0x48000
97 
98   If the loader decides to load the first segment at address 0xa0000000
99   then the segments' load address ranges will be:
100 
101        0xa0030000...0xa0034000
102        0xa0040000...0xa0048000
103 
104   In other words, all segments must be loaded at an address that has the same
105   constant offset from their p_vaddr value. This offset is computed as the
106   difference between the first segment's load address, and its p_vaddr value.
107 
108   However, in practice, segments do _not_ start at page boundaries. Since we
109   can only memory-map at page boundaries, this means that the bias is
110   computed as:
111 
112        load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr)
113 
114   (NOTE: The value must be used as a 32-bit unsigned integer, to deal with
115           possible wrap around UINT32_MAX for possible large p_vaddr values).
116 
117   And that the phdr0_load_address must start at a page boundary, with
118   the segment's real content starting at:
119 
120        phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr)
121 
122   Note that ELF requires the following condition to make the mmap()-ing work:
123 
124       PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset)
125 
126   The load_bias must be added to any p_vaddr value read from the ELF file to
127   determine the corresponding memory address.
128 
129  **/
130 
131 #define MAYBE_MAP_FLAG(x, from, to)  (((x) & (from)) ? (to) : 0)
132 #define PFLAGS_TO_PROT(x)            (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \
133                                       MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
134                                       MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
135 
ElfReader(const char * name,int fd,off64_t file_offset,off64_t file_size)136 ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size)
137     : name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size),
138       phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
139       load_start_(nullptr), load_size_(0), load_bias_(0),
140       loaded_phdr_(nullptr) {
141 }
142 
~ElfReader()143 ElfReader::~ElfReader() {
144   if (phdr_mmap_ != nullptr) {
145     munmap(phdr_mmap_, phdr_size_);
146   }
147 }
148 
Load(const android_dlextinfo * extinfo)149 bool ElfReader::Load(const android_dlextinfo* extinfo) {
150   return ReadElfHeader() &&
151          VerifyElfHeader() &&
152          ReadProgramHeader() &&
153          ReserveAddressSpace(extinfo) &&
154          LoadSegments() &&
155          FindPhdr();
156 }
157 
ReadElfHeader()158 bool ElfReader::ReadElfHeader() {
159   ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
160   if (rc < 0) {
161     DL_ERR("can't read file \"%s\": %s", name_, strerror(errno));
162     return false;
163   }
164 
165   if (rc != sizeof(header_)) {
166     DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_,
167            static_cast<size_t>(rc));
168     return false;
169   }
170   return true;
171 }
172 
VerifyElfHeader()173 bool ElfReader::VerifyElfHeader() {
174   if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
175     DL_ERR("\"%s\" has bad ELF magic", name_);
176     return false;
177   }
178 
179   // Try to give a clear diagnostic for ELF class mismatches, since they're
180   // an easy mistake to make during the 32-bit/64-bit transition period.
181   int elf_class = header_.e_ident[EI_CLASS];
182 #if defined(__LP64__)
183   if (elf_class != ELFCLASS64) {
184     if (elf_class == ELFCLASS32) {
185       DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_);
186     } else {
187       DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
188     }
189     return false;
190   }
191 #else
192   if (elf_class != ELFCLASS32) {
193     if (elf_class == ELFCLASS64) {
194       DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_);
195     } else {
196       DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class);
197     }
198     return false;
199   }
200 #endif
201 
202   if (header_.e_ident[EI_DATA] != ELFDATA2LSB) {
203     DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]);
204     return false;
205   }
206 
207   if (header_.e_type != ET_DYN) {
208     DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type);
209     return false;
210   }
211 
212   if (header_.e_version != EV_CURRENT) {
213     DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version);
214     return false;
215   }
216 
217   if (header_.e_machine != GetTargetElfMachine()) {
218     DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine);
219     return false;
220   }
221 
222   return true;
223 }
224 
225 // Loads the program header table from an ELF file into a read-only private
226 // anonymous mmap-ed block.
ReadProgramHeader()227 bool ElfReader::ReadProgramHeader() {
228   phdr_num_ = header_.e_phnum;
229 
230   // Like the kernel, we only accept program header tables that
231   // are smaller than 64KiB.
232   if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) {
233     DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_);
234     return false;
235   }
236 
237   ElfW(Addr) page_min = PAGE_START(header_.e_phoff);
238   ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr))));
239   ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff);
240 
241   phdr_size_ = page_max - page_min;
242 
243   void* mmap_result =
244       mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min);
245   if (mmap_result == MAP_FAILED) {
246     DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
247     return false;
248   }
249 
250   phdr_mmap_ = mmap_result;
251   phdr_table_ = reinterpret_cast<ElfW(Phdr)*>(reinterpret_cast<char*>(mmap_result) + page_offset);
252   return true;
253 }
254 
255 /* Returns the size of the extent of all the possibly non-contiguous
256  * loadable segments in an ELF program header table. This corresponds
257  * to the page-aligned size in bytes that needs to be reserved in the
258  * process' address space. If there are no loadable segments, 0 is
259  * returned.
260  *
261  * If out_min_vaddr or out_max_vaddr are not null, they will be
262  * set to the minimum and maximum addresses of pages to be reserved,
263  * or 0 if there is nothing to load.
264  */
phdr_table_get_load_size(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)* out_min_vaddr,ElfW (Addr)* out_max_vaddr)265 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
266                                 ElfW(Addr)* out_min_vaddr,
267                                 ElfW(Addr)* out_max_vaddr) {
268   ElfW(Addr) min_vaddr = UINTPTR_MAX;
269   ElfW(Addr) max_vaddr = 0;
270 
271   bool found_pt_load = false;
272   for (size_t i = 0; i < phdr_count; ++i) {
273     const ElfW(Phdr)* phdr = &phdr_table[i];
274 
275     if (phdr->p_type != PT_LOAD) {
276       continue;
277     }
278     found_pt_load = true;
279 
280     if (phdr->p_vaddr < min_vaddr) {
281       min_vaddr = phdr->p_vaddr;
282     }
283 
284     if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) {
285       max_vaddr = phdr->p_vaddr + phdr->p_memsz;
286     }
287   }
288   if (!found_pt_load) {
289     min_vaddr = 0;
290   }
291 
292   min_vaddr = PAGE_START(min_vaddr);
293   max_vaddr = PAGE_END(max_vaddr);
294 
295   if (out_min_vaddr != nullptr) {
296     *out_min_vaddr = min_vaddr;
297   }
298   if (out_max_vaddr != nullptr) {
299     *out_max_vaddr = max_vaddr;
300   }
301   return max_vaddr - min_vaddr;
302 }
303 
304 // Reserve a virtual address range big enough to hold all loadable
305 // segments of a program header table. This is done by creating a
306 // private anonymous mmap() with PROT_NONE.
ReserveAddressSpace(const android_dlextinfo * extinfo)307 bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
308   ElfW(Addr) min_vaddr;
309   load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr);
310   if (load_size_ == 0) {
311     DL_ERR("\"%s\" has no loadable segments", name_);
312     return false;
313   }
314 
315   uint8_t* addr = reinterpret_cast<uint8_t*>(min_vaddr);
316   void* start;
317   size_t reserved_size = 0;
318   bool reserved_hint = true;
319   // Assume position independent executable by default.
320   uint8_t* mmap_hint = nullptr;
321 
322   if (extinfo != nullptr) {
323     if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
324       reserved_size = extinfo->reserved_size;
325       reserved_hint = false;
326     } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
327       reserved_size = extinfo->reserved_size;
328     }
329 
330     if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) {
331       mmap_hint = addr;
332     }
333   }
334 
335   if (load_size_ > reserved_size) {
336     if (!reserved_hint) {
337       DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"",
338              reserved_size - load_size_, load_size_, name_);
339       return false;
340     }
341     int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
342     start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0);
343     if (start == MAP_FAILED) {
344       DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
345       return false;
346     }
347   } else {
348     start = extinfo->reserved_addr;
349   }
350 
351   load_start_ = start;
352   load_bias_ = reinterpret_cast<uint8_t*>(start) - addr;
353   return true;
354 }
355 
LoadSegments()356 bool ElfReader::LoadSegments() {
357   for (size_t i = 0; i < phdr_num_; ++i) {
358     const ElfW(Phdr)* phdr = &phdr_table_[i];
359 
360     if (phdr->p_type != PT_LOAD) {
361       continue;
362     }
363 
364     // Segment addresses in memory.
365     ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
366     ElfW(Addr) seg_end   = seg_start + phdr->p_memsz;
367 
368     ElfW(Addr) seg_page_start = PAGE_START(seg_start);
369     ElfW(Addr) seg_page_end   = PAGE_END(seg_end);
370 
371     ElfW(Addr) seg_file_end   = seg_start + phdr->p_filesz;
372 
373     // File offsets.
374     ElfW(Addr) file_start = phdr->p_offset;
375     ElfW(Addr) file_end   = file_start + phdr->p_filesz;
376 
377     ElfW(Addr) file_page_start = PAGE_START(file_start);
378     ElfW(Addr) file_length = file_end - file_page_start;
379 
380     if (file_size_ <= 0) {
381       DL_ERR("\"%s\" invalid file size: %" PRId64, name_, file_size_);
382       return false;
383     }
384 
385     if (file_end >= static_cast<size_t>(file_size_)) {
386       DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
387           " p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
388           name_, i, reinterpret_cast<void*>(phdr->p_offset),
389           reinterpret_cast<void*>(phdr->p_filesz),
390           reinterpret_cast<void*>(file_end), file_size_);
391       return false;
392     }
393 
394     if (file_length != 0) {
395       void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
396                             file_length,
397                             PFLAGS_TO_PROT(phdr->p_flags),
398                             MAP_FIXED|MAP_PRIVATE,
399                             fd_,
400                             file_offset_ + file_page_start);
401       if (seg_addr == MAP_FAILED) {
402         DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno));
403         return false;
404       }
405     }
406 
407     // if the segment is writable, and does not end on a page boundary,
408     // zero-fill it until the page limit.
409     if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) {
410       memset(reinterpret_cast<void*>(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end));
411     }
412 
413     seg_file_end = PAGE_END(seg_file_end);
414 
415     // seg_file_end is now the first page address after the file
416     // content. If seg_end is larger, we need to zero anything
417     // between them. This is done by using a private anonymous
418     // map for all extra pages.
419     if (seg_page_end > seg_file_end) {
420       void* zeromap = mmap(reinterpret_cast<void*>(seg_file_end),
421                            seg_page_end - seg_file_end,
422                            PFLAGS_TO_PROT(phdr->p_flags),
423                            MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
424                            -1,
425                            0);
426       if (zeromap == MAP_FAILED) {
427         DL_ERR("couldn't zero fill \"%s\" gap: %s", name_, strerror(errno));
428         return false;
429       }
430     }
431   }
432   return true;
433 }
434 
435 /* Used internally. Used to set the protection bits of all loaded segments
436  * with optional extra flags (i.e. really PROT_WRITE). Used by
437  * phdr_table_protect_segments and phdr_table_unprotect_segments.
438  */
_phdr_table_set_load_prot(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias,int extra_prot_flags)439 static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
440                                      ElfW(Addr) load_bias, int extra_prot_flags) {
441   const ElfW(Phdr)* phdr = phdr_table;
442   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
443 
444   for (; phdr < phdr_limit; phdr++) {
445     if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) {
446       continue;
447     }
448 
449     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
450     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
451 
452     int prot = PFLAGS_TO_PROT(phdr->p_flags);
453     if ((extra_prot_flags & PROT_WRITE) != 0) {
454       // make sure we're never simultaneously writable / executable
455       prot &= ~PROT_EXEC;
456     }
457 
458     int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
459                        seg_page_end - seg_page_start,
460                        prot | extra_prot_flags);
461     if (ret < 0) {
462       return -1;
463     }
464   }
465   return 0;
466 }
467 
468 /* Restore the original protection modes for all loadable segments.
469  * You should only call this after phdr_table_unprotect_segments and
470  * applying all relocations.
471  *
472  * Input:
473  *   phdr_table  -> program header table
474  *   phdr_count  -> number of entries in tables
475  *   load_bias   -> load bias
476  * Return:
477  *   0 on error, -1 on failure (error code in errno).
478  */
phdr_table_protect_segments(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias)479 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
480                                 size_t phdr_count, ElfW(Addr) load_bias) {
481   return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
482 }
483 
484 /* Change the protection of all loaded segments in memory to writable.
485  * This is useful before performing relocations. Once completed, you
486  * will have to call phdr_table_protect_segments to restore the original
487  * protection flags on all segments.
488  *
489  * Note that some writable segments can also have their content turned
490  * to read-only by calling phdr_table_protect_gnu_relro. This is no
491  * performed here.
492  *
493  * Input:
494  *   phdr_table  -> program header table
495  *   phdr_count  -> number of entries in tables
496  *   load_bias   -> load bias
497  * Return:
498  *   0 on error, -1 on failure (error code in errno).
499  */
phdr_table_unprotect_segments(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias)500 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table,
501                                   size_t phdr_count, ElfW(Addr) load_bias) {
502   return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE);
503 }
504 
505 /* Used internally by phdr_table_protect_gnu_relro and
506  * phdr_table_unprotect_gnu_relro.
507  */
_phdr_table_set_gnu_relro_prot(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias,int prot_flags)508 static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count,
509                                           ElfW(Addr) load_bias, int prot_flags) {
510   const ElfW(Phdr)* phdr = phdr_table;
511   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
512 
513   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
514     if (phdr->p_type != PT_GNU_RELRO) {
515       continue;
516     }
517 
518     // Tricky: what happens when the relro segment does not start
519     // or end at page boundaries? We're going to be over-protective
520     // here and put every page touched by the segment as read-only.
521 
522     // This seems to match Ian Lance Taylor's description of the
523     // feature at http://www.airs.com/blog/archives/189.
524 
525     //    Extract:
526     //       Note that the current dynamic linker code will only work
527     //       correctly if the PT_GNU_RELRO segment starts on a page
528     //       boundary. This is because the dynamic linker rounds the
529     //       p_vaddr field down to the previous page boundary. If
530     //       there is anything on the page which should not be read-only,
531     //       the program is likely to fail at runtime. So in effect the
532     //       linker must only emit a PT_GNU_RELRO segment if it ensures
533     //       that it starts on a page boundary.
534     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
535     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
536 
537     int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
538                        seg_page_end - seg_page_start,
539                        prot_flags);
540     if (ret < 0) {
541       return -1;
542     }
543   }
544   return 0;
545 }
546 
547 /* Apply GNU relro protection if specified by the program header. This will
548  * turn some of the pages of a writable PT_LOAD segment to read-only, as
549  * specified by one or more PT_GNU_RELRO segments. This must be always
550  * performed after relocations.
551  *
552  * The areas typically covered are .got and .data.rel.ro, these are
553  * read-only from the program's POV, but contain absolute addresses
554  * that need to be relocated before use.
555  *
556  * Input:
557  *   phdr_table  -> program header table
558  *   phdr_count  -> number of entries in tables
559  *   load_bias   -> load bias
560  * Return:
561  *   0 on error, -1 on failure (error code in errno).
562  */
phdr_table_protect_gnu_relro(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias)563 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table,
564                                  size_t phdr_count, ElfW(Addr) load_bias) {
565   return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ);
566 }
567 
568 /* Serialize the GNU relro segments to the given file descriptor. This can be
569  * performed after relocations to allow another process to later share the
570  * relocated segment, if it was loaded at the same address.
571  *
572  * Input:
573  *   phdr_table  -> program header table
574  *   phdr_count  -> number of entries in tables
575  *   load_bias   -> load bias
576  *   fd          -> writable file descriptor to use
577  * Return:
578  *   0 on error, -1 on failure (error code in errno).
579  */
phdr_table_serialize_gnu_relro(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias,int fd)580 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table,
581                                    size_t phdr_count,
582                                    ElfW(Addr) load_bias,
583                                    int fd) {
584   const ElfW(Phdr)* phdr = phdr_table;
585   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
586   ssize_t file_offset = 0;
587 
588   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
589     if (phdr->p_type != PT_GNU_RELRO) {
590       continue;
591     }
592 
593     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
594     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
595     ssize_t size = seg_page_end - seg_page_start;
596 
597     ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void*>(seg_page_start), size));
598     if (written != size) {
599       return -1;
600     }
601     void* map = mmap(reinterpret_cast<void*>(seg_page_start), size, PROT_READ,
602                      MAP_PRIVATE|MAP_FIXED, fd, file_offset);
603     if (map == MAP_FAILED) {
604       return -1;
605     }
606     file_offset += size;
607   }
608   return 0;
609 }
610 
611 /* Where possible, replace the GNU relro segments with mappings of the given
612  * file descriptor. This can be performed after relocations to allow a file
613  * previously created by phdr_table_serialize_gnu_relro in another process to
614  * replace the dirty relocated pages, saving memory, if it was loaded at the
615  * same address. We have to compare the data before we map over it, since some
616  * parts of the relro segment may not be identical due to other libraries in
617  * the process being loaded at different addresses.
618  *
619  * Input:
620  *   phdr_table  -> program header table
621  *   phdr_count  -> number of entries in tables
622  *   load_bias   -> load bias
623  *   fd          -> readable file descriptor to use
624  * Return:
625  *   0 on error, -1 on failure (error code in errno).
626  */
phdr_table_map_gnu_relro(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias,int fd)627 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table,
628                              size_t phdr_count,
629                              ElfW(Addr) load_bias,
630                              int fd) {
631   // Map the file at a temporary location so we can compare its contents.
632   struct stat file_stat;
633   if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) {
634     return -1;
635   }
636   off_t file_size = file_stat.st_size;
637   void* temp_mapping = nullptr;
638   if (file_size > 0) {
639     temp_mapping = mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd, 0);
640     if (temp_mapping == MAP_FAILED) {
641       return -1;
642     }
643   }
644   size_t file_offset = 0;
645 
646   // Iterate over the relro segments and compare/remap the pages.
647   const ElfW(Phdr)* phdr = phdr_table;
648   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
649 
650   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
651     if (phdr->p_type != PT_GNU_RELRO) {
652       continue;
653     }
654 
655     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
656     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
657 
658     char* file_base = static_cast<char*>(temp_mapping) + file_offset;
659     char* mem_base = reinterpret_cast<char*>(seg_page_start);
660     size_t match_offset = 0;
661     size_t size = seg_page_end - seg_page_start;
662 
663     if (file_size - file_offset < size) {
664       // File is too short to compare to this segment. The contents are likely
665       // different as well (it's probably for a different library version) so
666       // just don't bother checking.
667       break;
668     }
669 
670     while (match_offset < size) {
671       // Skip over dissimilar pages.
672       while (match_offset < size &&
673              memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) {
674         match_offset += PAGE_SIZE;
675       }
676 
677       // Count similar pages.
678       size_t mismatch_offset = match_offset;
679       while (mismatch_offset < size &&
680              memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) {
681         mismatch_offset += PAGE_SIZE;
682       }
683 
684       // Map over similar pages.
685       if (mismatch_offset > match_offset) {
686         void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset,
687                          PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset);
688         if (map == MAP_FAILED) {
689           munmap(temp_mapping, file_size);
690           return -1;
691         }
692       }
693 
694       match_offset = mismatch_offset;
695     }
696 
697     // Add to the base file offset in case there are multiple relro segments.
698     file_offset += size;
699   }
700   munmap(temp_mapping, file_size);
701   return 0;
702 }
703 
704 
705 #if defined(__arm__)
706 
707 #  ifndef PT_ARM_EXIDX
708 #    define PT_ARM_EXIDX    0x70000001      /* .ARM.exidx segment */
709 #  endif
710 
711 /* Return the address and size of the .ARM.exidx section in memory,
712  * if present.
713  *
714  * Input:
715  *   phdr_table  -> program header table
716  *   phdr_count  -> number of entries in tables
717  *   load_bias   -> load bias
718  * Output:
719  *   arm_exidx       -> address of table in memory (null on failure).
720  *   arm_exidx_count -> number of items in table (0 on failure).
721  * Return:
722  *   0 on error, -1 on failure (_no_ error code in errno)
723  */
phdr_table_get_arm_exidx(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias,ElfW (Addr)** arm_exidx,size_t * arm_exidx_count)724 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count,
725                              ElfW(Addr) load_bias,
726                              ElfW(Addr)** arm_exidx, size_t* arm_exidx_count) {
727   const ElfW(Phdr)* phdr = phdr_table;
728   const ElfW(Phdr)* phdr_limit = phdr + phdr_count;
729 
730   for (phdr = phdr_table; phdr < phdr_limit; phdr++) {
731     if (phdr->p_type != PT_ARM_EXIDX) {
732       continue;
733     }
734 
735     *arm_exidx = reinterpret_cast<ElfW(Addr)*>(load_bias + phdr->p_vaddr);
736     *arm_exidx_count = phdr->p_memsz / 8;
737     return 0;
738   }
739   *arm_exidx = nullptr;
740   *arm_exidx_count = 0;
741   return -1;
742 }
743 #endif
744 
745 /* Return the address and size of the ELF file's .dynamic section in memory,
746  * or null if missing.
747  *
748  * Input:
749  *   phdr_table  -> program header table
750  *   phdr_count  -> number of entries in tables
751  *   load_bias   -> load bias
752  * Output:
753  *   dynamic       -> address of table in memory (null on failure).
754  *   dynamic_flags -> protection flags for section (unset on failure)
755  * Return:
756  *   void
757  */
phdr_table_get_dynamic_section(const ElfW (Phdr)* phdr_table,size_t phdr_count,ElfW (Addr)load_bias,ElfW (Dyn)** dynamic,ElfW (Word)* dynamic_flags)758 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count,
759                                     ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
760                                     ElfW(Word)* dynamic_flags) {
761   *dynamic = nullptr;
762   for (size_t i = 0; i<phdr_count; ++i) {
763     const ElfW(Phdr)& phdr = phdr_table[i];
764     if (phdr.p_type == PT_DYNAMIC) {
765       *dynamic = reinterpret_cast<ElfW(Dyn)*>(load_bias + phdr.p_vaddr);
766       if (dynamic_flags) {
767         *dynamic_flags = phdr.p_flags;
768       }
769       return;
770     }
771   }
772 }
773 
774 // Sets loaded_phdr_ to the address of the program header table as it appears
775 // in the loaded segments in memory. This is in contrast with phdr_table_,
776 // which is temporary and will be released before the library is relocated.
FindPhdr()777 bool ElfReader::FindPhdr() {
778   const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
779 
780   // If there is a PT_PHDR, use it directly.
781   for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
782     if (phdr->p_type == PT_PHDR) {
783       return CheckPhdr(load_bias_ + phdr->p_vaddr);
784     }
785   }
786 
787   // Otherwise, check the first loadable segment. If its file offset
788   // is 0, it starts with the ELF header, and we can trivially find the
789   // loaded program header from it.
790   for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
791     if (phdr->p_type == PT_LOAD) {
792       if (phdr->p_offset == 0) {
793         ElfW(Addr)  elf_addr = load_bias_ + phdr->p_vaddr;
794         const ElfW(Ehdr)* ehdr = reinterpret_cast<const ElfW(Ehdr)*>(elf_addr);
795         ElfW(Addr)  offset = ehdr->e_phoff;
796         return CheckPhdr(reinterpret_cast<ElfW(Addr)>(ehdr) + offset);
797       }
798       break;
799     }
800   }
801 
802   DL_ERR("can't find loaded phdr for \"%s\"", name_);
803   return false;
804 }
805 
806 // Ensures that our program header is actually within a loadable
807 // segment. This should help catch badly-formed ELF files that
808 // would cause the linker to crash later when trying to access it.
CheckPhdr(ElfW (Addr)loaded)809 bool ElfReader::CheckPhdr(ElfW(Addr) loaded) {
810   const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_;
811   ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr)));
812   for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) {
813     if (phdr->p_type != PT_LOAD) {
814       continue;
815     }
816     ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_;
817     ElfW(Addr) seg_end = phdr->p_filesz + seg_start;
818     if (seg_start <= loaded && loaded_end <= seg_end) {
819       loaded_phdr_ = reinterpret_cast<const ElfW(Phdr)*>(loaded);
820       return true;
821     }
822   }
823   DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast<void*>(loaded));
824   return false;
825 }
826