Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751362AbdFAHn6 (ORCPT ); Thu, 1 Jun 2017 03:43:58 -0400 Received: from m12-13.163.com ([220.181.12.13]:58571 "EHLO m12-13.163.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750848AbdFAHn5 (ORCPT ); Thu, 1 Jun 2017 03:43:57 -0400 From: Jia-Ju Bai To: monis@mellanox.com, sean.hefty@intel.com, dledford@redhat.com, hal.rosenstock@gmail.com, leon@kernel.org Cc: linux-rdma@vger.kernel.org, linux-kernel@vger.kernel.org, Jia-Ju Bai Subject: [PATCH V2] rxe: Fix a sleep-in-atomic bug in post_one_send Date: Thu, 1 Jun 2017 15:45:41 +0800 Message-Id: <1496303141-14925-1-git-send-email-baijiaju1990@163.com> X-Mailer: git-send-email 1.7.9.5 X-CM-TRANSID: DcCowABH7FWdxS9ZzMIpHQ--.27140S2 X-Coremail-Antispam: 1Uf129KBjvJXoW7ZFy8Zw4UtF17Aw1UWF4xtFb_yoW8Zw48pa 1rX3ZIkr43XFW7Za1qyr4qvrWfJ3sIv34UKF9Fq3s5ZF1DKryaqFs3K3WavFW0gFWxGF4I qr1UtrZ8Ca15CaDanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UGNtsUUUUU= X-Originating-IP: [166.111.70.19] X-CM-SenderInfo: xedlyx5dmximizq6il2tof0z/1tbiHgHpelSIVWWAlQAAs1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2045 Lines: 59 The driver may sleep under a spin lock, and the function call path is: post_one_send (acquire the lock by spin_lock_irqsave) init_send_wqe copy_from_user --> may sleep To fix it, the lock is released before copy_from_user, and the lock is acquired again after this function. The parameter "flags" is used to restore and save the irq status. Thank Leon for good advice. Signed-off-by: Jia-Ju Bai --- drivers/infiniband/sw/rxe/rxe_verbs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index 83d709e..7dcdf67 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -721,11 +721,11 @@ static void init_send_wr(struct rxe_qp *qp, struct rxe_send_wr *wr, static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr, unsigned int mask, unsigned int length, - struct rxe_send_wqe *wqe) + struct rxe_send_wqe *wqe, unsigned long *flags) { int num_sge = ibwr->num_sge; struct ib_sge *sge; - int i; + int i, err; u8 *p; init_send_wr(qp, &wqe->wr, ibwr); @@ -742,7 +742,12 @@ static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr, for (i = 0; i < num_sge; i++, sge++) { if (qp->is_user && copy_from_user(p, (__user void *) (uintptr_t)sge->addr, sge->length)) - return -EFAULT; + spin_unlock_irqrestore(&qp->sq.sq_lock, *flags); + err = copy_from_user(p, (__user void *) + (uintptr_t)sge->addr, sge->length); + spin_lock_irqsave(&qp->sq.sq_lock, *flags); + if (qp->is_user && err) + return -EFAULT; else if (!qp->is_user) memcpy(p, (void *)(uintptr_t)sge->addr, @@ -794,7 +799,7 @@ static int post_one_send(struct rxe_qp *qp, struct ib_send_wr *ibwr, send_wqe = producer_addr(sq->queue); - err = init_send_wqe(qp, ibwr, mask, length, send_wqe); + err = init_send_wqe(qp, ibwr, mask, length, send_wqe, &flags); if (unlikely(err)) goto err1; -- 1.7.9.5