iw_cxgb4: Guard against null cm_id in dump_ep/qp
authorGanesh Goudar <ganeshgr@chelsio.com>
Fri, 20 Jan 2017 07:02:01 +0000 (12:32 +0530)
committerDoug Ledford <dledford@redhat.com>
Tue, 24 Jan 2017 19:44:01 +0000 (14:44 -0500)
Endpoints that are aborting can have already dereferenced the
cm_id and set ep->com.cm_id to NULL.  So guard against that in
dump_ep() and dump_qp().

Also create a common function for setting up ip address pointers
since the same logic is needed in several places.

Reviewed-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/cxgb4/device.c

index 516b0ae6dc3f6d061cc3c7d8ba412196785a599c..c4b344e1f7e71ac11fc90d8496cbaadcd35c9906 100644 (file)
@@ -214,6 +214,52 @@ static const struct file_operations wr_log_debugfs_fops = {
        .write   = wr_log_clear,
 };
 
+static struct sockaddr_in zero_sin = {
+       .sin_family = AF_INET,
+};
+
+static struct sockaddr_in6 zero_sin6 = {
+       .sin6_family = AF_INET6,
+};
+
+static void set_ep_sin_addrs(struct c4iw_ep *ep,
+                            struct sockaddr_in **lsin,
+                            struct sockaddr_in **rsin,
+                            struct sockaddr_in **m_lsin,
+                            struct sockaddr_in **m_rsin)
+{
+       struct iw_cm_id *id = ep->com.cm_id;
+
+       *lsin = (struct sockaddr_in *)&ep->com.local_addr;
+       *rsin = (struct sockaddr_in *)&ep->com.remote_addr;
+       if (id) {
+               *m_lsin = (struct sockaddr_in *)&id->m_local_addr;
+               *m_rsin = (struct sockaddr_in *)&id->m_remote_addr;
+       } else {
+               *m_lsin = &zero_sin;
+               *m_rsin = &zero_sin;
+       }
+}
+
+static void set_ep_sin6_addrs(struct c4iw_ep *ep,
+                             struct sockaddr_in6 **lsin6,
+                             struct sockaddr_in6 **rsin6,
+                             struct sockaddr_in6 **m_lsin6,
+                             struct sockaddr_in6 **m_rsin6)
+{
+       struct iw_cm_id *id = ep->com.cm_id;
+
+       *lsin6 = (struct sockaddr_in6 *)&ep->com.local_addr;
+       *rsin6 = (struct sockaddr_in6 *)&ep->com.remote_addr;
+       if (id) {
+               *m_lsin6 = (struct sockaddr_in6 *)&id->m_local_addr;
+               *m_rsin6 = (struct sockaddr_in6 *)&id->m_remote_addr;
+       } else {
+               *m_lsin6 = &zero_sin6;
+               *m_rsin6 = &zero_sin6;
+       }
+}
+
 static int dump_qp(int id, void *p, void *data)
 {
        struct c4iw_qp *qp = p;
@@ -229,16 +275,15 @@ static int dump_qp(int id, void *p, void *data)
                return 1;
 
        if (qp->ep) {
-               if (qp->ep->com.local_addr.ss_family == AF_INET) {
-                       struct sockaddr_in *lsin = (struct sockaddr_in *)
-                               &qp->ep->com.cm_id->local_addr;
-                       struct sockaddr_in *rsin = (struct sockaddr_in *)
-                               &qp->ep->com.cm_id->remote_addr;
-                       struct sockaddr_in *mapped_lsin = (struct sockaddr_in *)
-                               &qp->ep->com.cm_id->m_local_addr;
-                       struct sockaddr_in *mapped_rsin = (struct sockaddr_in *)
-                               &qp->ep->com.cm_id->m_remote_addr;
+               struct c4iw_ep *ep = qp->ep;
+
+               if (ep->com.local_addr.ss_family == AF_INET) {
+                       struct sockaddr_in *lsin;
+                       struct sockaddr_in *rsin;
+                       struct sockaddr_in *m_lsin;
+                       struct sockaddr_in *m_rsin;
 
+                       set_ep_sin_addrs(ep, &lsin, &rsin, &m_lsin, &m_rsin);
                        cc = snprintf(qpd->buf + qpd->pos, space,
                                      "rc qp sq id %u rq id %u state %u "
                                      "onchip %u ep tid %u state %u "
@@ -246,23 +291,19 @@ static int dump_qp(int id, void *p, void *data)
                                      qp->wq.sq.qid, qp->wq.rq.qid,
                                      (int)qp->attr.state,
                                      qp->wq.sq.flags & T4_SQ_ONCHIP,
-                                     qp->ep->hwtid, (int)qp->ep->com.state,
+                                     ep->hwtid, (int)ep->com.state,
                                      &lsin->sin_addr, ntohs(lsin->sin_port),
-                                     ntohs(mapped_lsin->sin_port),
+                                     ntohs(m_lsin->sin_port),
                                      &rsin->sin_addr, ntohs(rsin->sin_port),
-                                     ntohs(mapped_rsin->sin_port));
+                                     ntohs(m_rsin->sin_port));
                } else {
-                       struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)
-                               &qp->ep->com.cm_id->local_addr;
-                       struct sockaddr_in6 *rsin6 = (struct sockaddr_in6 *)
-                               &qp->ep->com.cm_id->remote_addr;
-                       struct sockaddr_in6 *mapped_lsin6 =
-                               (struct sockaddr_in6 *)
-                               &qp->ep->com.cm_id->m_local_addr;
-                       struct sockaddr_in6 *mapped_rsin6 =
-                               (struct sockaddr_in6 *)
-                               &qp->ep->com.cm_id->m_remote_addr;
+                       struct sockaddr_in6 *lsin6;
+                       struct sockaddr_in6 *rsin6;
+                       struct sockaddr_in6 *m_lsin6;
+                       struct sockaddr_in6 *m_rsin6;
 
+                       set_ep_sin6_addrs(ep, &lsin6, &rsin6, &m_lsin6,
+                                         &m_rsin6);
                        cc = snprintf(qpd->buf + qpd->pos, space,
                                      "rc qp sq id %u rq id %u state %u "
                                      "onchip %u ep tid %u state %u "
@@ -270,13 +311,13 @@ static int dump_qp(int id, void *p, void *data)
                                      qp->wq.sq.qid, qp->wq.rq.qid,
                                      (int)qp->attr.state,
                                      qp->wq.sq.flags & T4_SQ_ONCHIP,
-                                     qp->ep->hwtid, (int)qp->ep->com.state,
+                                     ep->hwtid, (int)ep->com.state,
                                      &lsin6->sin6_addr,
                                      ntohs(lsin6->sin6_port),
-                                     ntohs(mapped_lsin6->sin6_port),
+                                     ntohs(m_lsin6->sin6_port),
                                      &rsin6->sin6_addr,
                                      ntohs(rsin6->sin6_port),
-                                     ntohs(mapped_rsin6->sin6_port));
+                                     ntohs(m_rsin6->sin6_port));
                }
        } else
                cc = snprintf(qpd->buf + qpd->pos, space,
@@ -533,15 +574,12 @@ static int dump_ep(int id, void *p, void *data)
                return 1;
 
        if (ep->com.local_addr.ss_family == AF_INET) {
-               struct sockaddr_in *lsin = (struct sockaddr_in *)
-                       &ep->com.cm_id->local_addr;
-               struct sockaddr_in *rsin = (struct sockaddr_in *)
-                       &ep->com.cm_id->remote_addr;
-               struct sockaddr_in *mapped_lsin = (struct sockaddr_in *)
-                       &ep->com.cm_id->m_local_addr;
-               struct sockaddr_in *mapped_rsin = (struct sockaddr_in *)
-                       &ep->com.cm_id->m_remote_addr;
+               struct sockaddr_in *lsin;
+               struct sockaddr_in *rsin;
+               struct sockaddr_in *m_lsin;
+               struct sockaddr_in *m_rsin;
 
+               set_ep_sin_addrs(ep, &lsin, &rsin, &m_lsin, &m_rsin);
                cc = snprintf(epd->buf + epd->pos, space,
                              "ep %p cm_id %p qp %p state %d flags 0x%lx "
                              "history 0x%lx hwtid %d atid %d "
@@ -553,19 +591,16 @@ static int dump_ep(int id, void *p, void *data)
                              ep->stats.connect_neg_adv,
                              ep->stats.abort_neg_adv,
                              &lsin->sin_addr, ntohs(lsin->sin_port),
-                             ntohs(mapped_lsin->sin_port),
+                             ntohs(m_lsin->sin_port),
                              &rsin->sin_addr, ntohs(rsin->sin_port),
-                             ntohs(mapped_rsin->sin_port));
+                             ntohs(m_rsin->sin_port));
        } else {
-               struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)
-                       &ep->com.cm_id->local_addr;
-               struct sockaddr_in6 *rsin6 = (struct sockaddr_in6 *)
-                       &ep->com.cm_id->remote_addr;
-               struct sockaddr_in6 *mapped_lsin6 = (struct sockaddr_in6 *)
-                       &ep->com.cm_id->m_local_addr;
-               struct sockaddr_in6 *mapped_rsin6 = (struct sockaddr_in6 *)
-                       &ep->com.cm_id->m_remote_addr;
+               struct sockaddr_in6 *lsin6;
+               struct sockaddr_in6 *rsin6;
+               struct sockaddr_in6 *m_lsin6;
+               struct sockaddr_in6 *m_rsin6;
 
+               set_ep_sin6_addrs(ep, &lsin6, &rsin6, &m_lsin6, &m_rsin6);
                cc = snprintf(epd->buf + epd->pos, space,
                              "ep %p cm_id %p qp %p state %d flags 0x%lx "
                              "history 0x%lx hwtid %d atid %d "
@@ -577,9 +612,9 @@ static int dump_ep(int id, void *p, void *data)
                              ep->stats.connect_neg_adv,
                              ep->stats.abort_neg_adv,
                              &lsin6->sin6_addr, ntohs(lsin6->sin6_port),
-                             ntohs(mapped_lsin6->sin6_port),
+                             ntohs(m_lsin6->sin6_port),
                              &rsin6->sin6_addr, ntohs(rsin6->sin6_port),
-                             ntohs(mapped_rsin6->sin6_port));
+                             ntohs(m_rsin6->sin6_port));
        }
        if (cc < space)
                epd->pos += cc;
@@ -600,7 +635,7 @@ static int dump_listen_ep(int id, void *p, void *data)
        if (ep->com.local_addr.ss_family == AF_INET) {
                struct sockaddr_in *lsin = (struct sockaddr_in *)
                        &ep->com.cm_id->local_addr;
-               struct sockaddr_in *mapped_lsin = (struct sockaddr_in *)
+               struct sockaddr_in *m_lsin = (struct sockaddr_in *)
                        &ep->com.cm_id->m_local_addr;
 
                cc = snprintf(epd->buf + epd->pos, space,
@@ -609,11 +644,11 @@ static int dump_listen_ep(int id, void *p, void *data)
                              ep, ep->com.cm_id, (int)ep->com.state,
                              ep->com.flags, ep->stid, ep->backlog,
                              &lsin->sin_addr, ntohs(lsin->sin_port),
-                             ntohs(mapped_lsin->sin_port));
+                             ntohs(m_lsin->sin_port));
        } else {
                struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)
                        &ep->com.cm_id->local_addr;
-               struct sockaddr_in6 *mapped_lsin6 = (struct sockaddr_in6 *)
+               struct sockaddr_in6 *m_lsin6 = (struct sockaddr_in6 *)
                        &ep->com.cm_id->m_local_addr;
 
                cc = snprintf(epd->buf + epd->pos, space,
@@ -622,7 +657,7 @@ static int dump_listen_ep(int id, void *p, void *data)
                              ep, ep->com.cm_id, (int)ep->com.state,
                              ep->com.flags, ep->stid, ep->backlog,
                              &lsin6->sin6_addr, ntohs(lsin6->sin6_port),
-                             ntohs(mapped_lsin6->sin6_port));
+                             ntohs(m_lsin6->sin6_port));
        }
        if (cc < space)
                epd->pos += cc;