diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2019-12-10 16:04:18 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2019-12-10 16:08:35 +0100 |
| commit | cb704a294c54aed90281c016a6dc0c40ae295601 (patch) | |
| tree | 4aac076186076a786c43b9bdf584c980747d0617 /executor/common_linux.h | |
| parent | 5a5826a14e99564bdd4de163d3ac368056e5d992 (diff) | |
executor: fix syz_mount_image
1. It always crashed in cover_reset when coverage is disabled.
2. Use NONFAILING when accessing image segments.
3. Give it additional 100 ms as it may be slow.
4. Add a test for syz_mount_image.
Diffstat (limited to 'executor/common_linux.h')
| -rw-r--r-- | executor/common_linux.h | 55 |
1 files changed, 23 insertions, 32 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); |
