diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_linux.h | 55 | ||||
| -rw-r--r-- | executor/executor.cc | 2 | ||||
| -rw-r--r-- | executor/executor_linux.h | 8 |
3 files changed, 32 insertions, 33 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h index 66d3d561e..74ffa0847 100644 --- a/executor/common_linux.h +++ b/executor/common_linux.h @@ -1230,16 +1230,14 @@ struct fs_image_segment { #elif GOARCH_ppc64le #define sys_memfd_create 360 #endif -#endif -#if SYZ_EXECUTOR || __NR_syz_read_part_table -// syz_read_part_table(size intptr, nsegs len[segments], segments ptr[in, array[fs_image_segment]]) -static long syz_read_part_table(volatile unsigned long size, volatile unsigned long nsegs, volatile long segments) +static unsigned long fs_image_segment_check(unsigned long size, unsigned long nsegs, long segments) { - char loopname[64], linkname[64]; - int loopfd, err = 0, res = -1; - unsigned long i, j; - // See the comment in syz_mount_image. + unsigned long i; + // Strictly saying we ought to do a nonfailing copyout of segments into a local var. + // But some filesystems have large number of segments (2000+), + // we can't allocate that much on stack and allocating elsewhere is problematic, + // so we just use the memory allocated by fuzzer. struct fs_image_segment* segs = (struct fs_image_segment*)segments; if (nsegs > IMAGE_MAX_SEGMENTS) @@ -1255,6 +1253,18 @@ static long syz_read_part_table(volatile unsigned long size, volatile unsigned l } if (size > IMAGE_MAX_SIZE) size = IMAGE_MAX_SIZE; + return size; +} +#endif + +#if SYZ_EXECUTOR || __NR_syz_read_part_table +// syz_read_part_table(size intptr, nsegs len[segments], segments ptr[in, array[fs_image_segment]]) +static long syz_read_part_table(volatile unsigned long size, volatile unsigned long nsegs, volatile long segments) +{ + char loopname[64], linkname[64]; + int loopfd, err = 0, res = -1; + unsigned long i, j; + NONFAILING(size = fs_image_segment_check(size, nsegs, segments)); int memfd = syscall(sys_memfd_create, "syz_read_part_table", 0); if (memfd == -1) { err = errno; @@ -1265,9 +1275,8 @@ static long syz_read_part_table(volatile unsigned long size, volatile unsigned l goto error_close_memfd; } for (i = 0; i < nsegs; i++) { - if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) { - debug("syz_read_part_table: pwrite[%u] failed: %d\n", (int)i, errno); - } + struct fs_image_segment* segs = (struct fs_image_segment*)segments; + NONFAILING(pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset)); } snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid); loopfd = open(loopname, O_RDWR); @@ -1339,25 +1348,8 @@ static long syz_mount_image(volatile long fsarg, volatile long dir, volatile uns char loopname[64], fs[32], opts[256]; int loopfd, err = 0, res = -1; unsigned long i; - // Strictly saying we ought to do a nonfailing copyout of segments into a local var. - // But some filesystems have large number of segments (2000+), - // we can't allocate that much on stack and allocating elsewhere is problematic, - // so we just use the memory allocated by fuzzer. - struct fs_image_segment* segs = (struct fs_image_segment*)segments; - if (nsegs > IMAGE_MAX_SEGMENTS) - nsegs = IMAGE_MAX_SEGMENTS; - for (i = 0; i < nsegs; i++) { - if (segs[i].size > IMAGE_MAX_SIZE) - segs[i].size = IMAGE_MAX_SIZE; - segs[i].offset %= IMAGE_MAX_SIZE; - if (segs[i].offset > IMAGE_MAX_SIZE - segs[i].size) - segs[i].offset = IMAGE_MAX_SIZE - segs[i].size; - if (size < segs[i].offset + segs[i].offset) - size = segs[i].offset + segs[i].offset; - } - if (size > IMAGE_MAX_SIZE) - size = IMAGE_MAX_SIZE; + NONFAILING(size = fs_image_segment_check(size, nsegs, segments)); int memfd = syscall(sys_memfd_create, "syz_mount_image", 0); if (memfd == -1) { err = errno; @@ -1368,9 +1360,8 @@ static long syz_mount_image(volatile long fsarg, volatile long dir, volatile uns goto error_close_memfd; } for (i = 0; i < nsegs; i++) { - if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) { - debug("syz_mount_image: pwrite[%u] failed: %d\n", (int)i, errno); - } + struct fs_image_segment* segs = (struct fs_image_segment*)segments; + NONFAILING(pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset)); } snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid); loopfd = open(loopname, O_RDWR); diff --git a/executor/executor.cc b/executor/executor.cc index c8a4b8b2e..c0e332190 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -709,6 +709,8 @@ retry: call_extra_timeout = 300; if (strncmp(syscalls[call_num].name, "syz_open_dev$hiddev", strlen("syz_open_dev$hiddev")) == 0) call_extra_timeout = 50; + if (strncmp(syscalls[call_num].name, "syz_mount_image", strlen("syz_mount_image")) == 0) + call_extra_timeout = 50; uint64 copyout_index = read_input(&input_pos); uint64 num_args = read_input(&input_pos); if (num_args > kMaxArgs) diff --git a/executor/executor_linux.h b/executor/executor_linux.h index 13d6a598e..73005877d 100644 --- a/executor/executor_linux.h +++ b/executor/executor_linux.h @@ -139,8 +139,14 @@ static void cover_enable(cover_t* cov, bool collect_comps, bool extra) static void cover_reset(cover_t* cov) { - if (cov == 0) + // Callers in common_linux.h don't check this flag. + if (!flag_coverage) + return; + if (cov == 0) { + if (current_cover == 0) + fail("cover_reset: current_cover == 0"); cov = current_cover; + } *(uint64*)cov->data = 0; } |
