Merge "Block align start and length while punching holes" into main
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
index 01920de..31f4e64 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.cpp
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -21,6 +21,7 @@
 #include <android-base/file.h>
 #include <android-base/hex.h>
 #include <android-base/unique_fd.h>
+#include <bionic/macros.h>
 #include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -35,10 +36,45 @@
 #include <fstream>
 #include <vector>
 
+using android::base::borrowed_fd;
 using android::base::HexString;
 using android::base::ReadFullyAtOffset;
 
 namespace android {
+
+bool punchWithBlockAlignment(borrowed_fd fd, uint64_t start, uint64_t length, uint64_t blockSize) {
+    uint64_t end;
+    if (__builtin_add_overflow(start, length, &end)) {
+        ALOGE("Overflow occurred when calculating end");
+        return false;
+    }
+
+    start = align_up(start, blockSize);
+    end = align_down(end, blockSize);
+
+    uint64_t alignedLength;
+    if (__builtin_sub_overflow(end, start, &alignedLength)) {
+        ALOGE("Overflow occurred when calculating length");
+        return false;
+    }
+
+    if (alignedLength < blockSize) {
+        ALOGW("Skipping punching hole as aligned length is less than block size");
+        return false;
+    }
+
+    ALOGD("Punching hole in file - start: %" PRIu64 " len:%" PRIu64 "", start, alignedLength);
+
+    int result =
+            fallocate(fd.get(), FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, start, alignedLength);
+    if (result < 0) {
+        ALOGE("fallocate failed to punch hole, error:%d", errno);
+        return false;
+    }
+
+    return true;
+}
+
 bool punchHoles(const char *filePath, const uint64_t offset,
                 const std::vector<Elf64_Phdr> &programHeaders) {
     struct stat64 beforePunch;
@@ -96,6 +132,8 @@
             continue;
         }
 
+        // if we have a uncompressed file which is being opened from APK, use the offset to
+        // punch native lib inside Apk.
         uint64_t punchStartOffset;
         if (__builtin_add_overflow(offset, punchOffset, &punchStartOffset)) {
             ALOGE("Overflow occurred when calculating length");
@@ -144,12 +182,7 @@
             position = uncheckedChunkEnd;
         }
 
-        // if we have a uncompressed file which is being opened from APK, use the offset to
-        // punch native lib inside Apk.
-        int result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, punchStartOffset,
-                               punchLen);
-        if (result < 0) {
-            ALOGE("fallocate failed to punch hole, error:%d", errno);
+        if (!punchWithBlockAlignment(fd, punchStartOffset, punchLen, blockSize)) {
             return false;
         }
     }
@@ -298,13 +331,7 @@
                 return false;
             }
 
-            ALOGD("Punching hole in apk start: %" PRIu64 " len:%" PRIu64 "", punchOffset, punchLen);
-
-            // Punch hole for this entire stretch.
-            int result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, punchOffset,
-                                   punchLen);
-            if (result < 0) {
-                ALOGE("fallocate failed to punch hole inside apk, error:%d", errno);
+            if (!punchWithBlockAlignment(fd, punchOffset, punchLen, blockSize)) {
                 return false;
             }
         }