aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2024-01-12 16:13:16 +0100
committerAleksandr Nogikh <nogikh@google.com>2024-01-12 15:40:35 +0000
commit551587c192ecb4df26fcdab775ed145ee69c07d4 (patch)
treec3371daf91899391c00066fc7d8f652acf601879 /executor
parentf6fa7c2845ca01940da7571219da2203c579068d (diff)
executor: don't hold a loop device fd
When BLK_DEV_WRITE_MOUNTED is enabled, the kernel treats the loopfd reference as a writer and does not let us issue mount() calls over the same block device.
Diffstat (limited to 'executor')
-rw-r--r--executor/common_linux.h31
1 files changed, 26 insertions, 5 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 9558bdb7d..98339194f 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -2967,6 +2967,7 @@ static int setup_loop_device(unsigned char* data, unsigned long size, const char
loopfd = open(loopname, O_RDWR);
if (loopfd == -1) {
err = errno;
+ debug("setup_loop_device: open failed: %d\n", errno);
goto error_close_memfd;
}
if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
@@ -2994,6 +2995,24 @@ error:
errno = err;
return -1;
}
+
+#if SYZ_EXECUTOR || __NR_syz_mount_image
+
+static void reset_loop_device(const char* loopname)
+{
+ int loopfd = open(loopname, O_RDWR);
+ if (loopfd == -1) {
+ debug("reset_loop_device: open failed: %d\n", errno);
+ return;
+ }
+ if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
+ debug("reset_loop_device: LOOP_CLR_FD failed: %d\n", errno);
+ }
+ close(loopfd);
+}
+
+#endif
+
#endif
#if SYZ_EXECUTOR || __NR_syz_read_part_table
@@ -3067,7 +3086,7 @@ static long syz_mount_image(
volatile long image)
{
unsigned char* data = (unsigned char*)image;
- int res = -1, err = 0, loopfd = -1, need_loop_device = !!size;
+ int res = -1, err = 0, need_loop_device = !!size;
char* mount_opts = (char*)optsarg;
char* target = (char*)dir;
char* fs = (char*)fsarg;
@@ -3075,12 +3094,16 @@ static long syz_mount_image(
char loopname[64];
if (need_loop_device) {
+ int loopfd;
// Some filesystems (e.g. FUSE) do not need a backing device or
// filesystem image.
memset(loopname, 0, sizeof(loopname));
snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
if (setup_loop_device(data, size, loopname, &loopfd) == -1)
return -1;
+ // If BLK_DEV_WRITE_MOUNTED is set, we won't be able to mount()
+ // while holding the loop device fd.
+ close(loopfd);
source = loopname;
}
@@ -3137,10 +3160,8 @@ static long syz_mount_image(
}
error_clear_loop:
- if (need_loop_device) {
- ioctl(loopfd, LOOP_CLR_FD, 0);
- close(loopfd);
- }
+ if (need_loop_device)
+ reset_loop_device(loopname);
errno = err;
return res;
}