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 #pragma once 30 31 /* Declarations related to the ELF program header table and segments. 32 * 33 * The design goal is to provide an API that is as close as possible 34 * to the ELF spec, and does not depend on linker-specific data 35 * structures (e.g. the exact layout of struct soinfo). 36 */ 37 38 #include "linker.h" 39 #include "linker_mapped_file_fragment.h" 40 #include "linker_note_gnu_property.h" 41 42 #include <list> 43 44 #define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0) 45 #define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ 46 MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ 47 MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) 48 49 static constexpr size_t kCompatPageSize = 0x1000; 50 51 class ElfReader { 52 public: 53 ElfReader(); 54 55 [[nodiscard]] bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size); 56 [[nodiscard]] bool Load(address_space_params* address_space); 57 name()58 const char* name() const { return name_.c_str(); } phdr_count()59 size_t phdr_count() const { return phdr_num_; } load_start()60 ElfW(Addr) load_start() const { return reinterpret_cast<ElfW(Addr)>(load_start_); } load_size()61 size_t load_size() const { return load_size_; } gap_start()62 ElfW(Addr) gap_start() const { return reinterpret_cast<ElfW(Addr)>(gap_start_); } gap_size()63 size_t gap_size() const { return gap_size_; } load_bias()64 ElfW(Addr) load_bias() const { return load_bias_; } ElfW(Phdr)65 const ElfW(Phdr)* loaded_phdr() const { return loaded_phdr_; } ElfW(Dyn)66 const ElfW(Dyn)* dynamic() const { return dynamic_; } 67 const char* get_string(ElfW(Word) index) const; is_mapped_by_caller()68 bool is_mapped_by_caller() const { return mapped_by_caller_; } entry_point()69 ElfW(Addr) entry_point() const { return header_.e_entry + load_bias_; } should_pad_segments()70 bool should_pad_segments() const { return should_pad_segments_; } should_use_16kib_app_compat()71 bool should_use_16kib_app_compat() const { return should_use_16kib_app_compat_; } compat_relro_start()72 ElfW(Addr) compat_relro_start() const { return compat_relro_start_; } compat_relro_size()73 ElfW(Addr) compat_relro_size() const { return compat_relro_size_; } 74 75 private: 76 [[nodiscard]] bool ReadElfHeader(); 77 [[nodiscard]] bool VerifyElfHeader(); 78 [[nodiscard]] bool ReadProgramHeaders(); 79 [[nodiscard]] bool ReadSectionHeaders(); 80 [[nodiscard]] bool ReadDynamicSection(); 81 [[nodiscard]] bool ReadPadSegmentNote(); 82 [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space); 83 [[nodiscard]] bool MapSegment(size_t seg_idx, size_t len); 84 [[nodiscard]] bool CompatMapSegment(size_t seg_idx, size_t len); 85 void ZeroFillSegment(const ElfW(Phdr)* phdr); 86 void DropPaddingPages(const ElfW(Phdr)* phdr, uint64_t seg_file_end); 87 [[nodiscard]] bool MapBssSection(const ElfW(Phdr)* phdr, ElfW(Addr) seg_page_end, 88 ElfW(Addr) seg_file_end); 89 [[nodiscard]] bool IsEligibleFor16KiBAppCompat(ElfW(Addr)* vaddr); 90 [[nodiscard]] bool HasAtMostOneRelroSegment(const ElfW(Phdr)** relro_phdr); 91 [[nodiscard]] bool Setup16KiBAppCompat(); 92 [[nodiscard]] bool LoadSegments(); 93 [[nodiscard]] bool FindPhdr(); 94 [[nodiscard]] bool FindGnuPropertySection(); 95 [[nodiscard]] bool CheckPhdr(ElfW(Addr)); 96 [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment); 97 98 bool did_read_; 99 bool did_load_; 100 std::string name_; 101 int fd_; 102 off64_t file_offset_; 103 off64_t file_size_; 104 105 ElfW(Ehdr) header_; 106 size_t phdr_num_; 107 108 MappedFileFragment phdr_fragment_; 109 const ElfW(Phdr)* phdr_table_; 110 111 MappedFileFragment shdr_fragment_; 112 const ElfW(Shdr)* shdr_table_; 113 size_t shdr_num_; 114 115 MappedFileFragment dynamic_fragment_; 116 const ElfW(Dyn)* dynamic_; 117 118 MappedFileFragment strtab_fragment_; 119 const char* strtab_; 120 size_t strtab_size_; 121 122 // First page of reserved address space. 123 void* load_start_; 124 // Size in bytes of reserved address space. 125 size_t load_size_; 126 // First page of inaccessible gap mapping reserved for this DSO. 127 void* gap_start_; 128 // Size in bytes of the gap mapping. 129 size_t gap_size_; 130 // Load bias. 131 ElfW(Addr) load_bias_; 132 133 // Loaded phdr. 134 const ElfW(Phdr)* loaded_phdr_; 135 136 // Is map owned by the caller 137 bool mapped_by_caller_; 138 139 // Pad gaps between segments when memory mapping? 140 bool should_pad_segments_ = false; 141 142 // Use app compat mode when loading 4KiB max-page-size ELFs on 16KiB page-size devices? 143 bool should_use_16kib_app_compat_ = false; 144 145 // RELRO region for 16KiB compat loading 146 ElfW(Addr) compat_relro_start_ = 0; 147 ElfW(Addr) compat_relro_size_ = 0; 148 149 // Only used by AArch64 at the moment. 150 GnuPropertySection note_gnu_property_ __unused; 151 }; 152 153 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, 154 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr); 155 156 size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count); 157 size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count); 158 159 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 160 ElfW(Addr) load_bias, bool should_pad_segments, 161 bool should_use_16kib_app_compat, 162 const GnuPropertySection* prop = nullptr); 163 164 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 165 ElfW(Addr) load_bias, bool should_pad_segments, 166 bool should_use_16kib_app_compat); 167 168 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 169 ElfW(Addr) load_bias, bool should_pad_segments, 170 bool should_use_16kib_app_compat); 171 172 int phdr_table_protect_gnu_relro_16kib_compat(ElfW(Addr) start, ElfW(Addr) size); 173 174 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 175 ElfW(Addr) load_bias, int fd, size_t* file_offset); 176 177 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 178 ElfW(Addr) load_bias, int fd, size_t* file_offset); 179 180 #if defined(__arm__) 181 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias, 182 ElfW(Addr)** arm_exidx, size_t* arm_exidix_count); 183 #endif 184 185 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, 186 ElfW(Addr) load_bias, ElfW(Dyn)** dynamic, 187 ElfW(Word)* dynamic_flags); 188 189 const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count, 190 ElfW(Addr) load_bias); 191 192 bool page_size_migration_supported(); 193 194 int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count, 195 ElfW(Addr) load_bias); 196 197 void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count, 198 ElfW(Addr) load_bias); 199 200 void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count, 201 ElfW(Addr) load_bias, const char* soname, 202 std::list<std::string>* vma_names); 203