diff options
author | Sean Hefty <sean.hefty@intel.com> | 2010-07-21 19:36:52 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2010-07-28 18:18:24 -0400 |
commit | 50a025c69ee749d822c301f9bf63dee13c113680 (patch) | |
tree | 132eccb57ef6c10cc96e50a3b53306d6e84887a1 /drivers | |
parent | f400e5b38a5eeb8a91b481e4f3059611fa4ddce2 (diff) |
IB/cm: Check LAP state before sending an MRA
NULL pointer dereferences in ib_cm_init_qp_attr() were seen by some
users. From a crash dump, I determined that we died in
cm_init_qp_rts_attr() (it's inlined, so it doesn't show up in the
traceback) on the line labeled below:
static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv,
struct ib_qp_attr *qp_attr,
int *qp_attr_mask)
{
........
if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) {
.....
} else {
*qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE;
qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; <-die
The problem is that the rdma_cm can call ib_send_cm_mra() after a
connection has been established. The ib_cm incorrectly assumes that
the MRA is in response to a LAP (load alternate path) message, even
though no LAP message has been received. The ib_cm needs to check the
lap_state before sending an MRA if the cm_id state is established.
Reported-by: Arthur Kepner <akepner@sgi.com>
Reported-by: Josh England <jjengla@gmail.com>
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/core/cm.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index ad63b79afac1..64e0903091a8 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -2409,10 +2409,12 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id, | |||
2409 | msg_response = CM_MSG_RESPONSE_REP; | 2409 | msg_response = CM_MSG_RESPONSE_REP; |
2410 | break; | 2410 | break; |
2411 | case IB_CM_ESTABLISHED: | 2411 | case IB_CM_ESTABLISHED: |
2412 | cm_state = cm_id->state; | 2412 | if (cm_id->lap_state == IB_CM_LAP_RCVD) { |
2413 | lap_state = IB_CM_MRA_LAP_SENT; | 2413 | cm_state = cm_id->state; |
2414 | msg_response = CM_MSG_RESPONSE_OTHER; | 2414 | lap_state = IB_CM_MRA_LAP_SENT; |
2415 | break; | 2415 | msg_response = CM_MSG_RESPONSE_OTHER; |
2416 | break; | ||
2417 | } | ||
2416 | default: | 2418 | default: |
2417 | ret = -EINVAL; | 2419 | ret = -EINVAL; |
2418 | goto error1; | 2420 | goto error1; |