]> www.infradead.org Git - users/jedix/linux-maple.git/commit
ib/sdp: fix null dereference of sk->sk_wq in sdp_rx_irq()
authorChuck Anderson <chuck.anderson@oracle.com>
Thu, 8 Jan 2015 00:06:49 +0000 (17:06 -0700)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 6 Oct 2015 12:46:01 +0000 (05:46 -0700)
commit6aa28cad6cb7c6b639cf4f62d4d8f3e7c5de8d88
tree973e62fc344f78deb4bdc31fb16c04d319190f20
parent3bc44760391e34b22df736a725176cc3bb280ada
ib/sdp: fix null dereference of sk->sk_wq in sdp_rx_irq()

Orabug: 20070989

BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
IP: [<ffffffffa02b639f>] sdp_rx_irq+0x4f/0x160 [ib_sdp]
PGD 1d7fd14067 PUD 190984b067 PMD 0
Oops: 0000 [#1] SMP
...
Pid: 61889, comm: oracle Not tainted 2.6.39-400.128.20.el5uek #1 Oracle
Corporation SUN FIRE X4170 M3     /ASSY,MOTHERBOARD,1U
RIP: 0010:[<ffffffffa02b639f>]  [<ffffffffa02b639f>] sdp_rx_irq+0x4f/0x160
[ib_sdp]
...

Crash occurs in the call to sdp_sk_sleep(sk) through waitqueue_active():

drivers/infiniband/ulp/sdp/sdp_rx.c
static void sdp_rx_irq(struct ib_cq *cq, void *cq_context)
        if (should_wake_up(sk)) {

drivers/infiniband/ulp/sdp/sdp_rx.c
static inline int should_wake_up(struct sock *sk)
{
        return sdp_sk_sleep(sk) && waitqueue_active(sdp_sk_sleep(sk)) &&
                (posts_handler(sdp_sk(sk)) || somebody_is_waiting(sk));
}

drivers/infiniband/ulp/sdp/sdp.h:
        #define sdp_sk_sleep(sk) sk_sleep(sk)

include/net/sock.h
static inline wait_queue_head_t *sk_sleep(struct sock *sk)
{
        BUILD_BUG_ON(offsetof(struct socket_wq, wait) != 0);
        return &rcu_dereference_raw(sk->sk_wq)->wait;
}

We know the first call to sdp_sk_sleep(sk) finds a non-null sk->sk_wq
because we don't crash:

0xffffffffa02b6388 <sdp_rx_irq+56>:     mov    0xb8(%rsi),%rax
0xffffffffa02b638f <sdp_rx_irq+63>:     test   %rax,%rax
*** struct sock sk+0xb8 == sk->sk_wq (sk_wq is at offset 0xb8)
*** we didn't crash at sdp_rx_irq+56 so sk->sk_wq was apparently valid
0xffffffffa02b6394 <sdp_rx_irq+68>:     mov    0xb8(%rsi),%rdx
0xffffffffa02b639b <sdp_rx_irq+75>:     lea    0x8(%rdx),%rax
0xffffffffa02b639f <sdp_rx_irq+79>:     cmp    %rax,0x8(%rdx)
*** RDX is NULL causing the null dereference of address 0x8 at sdp_rx_irq+79.

Fix is to check if sk->sk_wq is NULL before dereferencing it to get the
address of sk->sk_wq->wait.  Also, do the RCU dereference of sk->sk_wq
once, not twice as we may get a different answer (NULL) the second time.

Signed-off-by: Chuck Anderson <chuck.anderson@oracle.com>
Signed-off-by: John Sobecki <john.sobecki@oracle.com>
Acked-by: Chien Yen <chien.yen@oracle.com>
Signed-off-by: Guangyu Sun <guangyu.sun@oracle.com>
drivers/infiniband/ulp/sdp/sdp_rx.c