From 528601d25abae7a6b5e44084ef8d8907ffe72cae Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 10 Nov 2021 02:58:20 -0800 Subject: [PATCH] Fix integer overflow and workaround seccomp - Use ftruncate64 instead of ftruncate to workaround seccomp - Cast uint32_t to off64_t before making it negative Note: Using ftruncate with a modern NDK libc should actually be fine as the syscall wrapper in bionic will use ftruncate64 internally. However, since we are using the libc.a from r10e built for Gingerbread, seccomp wasn't a thing back then, and also the ftruncate64 symbol is missing; we have to create our own wrapper and call it instead on 32-bit ABIs. Props to @jnotuo for discovering the overflow bug and seccomp issue Fix #3703, close #4915 --- native/jni/magiskboot/bootimg.cpp | 4 ++-- native/jni/utils/missing.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index 6d3022201..bd925ef0d 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -554,7 +554,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) { if (boot.flags[ZIMAGE_KERNEL] && boot.k_fmt == GZIP && hdr->kernel_size() > boot.hdr->kernel_size()) { // Revert and try zipfoli - ftruncate(fd, lseek(fd, -hdr->kernel_size(), SEEK_CUR)); + ftruncate64(fd, lseek64(fd, -(off64_t)hdr->kernel_size(), SEEK_CUR)); hdr->kernel_size() = compress(ZOPFLI, fd, raw_buf, raw_size); } @@ -563,7 +563,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) { if (boot.flags[ZIMAGE_KERNEL]) { if (hdr->kernel_size() > boot.hdr->kernel_size()) { LOGW("Recompressed kernel is too large, using original kernel\n"); - ftruncate(fd, lseek(fd, -hdr->kernel_size(), SEEK_CUR)); + ftruncate64(fd, lseek64(fd, -(off64_t)hdr->kernel_size(), SEEK_CUR)); hdr->kernel_size() = xwrite(fd, boot.z_info.tail - boot.hdr->kernel_size(), boot.hdr->kernel_size()); } else { write_zero(fd, boot.hdr->kernel_size() - hdr->kernel_size() - 4); diff --git a/native/jni/utils/missing.cpp b/native/jni/utils/missing.cpp index 87ce2a333..41f3d1e8f 100644 --- a/native/jni/utils/missing.cpp +++ b/native/jni/utils/missing.cpp @@ -129,6 +129,19 @@ int faccessat(int dirfd, const char *pathname, int mode, int flags) { return syscall(__NR_faccessat, dirfd, pathname, mode, flags); } +#define SPLIT_64(v) (unsigned)((v) & 0xFFFFFFFF), (unsigned)((v) >> 32) + +#if defined(__arm__) +// Why the additional 0 is required: https://man7.org/linux/man-pages/man2/syscall.2.html +int ftruncate64(int fd, off64_t length) { + return syscall(__NR_ftruncate64, fd, 0, SPLIT_64(length)); +} +#elif defined(__i386__) +int ftruncate64(int fd, off64_t length) { + return syscall(__NR_ftruncate64, fd, SPLIT_64(length)); +} +#endif + #if !defined(__LP64__) void android_set_abort_message(const char *msg) {} #endif