Commit 528601d2 authored by topjohnwu's avatar topjohnwu

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
parent ddd153c0
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment