Merge "exit(): add a lock." into main
diff --git a/libm/NOTICE b/libm/NOTICE
index a88c351..bcdce54 100644
--- a/libm/NOTICE
+++ b/libm/NOTICE
@@ -244,34 +244,6 @@
-------------------------------------------------------------------
-Copyright (C) 2021 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
-OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
-OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
-
--------------------------------------------------------------------
-
Copyright (C) 2022 The Android Open Source Project
All rights reserved.
@@ -540,36 +512,6 @@
-------------------------------------------------------------------
-Copyright (c) 2014, Intel Corporation
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
-
- * Neither the name of Intel Corporation nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
--------------------------------------------------------------------
-
Copyright (c) 2017 Steven G. Kargl
All rights reserved.
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index b9229ca..a629ee6 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -221,17 +221,24 @@
}
bool ElfReader::ReadElfHeader() {
- ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_));
- if (rc < 0) {
- DL_ERR("can't read file \"%s\": %s", name_.c_str(), strerror(errno));
+ size_t map_size = file_size_ - file_offset_;
+ if (map_size < sizeof(header_)) {
+ DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
+ map_size);
return false;
}
- if (rc != sizeof(header_)) {
- DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_.c_str(),
- static_cast<size_t>(rc));
+#if !defined(__LP64__)
+ // Map at most 1MiB which should cover most cases
+ map_size = std::min(map_size, static_cast<size_t>(1 * 1024 * 1024));
+#endif
+
+ if (!file_fragment_.Map(fd_, file_offset_, 0, map_size)) {
+ DL_ERR("\"%s\" header mmap failed: %s", name_.c_str(), strerror(errno));
return false;
}
+
+ header_ = *static_cast<ElfW(Ehdr)*>(file_fragment_.data());
return true;
}
@@ -340,6 +347,24 @@
((offset % alignment) == 0);
}
+void* ElfReader::MapData(MappedFileFragment* fragment, off64_t offs, off64_t size) {
+ off64_t end;
+ CHECK(safe_add(&end, offs, size));
+
+ // If the data is already mapped just return it
+ if (static_cast<off64_t>(file_fragment_.size()) >= end) {
+ return static_cast<char*>(file_fragment_.data()) + offs;
+ }
+ // Use the passed-in fragment if area is not mapped. We can't remap the original fragment
+ // because that invalidates all previous pointers if the file is remapped to a different
+ // virtual address. A local variable can't be used in place of the passed-in fragment because
+ // the area would be unmapped as soon as the local object goes out of scope.
+ if (fragment->Map(fd_, file_offset_, offs, size)) {
+ return fragment->data();
+ }
+ return nullptr;
+}
+
// Loads the program header table from an ELF file into a read-only private
// anonymous mmap-ed block.
bool ElfReader::ReadProgramHeaders() {
@@ -362,12 +387,13 @@
return false;
}
- if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
+ void* phdr_data = MapData(&phdr_fragment_, header_.e_phoff, size);
+ if (phdr_data == nullptr) {
DL_ERR("\"%s\" phdr mmap failed: %s", name_.c_str(), strerror(errno));
return false;
}
- phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_fragment_.data());
+ phdr_table_ = static_cast<ElfW(Phdr)*>(phdr_data);
return true;
}
@@ -388,12 +414,13 @@
return false;
}
- if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
+ void* shdr_data = MapData(&shdr_fragment_, header_.e_shoff, size);
+ if (shdr_data == nullptr) {
DL_ERR("\"%s\" shdr mmap failed: %s", name_.c_str(), strerror(errno));
return false;
}
- shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_fragment_.data());
+ shdr_table_ = static_cast<const ElfW(Shdr)*>(shdr_data);
return true;
}
@@ -481,12 +508,13 @@
return false;
}
- if (!dynamic_fragment_.Map(fd_, file_offset_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
+ void* dynamic_data = MapData(&dynamic_fragment_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size);
+ if (dynamic_data == nullptr) {
DL_ERR("\"%s\" dynamic section mmap failed: %s", name_.c_str(), strerror(errno));
return false;
}
- dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_fragment_.data());
+ dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_data);
if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size, alignof(const char))) {
DL_ERR_AND_LOG("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
@@ -494,13 +522,14 @@
return false;
}
- if (!strtab_fragment_.Map(fd_, file_offset_, strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
+ void* strtab_data = MapData(&strtab_fragment_, strtab_shdr->sh_offset, strtab_shdr->sh_size);
+ if (strtab_data == nullptr) {
DL_ERR("\"%s\" strtab section mmap failed: %s", name_.c_str(), strerror(errno));
return false;
}
- strtab_ = static_cast<const char*>(strtab_fragment_.data());
- strtab_size_ = strtab_fragment_.size();
+ strtab_ = static_cast<const char*>(strtab_data);
+ strtab_size_ = strtab_shdr->sh_size;
return true;
}
@@ -756,7 +785,8 @@
// note_fragment is scoped to within the loop so that there is
// at most 1 PT_NOTE mapped at anytime during this search.
MappedFileFragment note_fragment;
- if (!note_fragment.Map(fd_, file_offset_, phdr->p_offset, phdr->p_memsz)) {
+ void* note_data = MapData(¬e_fragment, phdr->p_offset, phdr->p_memsz);
+ if (note_data == nullptr) {
DL_ERR("\"%s\": PT_NOTE mmap(nullptr, %p, PROT_READ, MAP_PRIVATE, %d, %p) failed: %m",
name_.c_str(), reinterpret_cast<void*>(phdr->p_memsz), fd_,
reinterpret_cast<void*>(page_start(file_offset_ + phdr->p_offset)));
@@ -766,7 +796,7 @@
const ElfW(Nhdr)* note_hdr = nullptr;
const char* note_desc = nullptr;
if (!__get_elf_note(NT_ANDROID_TYPE_PAD_SEGMENT, "Android",
- reinterpret_cast<ElfW(Addr)>(note_fragment.data()),
+ reinterpret_cast<ElfW(Addr)>(note_data),
phdr, ¬e_hdr, ¬e_desc)) {
continue;
}
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index aab9018..dc1ca99 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -73,6 +73,7 @@
[[nodiscard]] bool FindGnuPropertySection();
[[nodiscard]] bool CheckPhdr(ElfW(Addr));
[[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
+ [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offs, off64_t size);
bool did_read_;
bool did_load_;
@@ -81,6 +82,8 @@
off64_t file_offset_;
off64_t file_size_;
+ MappedFileFragment file_fragment_;
+
ElfW(Ehdr) header_;
size_t phdr_num_;