// https://syzkaller.appspot.com/bug?id=01d2f6a29a32efac53ccbf018d754ba5b46cf137 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #define BPF_CALL_FUNC(_imm) \ ((struct bpf_insn){ .code = 0x85, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = _imm }) #define BPF_EXIT_INSN() \ ((struct bpf_insn){ .code = 0x95, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = 0 }) #define BPF_MOV64_IMM(_dst, _imm) \ ((struct bpf_insn){ .code = 0xb7, .dst_reg = _dst, .src_reg = 0, .off = 0, .imm = _imm }) struct bpf_insn { uint8_t code; uint8_t dst_reg:4; uint8_t src_reg:4; int16_t off; int32_t imm; }; union bpf_attr { struct { uint32_t prog_type; uint32_t insn_cnt; uint64_t insns; uint64_t license; uint32_t log_level; uint32_t log_size; uint64_t log_buf; uint32_t kern_version; uint32_t prog_flags; char prog_name[16]; uint32_t prog_ifindex; uint32_t expected_attach_type; uint32_t prog_btf_fd; uint32_t func_info_rec_size; uint64_t func_info; uint32_t func_info_cnt; uint32_t line_info_rec_size; uint64_t line_info; uint32_t line_info_cnt; uint32_t attach_btf_id; uint32_t attach_prog_fd; }; struct { uint32_t prog_fd; uint32_t retval; uint32_t data_size_in; uint32_t data_size_out; uint64_t data_in; uint64_t data_out; uint32_t repeat; uint32_t duration; uint32_t ctx_size_in; uint32_t ctx_size_out; uint64_t ctx_in; uint64_t ctx_out; uint32_t flags; uint32_t cpu; uint32_t batch_size; } test; char padding[144]; }; int bpf_fd = -1; void pin_to_other_cpu() { cpu_set_t set; CPU_ZERO(&set); if (sched_getaffinity(0, sizeof(set), &set) == 0) { if (CPU_COUNT(&set) > 1) { CPU_CLR(0, &set); sched_setaffinity(0, sizeof(set), &set); } } } void *bpf_thread(void *arg) { pin_to_other_cpu(); char data[14] = {0}; union bpf_attr test_attr; memset(&test_attr, 0, sizeof(test_attr)); test_attr.test.prog_fd = bpf_fd; test_attr.test.data_size_in = sizeof(data); test_attr.test.data_in = (uint64_t)data; test_attr.test.repeat = 1000000; while (1) { syscall(__NR_bpf, 10, &test_attr, sizeof(test_attr)); // BPF_PROG_TEST_RUN } return NULL; } void *trace_marker_thread(void *arg) { pin_to_other_cpu(); int fd_marker = open("/sys/kernel/tracing/trace_marker", O_WRONLY); if (fd_marker < 0) fd_marker = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY); if (fd_marker >= 0) { while (1) { if (write(fd_marker, "a", 1) < 0) { // ignore } } } return NULL; } int main() { struct bpf_insn insns[1024]; int i = 0; /* Call bpf_ktime_get_ns() 1000 times */ for (; i < 1000; i++) { insns[i] = BPF_CALL_FUNC(5); // 5 is BPF_FUNC_ktime_get_ns } insns[i++] = BPF_MOV64_IMM(0, 0); insns[i++] = BPF_EXIT_INSN(); union bpf_attr attr; memset(&attr, 0, sizeof(attr)); attr.prog_type = 1; // BPF_PROG_TYPE_SOCKET_FILTER attr.insn_cnt = i; attr.insns = (uint64_t)insns; attr.license = (uint64_t)"GPL"; bpf_fd = syscall(__NR_bpf, 5, &attr, sizeof(attr)); // BPF_PROG_LOAD pthread_t th[8]; if (bpf_fd < 0) { printf("[-] Failed to load BPF program: %s\n", strerror(errno)); /* Fallback: use ftrace trace_marker with mono clock */ int fd_clock = open("/sys/kernel/tracing/trace_clock", O_WRONLY); if (fd_clock < 0) fd_clock = open("/sys/kernel/debug/tracing/trace_clock", O_WRONLY); if (fd_clock >= 0) { if (write(fd_clock, "mono\n", 5) < 0) { printf("[-] Failed to write to trace_clock: %s\n", strerror(errno)); } close(fd_clock); } for (int j = 0; j < 8; j++) { pthread_create(&th[j], NULL, trace_marker_thread, NULL); } } else { printf("[+] BPF program loaded successfully.\n"); /* Primary: use BPF_PROG_TEST_RUN */ for (int j = 0; j < 8; j++) { pthread_create(&th[j], NULL, bpf_thread, NULL); } } /* Do not exit to avoid exit-related KCSAN reports */ while (1) { sleep(1); } return 0; }