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 CheckProgramHeaderAlignment(); 80 [[nodiscard]] bool ReadSectionHeaders(); 81 [[nodiscard]] bool ReadDynamicSection(); 82 [[nodiscard]] bool ReadPadSegmentNote(); 83 [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space); 84 [[nodiscard]] bool MapSegment(size_t seg_idx, size_t len); 85 [[nodiscard]] bool CompatMapSegment(size_t seg_idx, size_t len); 86 void ZeroFillSegment(const ElfW(Phdr)* phdr); 87 void DropPaddingPages(const ElfW(Phdr)* phdr, uint64_t seg_file_end); 88 [[nodiscard]] bool MapBssSection(const ElfW(Phdr)* phdr, ElfW(Addr) seg_page_end, 89 ElfW(Addr) seg_file_end); 90 [[nodiscard]] bool IsEligibleFor16KiBAppCompat(ElfW(Addr)* vaddr); 91 [[nodiscard]] bool HasAtMostOneRelroSegment(const ElfW(Phdr)** relro_phdr); 92 [[nodiscard]] bool Setup16KiBAppCompat(); 93 [[nodiscard]] bool LoadSegments(); 94 [[nodiscard]] bool FindPhdr(); 95 [[nodiscard]] bool FindGnuPropertySection(); 96 [[nodiscard]] bool CheckPhdr(ElfW(Addr)); 97 [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment); 98 99 bool did_read_; 100 bool did_load_; 101 std::string name_; 102 int fd_; 103 off64_t file_offset_; 104 off64_t file_size_; 105 106 ElfW(Ehdr) header_; 107 size_t phdr_num_; 108 109 MappedFileFragment phdr_fragment_; 110 const ElfW(Phdr)* phdr_table_; 111 112 MappedFileFragment shdr_fragment_; 113 const ElfW(Shdr)* shdr_table_; 114 size_t shdr_num_; 115 116 MappedFileFragment dynamic_fragment_; 117 const ElfW(Dyn)* dynamic_; 118 119 MappedFileFragment strtab_fragment_; 120 const char* strtab_; 121 size_t strtab_size_; 122 123 // First page of reserved address space. 124 void* load_start_; 125 // Size in bytes of reserved address space. 126 size_t load_size_; 127 // First page of inaccessible gap mapping reserved for this DSO. 128 void* gap_start_; 129 // Size in bytes of the gap mapping. 130 size_t gap_size_; 131 // Load bias. 132 ElfW(Addr) load_bias_; 133 134 // Maximum and minimum alignment requirements across all phdrs. 135 size_t max_align_; 136 size_t min_align_; 137 138 // Loaded phdr. 139 const ElfW(Phdr)* loaded_phdr_; 140 141 // Is map owned by the caller 142 bool mapped_by_caller_; 143 144 // Pad gaps between segments when memory mapping? 145 bool should_pad_segments_ = false; 146 147 // Use app compat mode when loading 4KiB max-page-size ELFs on 16KiB page-size devices? 148 bool should_use_16kib_app_compat_ = false; 149 150 // RELRO region for 16KiB compat loading 151 ElfW(Addr) compat_relro_start_ = 0; 152 ElfW(Addr) compat_relro_size_ = 0; 153 154 // Only used by AArch64 at the moment. 155 GnuPropertySection note_gnu_property_ __unused; 156 }; 157 158 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, 159 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr); 160 161 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 162 ElfW(Addr) load_bias, bool should_pad_segments, 163 bool should_use_16kib_app_compat, 164 const GnuPropertySection* prop = nullptr); 165 166 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 167 ElfW(Addr) load_bias, bool should_pad_segments, 168 bool should_use_16kib_app_compat); 169 170 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 171 ElfW(Addr) load_bias, bool should_pad_segments, 172 bool should_use_16kib_app_compat); 173 174 int phdr_table_protect_gnu_relro_16kib_compat(ElfW(Addr) start, ElfW(Addr) size); 175 176 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 177 ElfW(Addr) load_bias, int fd, size_t* file_offset); 178 179 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 180 ElfW(Addr) load_bias, int fd, size_t* file_offset); 181 182 #if defined(__arm__) 183 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias, 184 ElfW(Addr)** arm_exidx, size_t* arm_exidix_count); 185 #endif 186 187 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, 188 ElfW(Addr) load_bias, ElfW(Dyn)** dynamic, 189 ElfW(Word)* dynamic_flags); 190 191 const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count, 192 ElfW(Addr) load_bias); 193 194 bool page_size_migration_supported(); 195 196 int remap_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count, 197 ElfW(Addr) load_bias); 198 199 void protect_memtag_globals_ro_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count, 200 ElfW(Addr) load_bias); 201 202 void name_memtag_globals_segments(const ElfW(Phdr) * phdr_table, size_t phdr_count, 203 ElfW(Addr) load_bias, const char* soname, 204 std::list<std::string>* vma_names); 205