// https://syzkaller.appspot.com/bug?id=2a3c5f6dc8ee7d04e8531e92b2bcef857aba69d3 // autogenerated by syzkaller (http://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include extern unsigned long long procid; struct fs_image_segment { void* data; uintptr_t size; uintptr_t offset; }; #define IMAGE_MAX_SEGMENTS 4096 #define IMAGE_MAX_SIZE (129 << 20) #define SYZ_memfd_create 319 static uintptr_t syz_mount_image(uintptr_t fsarg, uintptr_t dir, uintptr_t size, uintptr_t nsegs, uintptr_t segments, uintptr_t flags, uintptr_t optsarg) { char loopname[64], fs[32], opts[256]; int loopfd, err = 0, res = -1; uintptr_t i; 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; int memfd = syscall(SYZ_memfd_create, "syz_mount_image", 0); if (memfd == -1) { err = errno; goto error; } if (ftruncate(memfd, size)) { err = errno; goto error_close_memfd; } for (i = 0; i < nsegs; i++) { if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) { } } snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid); loopfd = open(loopname, O_RDWR); if (loopfd == -1) { err = errno; goto error_close_memfd; } if (ioctl(loopfd, LOOP_SET_FD, memfd)) { if (errno != EBUSY) { err = errno; goto error_close_loop; } ioctl(loopfd, LOOP_CLR_FD, 0); usleep(1000); if (ioctl(loopfd, LOOP_SET_FD, memfd)) { err = errno; goto error_close_loop; } } mkdir((char*)dir, 0777); memset(fs, 0, sizeof(fs)); strncpy(fs, (char*)fsarg, sizeof(fs) - 1); memset(opts, 0, sizeof(opts)); strncpy(opts, (char*)optsarg, sizeof(opts) - 32); if (strcmp(fs, "iso9660") == 0) { flags |= MS_RDONLY; } else if (strncmp(fs, "ext", 3) == 0) { if (strstr(opts, "errors=panic") || strstr(opts, "errors=remount-ro") == 0) strcat(opts, ",errors=continue"); } else if (strcmp(fs, "xfs") == 0) { strcat(opts, ",nouuid"); } if (mount(loopname, (char*)dir, fs, flags, opts)) { err = errno; goto error_clear_loop; } res = 0; error_clear_loop: ioctl(loopfd, LOOP_CLR_FD, 0); error_close_loop: close(loopfd); error_close_memfd: close(memfd); error: errno = err; return res; } static void execute_one(); extern unsigned long long procid; void loop() { while (1) { execute_one(); } } uint64_t r[1] = {0xffffffffffffffff}; unsigned long long procid; void execute_one() { long res = 0; memcpy((void*)0x20000080, "btrfs", 6); memcpy((void*)0x200000c0, "./file0", 8); *(uint64_t*)0x20000400 = 0x20000500; memcpy((void*)0x20000500, "\x8d\xa4\x36\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4d\x01" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xec\xf6" "\xf2\xa2\x29\x97\x48\xae\xb8\x1e\x1b\x00\x92\x0e\xfd\x9a\x00\x00\x01" "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x5f\x42\x48\x52" "\x66\x53\x5f\x4d\xd2\xf8\x73\x57\x4f\x25\x7e\x0a\x01\xe2\xa6\xa0\x2f" "\x5e\x07\x13\x83\xfa\x5a\x66\x9a\x53\xf2\xfe\x9e\xb4\xeb\x79\x18\x62" "\x8a\xf4\x1b\x03\x5f\xd9\x83\x72\xe7\xc2\xa6\x97\x0f\x55\x04\x41\xf0" "\xb2\x63\xdc\xa4\x6c\x12\xce\x6a\xaa\x99\x4f\xbb\x4b\x34\x93\xca\x90" "\x18\x78\xbb\x33\x0d\x2d\xb8\xe9\x53\xfc\x88\x3f\x9c\x75\x4f\x41\x9e" "\x96\x38\x74\x19\x92\x95\xa9\x45\xec\x86\x7b\x4f\x22\x4f\xde\x52\x26" "\x8a\x81\xe1\x15\x4b\x80\xf7\x07\x6f\x32\xb6\xeb\x86\x14\xc6\x72\xec" "\xde\xcd\x38\x5a\x1a\x7b\x8c\xac\x7c\xca\x0e\xb0\xcd\xbf\x1c\x5e\xe5" "\x39\xc3\x7d\x1f", 208); *(uint64_t*)0x20000408 = 0xd0; *(uint64_t*)0x20000410 = 0x10000; syz_mount_image(0x20000080, 0x200000c0, 0, 1, 0x20000400, 0, 0x200003c0); syscall(__NR_write, -1, 0x20000780, 0); memcpy((void*)0x20000040, "/dev/null", 10); res = syscall(__NR_openat, 0xffffffffffffff9c, 0x20000040, 0, 0); if (res != -1) r[0] = res; *(uint64_t*)0x20000340 = 4; syscall(__NR_ioctl, r[0], 0x4b45, 0x20000340); } int main() { syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0); for (procid = 0; procid < 8; procid++) { if (fork() == 0) { for (;;) { loop(); } } } sleep(1000000); return 0; }