diff options
author | Kalesh Singh <kaleshsingh@google.com> | 2024-03-06 17:33:36 -0800 |
---|---|---|
committer | Kalesh Singh <kaleshsingh@google.com> | 2024-03-13 13:40:28 -0700 |
commit | 1d3ba112ab1b7b1d837f3be7efc032d14822d1aa (patch) | |
tree | d9b385292d400f9d154a2c6f60cb81eb8d4698d8 | |
parent | 702d9b0bad7eac3d1d59e8e433f5a6a0345ea5f8 (diff) | |
download | bionic-1d3ba112ab1b7b1d837f3be7efc032d14822d1aa.tar.gz |
bionic: loader: Only zero the last partial page in RW segments
Only zero the partial page at the end of the segment. There may be
entire pages beyond first page boundary after the segment -- due to
segment padding (VMA extension); but these are not expected to be
touched (faulted).
Do not attempt to zero the extended region past the first partial page,
since doing so may:
1) Result in a SIGBUS, as the region is not backed by the underlying
file.
2) Break the COW backing, faulting in new anon pages for a region
that will not be used.
Bug: 327600007
Bug: 328797737
Test: Dexcom G7 app
Test: atest -c linker-unit-tests
Test: bootup/idle/system-processes-memory-direct
Change-Id: Ib76b022f94bfc4a4b7eaca2c155af81478741b91
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
-rw-r--r-- | linker/Android.bp | 1 | ||||
-rw-r--r-- | linker/linker_phdr.cpp | 29 |
2 files changed, 11 insertions, 19 deletions
diff --git a/linker/Android.bp b/linker/Android.bp index 55daf2202..f87a92e56 100644 --- a/linker/Android.bp +++ b/linker/Android.bp @@ -116,7 +116,6 @@ cc_defaults { "libziparchive", "libbase", "libz", - "libprocinfo", // For procinfo::MappedFileSize() "libasync_safe", diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp index 821f30dff..074012d3b 100644 --- a/linker/linker_phdr.cpp +++ b/linker/linker_phdr.cpp @@ -46,8 +46,6 @@ #include "private/CFIShadow.h" // For kLibraryAlignment #include "private/elf_note.h" -#include <procinfo/process_map.h> - static int GetTargetElfMachine() { #if defined(__arm__) return EM_ARM; @@ -869,25 +867,20 @@ bool ElfReader::LoadSegments() { } } - // if the segment is writable, and its memory map extends beyond - // the segment contents on file (p_filesz); zero-fill it until the - // end of the mapping backed by the file, rounded to the next - // page boundary; as this portion of the mapping corresponds to either - // garbage (partial page at the end) or data from other segments. - // - // If any part of the mapping extends beyond the file size there is - // no need to zero it since that region is not touchable by userspace - // and attempting to do so will causes the kernel to throw a SIGBUS. + // if the segment is writable, and does not end on a page boundary, + // zero-fill it until the page limit. // - // See: system/libprocinfo/include/procinfo/process_map_size.h - uint64_t file_backed_size = ::android::procinfo::MappedFileSize(seg_page_start, - page_end(seg_page_start + file_length), - file_offset_ + file_page_start, file_size_); + // Do not attempt to zero the extended region past the first partial page, + // since doing so may: + // 1) Result in a SIGBUS, as the region is not backed by the underlying + // file. + // 2) Break the COW backing, faulting in new anon pages for a region + // that will not be used. + // _seg_file_end = unextended seg_file_end uint64_t _seg_file_end = seg_start + phdr->p_filesz; - uint64_t zero_fill_len = file_backed_size - (_seg_file_end - seg_page_start); - if ((phdr->p_flags & PF_W) != 0 && zero_fill_len > 0) { - memset(reinterpret_cast<void*>(_seg_file_end), 0, zero_fill_len); + if ((phdr->p_flags & PF_W) != 0 && page_offset(_seg_file_end) > 0) { + memset(reinterpret_cast<void*>(_seg_file_end), 0, kPageSize - page_offset(_seg_file_end)); } seg_file_end = page_end(seg_file_end); |