// https://syzkaller.appspot.com/bug?id=45de5441f2f211f482eba41c46d860b16c5a0f35 // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef __NR_memfd_create #define __NR_memfd_create 319 #endif static unsigned long long procid; struct fs_image_segment { void* data; uintptr_t size; uintptr_t offset; }; static int setup_loop_device(long unsigned size, long unsigned nsegs, struct fs_image_segment* segs, const char* loopname, int* memfd_p, int* loopfd_p) { int err = 0, loopfd = -1; int memfd = syscall(__NR_memfd_create, "syzkaller", 0); if (memfd == -1) { err = errno; goto error; } if (ftruncate(memfd, size)) { err = errno; goto error_close_memfd; } for (size_t i = 0; i < nsegs; i++) { if (pwrite(memfd, segs[i].data, segs[i].size, segs[i].offset) < 0) { } } 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; } } *memfd_p = memfd; *loopfd_p = loopfd; return 0; error_close_loop: close(loopfd); error_close_memfd: close(memfd); error: errno = err; return -1; } static long syz_mount_image(volatile long fsarg, volatile long dir, volatile unsigned long size, volatile unsigned long nsegs, volatile long segments, volatile long flags, volatile long optsarg, volatile long change_dir) { struct fs_image_segment* segs = (struct fs_image_segment*)segments; int res = -1, err = 0, loopfd = -1, memfd = -1, need_loop_device = !!segs; char* mount_opts = (char*)optsarg; char* target = (char*)dir; char* fs = (char*)fsarg; char* source = NULL; char loopname[64]; if (need_loop_device) { memset(loopname, 0, sizeof(loopname)); snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid); if (setup_loop_device(size, nsegs, segs, loopname, &memfd, &loopfd) == -1) return -1; source = loopname; } mkdir(target, 0777); char opts[256]; memset(opts, 0, sizeof(opts)); if (strlen(mount_opts) > (sizeof(opts) - 32)) { } strncpy(opts, mount_opts, 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"); } res = mount(source, target, fs, flags, opts); if (res == -1) { err = errno; goto error_clear_loop; } res = open(target, O_RDONLY | O_DIRECTORY); if (res == -1) { err = errno; goto error_clear_loop; } if (change_dir) { res = chdir(target); if (res == -1) { err = errno; } } error_clear_loop: if (need_loop_device) { ioctl(loopfd, LOOP_CLR_FD, 0); close(loopfd); close(memfd); } errno = err; return res; } uint64_t r[1] = {0xffffffffffffffff}; int main(void) { syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); intptr_t res = 0; memcpy((void*)0x20000140, "erofs\000", 6); memcpy((void*)0x20000100, "./file0\000", 8); *(uint64_t*)0x20000180 = 0x200000c0; memcpy((void*)0x200000c0, "\xe2\xe1\xf5\xe0\x95\x21\xe9\x3c\x02\x00\x00\x00\x0c\x00\x24", 15); *(uint64_t*)0x20000188 = 0xf; *(uint64_t*)0x20000190 = 0x400; *(uint64_t*)0x20000198 = 0x20000200; memcpy((void*)0x20000200, "\x03\x00\x45\x31\x95\x44\x1e\x5a\x35\x5a", 10); *(uint64_t*)0x200001a0 = 0xa; *(uint64_t*)0x200001a8 = 0x480; *(uint64_t*)0x200001b0 = 0x20000040; memcpy((void*)0x20000040, "\xce\x37\x0d\x67\x73\x43\x27\x2d\x1c\x00\xb9\xf2\xf3\x04\x91\xb1\x6d" "\x13\xf8\x79\x7c\x5c\xc0\xc2\xff\xb5\x42\x87\xa7\x56\xd5\xcd\x99\x94" "\x2e\x8b\x32\x23\x6d", 39); *(uint64_t*)0x200001b8 = 0x27; *(uint64_t*)0x200001c0 = 0x1000; *(uint64_t*)0x200001c8 = 0x200004c0; memcpy( (void*)0x200004c0, "\xa8\x30\x3f\xe7\x90\x1a\xd2\x04\x51\xc7\xd5\x51\xec\x7a\x37\x3f\xcb\x1b" "\x06\x7a\x57\x27\x45\x62\x3d\x82\x00\xd6\x02\x92\x89\x0b\xd9\x69\xa6\xf0" "\x29\x57\x83\x51\x4e\x5e\xfc\x8d\xaa\x95\xbd\x91\x23\x0f\xdf\xaa\xd4\x02" "\x48\x10\x64\x62\x5f\x1f\xf8\x10\x8a\x09\x35\xaa\x40\x34\x12\x5d\xaa\xd0" "\xf9\x85\x72\xd5\x98\xe2\x24\x04\x63\xad\x34\x02\xe3\x57\x7b\xdd\xa3\xb1" "\xc3\x67\x5c\x0d\x5f\x29\xbe\x00\x66\xa2\xbc\x1f\x37\x26\x51\xa5\x9a\x93" "\x88\xee\xcf\x98\x8d\xbb\x74\xd1\xe1\xa3\xfd\xd7\x31\x04\x47\x10\xa0\x4a" "\xb4\x85\x43\x7e\x91\x29\x69\x43\x27\x75\xdc\xf0\x80\xc2\xd2\x2e\x6d\xe1" "\x5e\xfd\x55\x9b\xba\xbd\xd2\xaf\xb1\xf7\x57\xf1\x12\x6f\x36\xfe\xbf\x66" "\x10\xa9\x8c\xee\x16\x0c\xdf\x48\x9b\x1c\xa2\xec\xb4\xf2\x23\x73\x17\xdf" "\x80\xf3\x59\x19\x13\xa2\x78\x4a\x3a\x35\x8c\x21\x69\xe4\x23\x32\xb1\x75" "\x59\xd2\x4e\x00\xfe\xd4\x04\xbd\x25\x54\x79\xaf\xdd\xf6\x92\x10\x7d\x87" "\x2f\x4b\x03\xb1\xc1\x0a\x57\xe6\x95\xc6\x08\x13\x72\xcc\x0e\xf8\xcb\xbe" "\xd9\xb9\x31\x64\x65\xa5\x1d\xc7\x3c\x61\x3f\xec\xa7\x82\xe8\x91\x33\x9f" "\x67\x2f\xa2\x36\xef\x3f\xb6\x79\xad\x47\xde\x4f\x72\x16\x9a\x70\xda\x81" "\x7c\x4c\x7b\x55\x8a\xe0\x34\xdd\x98\xba\x49\x21\x60\xd9\xd7\xfe\xf5", 287); *(uint64_t*)0x200001d0 = 0x11f; *(uint64_t*)0x200001d8 = 0xc95d; *(uint32_t*)0x20000240 = 0; res = -1; res = syz_mount_image(0x20000140, 0x20000100, 0x8100000, 4, 0x20000180, 0, 0x20000240, 0); if (res != -1) r[0] = res; memcpy((void*)0x20000080, "./file0\000", 8); syscall(__NR_mknodat, r[0], 0x20000080ul, 4ul, 0x700); return 0; }