| From 817a68a6584aa08e323c64283fec5ded7be84759 Mon Sep 17 00:00:00 2001 |
| From: Dennis Dalessandro <dennis.dalessandro@intel.com> |
| Date: Tue, 25 Feb 2020 14:54:45 -0500 |
| Subject: IB/hfi1, qib: Ensure RCU is locked when accessing list |
| |
| From: Dennis Dalessandro <dennis.dalessandro@intel.com> |
| |
| commit 817a68a6584aa08e323c64283fec5ded7be84759 upstream. |
| |
| The packet handling function, specifically the iteration of the qp list |
| for mad packet processing misses locking RCU before running through the |
| list. Not only is this incorrect, but the list_for_each_entry_rcu() call |
| can not be called with a conditional check for lock dependency. Remedy |
| this by invoking the rcu lock and unlock around the critical section. |
| |
| This brings MAD packet processing in line with what is done for non-MAD |
| packets. |
| |
| Fixes: 7724105686e7 ("IB/hfi1: add driver files") |
| Link: https://lore.kernel.org/r/20200225195445.140896.41873.stgit@awfm-01.aw.intel.com |
| Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> |
| Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> |
| Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/infiniband/hw/hfi1/verbs.c | 4 +++- |
| drivers/infiniband/hw/qib/qib_verbs.c | 2 ++ |
| 2 files changed, 5 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/infiniband/hw/hfi1/verbs.c |
| +++ b/drivers/infiniband/hw/hfi1/verbs.c |
| @@ -515,10 +515,11 @@ static inline void hfi1_handle_packet(st |
| opa_get_lid(packet->dlid, 9B)); |
| if (!mcast) |
| goto drop; |
| + rcu_read_lock(); |
| list_for_each_entry_rcu(p, &mcast->qp_list, list) { |
| packet->qp = p->qp; |
| if (hfi1_do_pkey_check(packet)) |
| - goto drop; |
| + goto unlock_drop; |
| spin_lock_irqsave(&packet->qp->r_lock, flags); |
| packet_handler = qp_ok(packet); |
| if (likely(packet_handler)) |
| @@ -527,6 +528,7 @@ static inline void hfi1_handle_packet(st |
| ibp->rvp.n_pkt_drops++; |
| spin_unlock_irqrestore(&packet->qp->r_lock, flags); |
| } |
| + rcu_read_unlock(); |
| /* |
| * Notify rvt_multicast_detach() if it is waiting for us |
| * to finish. |
| --- a/drivers/infiniband/hw/qib/qib_verbs.c |
| +++ b/drivers/infiniband/hw/qib/qib_verbs.c |
| @@ -329,8 +329,10 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd |
| if (mcast == NULL) |
| goto drop; |
| this_cpu_inc(ibp->pmastats->n_multicast_rcv); |
| + rcu_read_lock(); |
| list_for_each_entry_rcu(p, &mcast->qp_list, list) |
| qib_qp_rcv(rcd, hdr, 1, data, tlen, p->qp); |
| + rcu_read_unlock(); |
| /* |
| * Notify rvt_multicast_detach() if it is waiting for us |
| * to finish. |