RDMA/rxe: Fix error unwind in rxe_create_qp()
authorZhu Yanjun <yanjun.zhu@linux.dev>
Sun, 31 Jul 2022 06:36:21 +0000 (02:36 -0400)
committerJason Gunthorpe <jgg@nvidia.com>
Tue, 2 Aug 2022 17:29:41 +0000 (14:29 -0300)
In the function rxe_create_qp(), rxe_qp_from_init() is called to
initialize qp, internally things like the spin locks are not setup until
rxe_qp_init_req().

If an error occures before this point then the unwind will call
rxe_cleanup() and eventually to rxe_qp_do_cleanup()/rxe_cleanup_task()
which will oops when trying to access the uninitialized spinlock.

Move the spinlock initializations earlier before any failures.

Fixes: 8700e3e7c485 ("Soft RoCE driver")
Link: https://lore.kernel.org/r/20220731063621.298405-1-yanjun.zhu@linux.dev
Reported-by: syzbot+833061116fa28df97f3b@syzkaller.appspotmail.com
Signed-off-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/sw/rxe/rxe_qp.c

index c6519b9..516bf9b 100644 (file)
@@ -172,6 +172,14 @@ static void rxe_qp_init_misc(struct rxe_dev *rxe, struct rxe_qp *qp,
 
        spin_lock_init(&qp->state_lock);
 
+       spin_lock_init(&qp->req.task.state_lock);
+       spin_lock_init(&qp->resp.task.state_lock);
+       spin_lock_init(&qp->comp.task.state_lock);
+
+       spin_lock_init(&qp->sq.sq_lock);
+       spin_lock_init(&qp->rq.producer_lock);
+       spin_lock_init(&qp->rq.consumer_lock);
+
        atomic_set(&qp->ssn, 0);
        atomic_set(&qp->skb_out, 0);
 }
@@ -232,7 +240,6 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp,
        qp->req.opcode          = -1;
        qp->comp.opcode         = -1;
 
-       spin_lock_init(&qp->sq.sq_lock);
        skb_queue_head_init(&qp->req_pkts);
 
        rxe_init_task(rxe, &qp->req.task, qp,
@@ -283,9 +290,6 @@ static int rxe_qp_init_resp(struct rxe_dev *rxe, struct rxe_qp *qp,
                }
        }
 
-       spin_lock_init(&qp->rq.producer_lock);
-       spin_lock_init(&qp->rq.consumer_lock);
-
        skb_queue_head_init(&qp->resp_pkts);
 
        rxe_init_task(rxe, &qp->resp.task, qp,