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
This commit is contained in:
topjohnwu 2021-11-10 02:58:20 -08:00
parent ddd153c00d
commit 528601d25a
2 changed files with 15 additions and 2 deletions

View File

@ -554,7 +554,7 @@ void repack(const char *src_img, const char *out_img, bool skip_comp) {
if (boot.flags[ZIMAGE_KERNEL] && if (boot.flags[ZIMAGE_KERNEL] &&
boot.k_fmt == GZIP && hdr->kernel_size() > boot.hdr->kernel_size()) { boot.k_fmt == GZIP && hdr->kernel_size() > boot.hdr->kernel_size()) {
// Revert and try zipfoli // 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); 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 (boot.flags[ZIMAGE_KERNEL]) {
if (hdr->kernel_size() > boot.hdr->kernel_size()) { if (hdr->kernel_size() > boot.hdr->kernel_size()) {
LOGW("Recompressed kernel is too large, using original kernel\n"); 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()); hdr->kernel_size() = xwrite(fd, boot.z_info.tail - boot.hdr->kernel_size(), boot.hdr->kernel_size());
} else { } else {
write_zero(fd, boot.hdr->kernel_size() - hdr->kernel_size() - 4); write_zero(fd, boot.hdr->kernel_size() - hdr->kernel_size() - 4);

View File

@ -129,6 +129,19 @@ int faccessat(int dirfd, const char *pathname, int mode, int flags) {
return syscall(__NR_faccessat, dirfd, pathname, mode, 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__) #if !defined(__LP64__)
void android_set_abort_message(const char *msg) {} void android_set_abort_message(const char *msg) {}
#endif #endif