aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2022-11-22 17:08:47 +0100
committerDmitry Vyukov <dvyukov@google.com>2022-11-23 09:09:39 +0100
commit24857b29bc28753137e73565e8f9c26e67bf0770 (patch)
tree8de7ced0fec1570a2e81e6cf13e9be8363e9563a /executor
parent0313f19c6536a190992aff148a0960c7fea6e47f (diff)
executor: don't pass uncompressed zlib size
This will allow us to mutate the image size. Fixes #3527
Diffstat (limited to 'executor')
-rw-r--r--executor/common_linux.h27
-rw-r--r--executor/common_test.h10
-rw-r--r--executor/common_zlib.h20
3 files changed, 26 insertions, 31 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 40d2ad894..8ca854c9e 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -2897,7 +2897,7 @@ static long syz_genetlink_get_family_id(volatile long name, volatile long sock_a
// creating and initializing the underlying file backing the loop device and
// returns the fds to the file and device.
// Returns 0 on success, -1 otherwise.
-static int setup_loop_device(long unsigned size, long unsigned compressed_size, unsigned char* data, const char* loopname, int* memfd_p, int* loopfd_p)
+static int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* memfd_p, int* loopfd_p)
{
int err = 0, loopfd = -1;
int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
@@ -2905,12 +2905,7 @@ static int setup_loop_device(long unsigned size, long unsigned compressed_size,
err = errno;
goto error;
}
- if (ftruncate(memfd, size)) {
- err = errno;
- goto error_close_memfd;
- }
-
- if (puff_zlib_to_file(data, compressed_size, memfd, size)) {
+ if (puff_zlib_to_file(data, size, memfd)) {
err = errno;
debug("setup_loop_device: could not decompress data: %d\n", errno);
goto error_close_memfd;
@@ -2949,15 +2944,15 @@ error:
#endif
#if SYZ_EXECUTOR || __NR_syz_read_part_table
-// syz_read_part_table(size intptr, size_compressed len[img], img ptr[in, compressed_image])
-static long syz_read_part_table(volatile unsigned long size, volatile unsigned long compressed_size, volatile long image)
+// syz_read_part_table(size len[img], img ptr[in, compressed_image])
+static long syz_read_part_table(volatile unsigned long size, volatile long image)
{
unsigned char* data = (unsigned char*)image;
int err = 0, res = -1, loopfd = -1, memfd = -1;
char loopname[64];
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
- if (setup_loop_device(size, compressed_size, data, loopname, &memfd, &loopfd) == -1)
+ if (setup_loop_device(data, size, loopname, &memfd, &loopfd) == -1)
return -1;
struct loop_info64 info;
@@ -3003,25 +2998,23 @@ error_clear_loop:
// syz_mount_image(
// fs ptr[in, string[fs]],
// dir ptr[in, filename],
-// size intptr,
-// size_compressed len[img],
// flags flags[mount_flags],
// opts ptr[in, fs_options],
// chdir bool8,
+// size len[img],
// img ptr[in, compressed_image]
// ) fd_dir
static long syz_mount_image(
volatile long fsarg,
volatile long dir,
- volatile unsigned long size,
- volatile unsigned long compressed_size,
volatile long flags,
volatile long optsarg,
volatile long change_dir,
+ volatile unsigned long size,
volatile long image)
{
unsigned char* data = (unsigned char*)image;
- int res = -1, err = 0, loopfd = -1, memfd = -1, need_loop_device = !!compressed_size;
+ int res = -1, err = 0, loopfd = -1, memfd = -1, need_loop_device = !!size;
char* mount_opts = (char*)optsarg;
char* target = (char*)dir;
char* fs = (char*)fsarg;
@@ -3033,7 +3026,7 @@ static long syz_mount_image(
// filesystem image.
memset(loopname, 0, sizeof(loopname));
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
- if (setup_loop_device(size, compressed_size, data, loopname, &memfd, &loopfd) == -1)
+ if (setup_loop_device(data, size, loopname, &memfd, &loopfd) == -1)
return -1;
source = loopname;
}
@@ -3058,7 +3051,7 @@ static long syz_mount_image(
// and if two parallel executors mounts fs with the same uuid, second mount fails.
strcat(opts, ",nouuid");
}
- debug("syz_mount_image: size=%llu compressed_size=%llu loop='%s' dir='%s' fs='%s' flags=%llu opts='%s'\n", (uint64)size, (uint64)compressed_size, loopname, target, fs, (uint64)flags, opts);
+ debug("syz_mount_image: size=%llu loop='%s' dir='%s' fs='%s' flags=%llu opts='%s'\n", (uint64)size, loopname, target, fs, (uint64)flags, opts);
#if SYZ_EXECUTOR
cover_reset(0);
#endif
diff --git a/executor/common_test.h b/executor/common_test.h
index 2ce410b36..6ef6ed82d 100644
--- a/executor/common_test.h
+++ b/executor/common_test.h
@@ -105,6 +105,7 @@ static long syz_compare_int(volatile long n, ...)
#include "common_zlib.h"
#include <errno.h>
#include <fcntl.h>
+#include <sys/stat.h>
// syz_compare_zlib(data ptr[in, array[int8]], size bytesize[data], zdata ptr[in, compressed_image], zsize bytesize[zdata])
static long syz_compare_zlib(volatile long data, volatile long size, volatile long zdata, volatile long zsize)
@@ -112,14 +113,15 @@ static long syz_compare_zlib(volatile long data, volatile long size, volatile lo
int fd = open("./uncompressed", O_RDWR | O_CREAT | O_EXCL, 0666);
if (fd == -1)
return -1;
- if (ftruncate(fd, size))
+ if (puff_zlib_to_file((unsigned char*)zdata, zsize, fd))
return -1;
- if (puff_zlib_to_file((unsigned char*)zdata, zsize, fd, size))
+ struct stat statbuf;
+ if (fstat(fd, &statbuf))
return -1;
- void* uncompressed = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ void* uncompressed = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (uncompressed == MAP_FAILED)
return -1;
- return syz_compare(data, size, (long)uncompressed, size);
+ return syz_compare(data, size, (long)uncompressed, statbuf.st_size);
}
#endif
diff --git a/executor/common_zlib.h b/executor/common_zlib.h
index e7e47e0fd..d3545ade2 100644
--- a/executor/common_zlib.h
+++ b/executor/common_zlib.h
@@ -493,11 +493,7 @@ static int puff(
#include <sys/mman.h>
#define ZLIB_HEADER_WIDTH 2 // Two-byte zlib header width.
-static int puff_zlib_to_file(
- const unsigned char* source,
- unsigned long sourcelen,
- int dest_fd,
- unsigned long destlen)
+static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
{
// Ignore zlib header.
if (sourcelen < ZLIB_HEADER_WIDTH) {
@@ -507,20 +503,24 @@ static int puff_zlib_to_file(
source += ZLIB_HEADER_WIDTH;
sourcelen -= ZLIB_HEADER_WIDTH;
- // Memory-map destination file dest_fd.
- void* ret = mmap(0, destlen, PROT_WRITE | PROT_READ, MAP_SHARED, dest_fd, 0);
+ const unsigned long max_destlen = 132 << 20;
+ void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
if (ret == MAP_FAILED)
return -1;
unsigned char* dest = (unsigned char*)ret;
// Inflate source array to destination file.
- unsigned long destlen_copy = destlen; // copy destlen as puff() may modify it
- int err = puff(dest, &destlen_copy, source, &sourcelen);
+ unsigned long destlen = max_destlen; // copy destlen as puff() may modify it
+ int err = puff(dest, &destlen, source, &sourcelen);
if (err) {
+ munmap(dest, max_destlen);
errno = -err;
return -1;
}
-
+ if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
+ munmap(dest, max_destlen);
+ return -1;
+ }
// Unmap memory-mapped region
return munmap(dest, destlen);
}