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>
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 821f30d..074012d 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 @@
       }
     }
 
-    // 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 the segment is writable, and does not end on a page boundary,
+    // zero-fill it until the page limit.
     //
-    // 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.
-    //
-    // 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);