Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80783868 authored by Steve Wise's avatar Steve Wise Committed by Roland Dreier
Browse files

RDMA/cxgb3: Don't post zero-byte read if endpoint is going away



tx_ack() wasn't checking the endpoint state and consequently would
attempt to post the p2p 0B read on an endpoint/QP that is closing or
aborting.  This causes a NULL pointer dereference crash.

Signed-off-by: default avatarSteve Wise <swise@opengridcomputing.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 257313b2
Loading
Loading
Loading
Loading
+17 −9
Original line number Original line Diff line number Diff line
@@ -913,7 +913,7 @@ static void process_mpa_reply(struct iwch_ep *ep, struct sk_buff *skb)
		goto err;
		goto err;


	if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
	if (peer2peer && iwch_rqes_posted(ep->com.qp) == 0) {
		iwch_post_zb_read(ep->com.qp);
		iwch_post_zb_read(ep);
	}
	}


	goto out;
	goto out;
@@ -1077,6 +1077,8 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
	struct iwch_ep *ep = ctx;
	struct iwch_ep *ep = ctx;
	struct cpl_wr_ack *hdr = cplhdr(skb);
	struct cpl_wr_ack *hdr = cplhdr(skb);
	unsigned int credits = ntohs(hdr->credits);
	unsigned int credits = ntohs(hdr->credits);
	unsigned long flags;
	int post_zb = 0;


	PDBG("%s ep %p credits %u\n", __func__, ep, credits);
	PDBG("%s ep %p credits %u\n", __func__, ep, credits);


@@ -1086,28 +1088,34 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
		return CPL_RET_BUF_DONE;
		return CPL_RET_BUF_DONE;
	}
	}


	spin_lock_irqsave(&ep->com.lock, flags);
	BUG_ON(credits != 1);
	BUG_ON(credits != 1);
	dst_confirm(ep->dst);
	dst_confirm(ep->dst);
	if (!ep->mpa_skb) {
	if (!ep->mpa_skb) {
		PDBG("%s rdma_init wr_ack ep %p state %u\n",
		PDBG("%s rdma_init wr_ack ep %p state %u\n",
			__func__, ep, state_read(&ep->com));
			__func__, ep, ep->com.state);
		if (ep->mpa_attr.initiator) {
		if (ep->mpa_attr.initiator) {
			PDBG("%s initiator ep %p state %u\n",
			PDBG("%s initiator ep %p state %u\n",
				__func__, ep, state_read(&ep->com));
				__func__, ep, ep->com.state);
			if (peer2peer)
			if (peer2peer && ep->com.state == FPDU_MODE)
				iwch_post_zb_read(ep->com.qp);
				post_zb = 1;
		} else {
		} else {
			PDBG("%s responder ep %p state %u\n",
			PDBG("%s responder ep %p state %u\n",
				__func__, ep, state_read(&ep->com));
				__func__, ep, ep->com.state);
			if (ep->com.state == MPA_REQ_RCVD) {
				ep->com.rpl_done = 1;
				ep->com.rpl_done = 1;
				wake_up(&ep->com.waitq);
				wake_up(&ep->com.waitq);
			}
			}
		}
	} else {
	} else {
		PDBG("%s lsm ack ep %p state %u freeing skb\n",
		PDBG("%s lsm ack ep %p state %u freeing skb\n",
			__func__, ep, state_read(&ep->com));
			__func__, ep, ep->com.state);
		kfree_skb(ep->mpa_skb);
		kfree_skb(ep->mpa_skb);
		ep->mpa_skb = NULL;
		ep->mpa_skb = NULL;
	}
	}
	spin_unlock_irqrestore(&ep->com.lock, flags);
	if (post_zb)
		iwch_post_zb_read(ep);
	return CPL_RET_BUF_DONE;
	return CPL_RET_BUF_DONE;
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -332,7 +332,7 @@ int iwch_bind_mw(struct ib_qp *qp,
			     struct ib_mw_bind *mw_bind);
			     struct ib_mw_bind *mw_bind);
int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
int iwch_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg);
int iwch_post_zb_read(struct iwch_qp *qhp);
int iwch_post_zb_read(struct iwch_ep *ep);
int iwch_register_device(struct iwch_dev *dev);
int iwch_register_device(struct iwch_dev *dev);
void iwch_unregister_device(struct iwch_dev *dev);
void iwch_unregister_device(struct iwch_dev *dev);
void stop_read_rep_timer(struct iwch_qp *qhp);
void stop_read_rep_timer(struct iwch_qp *qhp);
+3 −3
Original line number Original line Diff line number Diff line
@@ -738,7 +738,7 @@ static inline void build_term_codes(struct respQ_msg_t *rsp_msg,
	}
	}
}
}


int iwch_post_zb_read(struct iwch_qp *qhp)
int iwch_post_zb_read(struct iwch_ep *ep)
{
{
	union t3_wr *wqe;
	union t3_wr *wqe;
	struct sk_buff *skb;
	struct sk_buff *skb;
@@ -761,10 +761,10 @@ int iwch_post_zb_read(struct iwch_qp *qhp)
	wqe->read.local_len = cpu_to_be32(0);
	wqe->read.local_len = cpu_to_be32(0);
	wqe->read.local_to = cpu_to_be64(1);
	wqe->read.local_to = cpu_to_be64(1);
	wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
	wqe->send.wrh.op_seop_flags = cpu_to_be32(V_FW_RIWR_OP(T3_WR_READ));
	wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(qhp->ep->hwtid)|
	wqe->send.wrh.gen_tid_len = cpu_to_be32(V_FW_RIWR_TID(ep->hwtid)|
						V_FW_RIWR_LEN(flit_cnt));
						V_FW_RIWR_LEN(flit_cnt));
	skb->priority = CPL_PRIORITY_DATA;
	skb->priority = CPL_PRIORITY_DATA;
	return iwch_cxgb3_ofld_send(qhp->rhp->rdev.t3cdev_p, skb);
	return iwch_cxgb3_ofld_send(ep->com.qp->rhp->rdev.t3cdev_p, skb);
}
}


/*
/*