aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_linux.h
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-12-10 16:04:18 +0100
committerDmitry Vyukov <dvyukov@google.com>2019-12-10 16:08:35 +0100
commitcb704a294c54aed90281c016a6dc0c40ae295601 (patch)
tree4aac076186076a786c43b9bdf584c980747d0617 /executor/common_linux.h
parent5a5826a14e99564bdd4de163d3ac368056e5d992 (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.h55
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);