mthca: Fix signed-overflow UB in __mthca_cq_clean() sweep condition
[ Upstream commit 8bc76f2d55c703201649c985ac31cfb828c916c6 ]
The backward sweep in __mthca_cq_clean() used:
while ((int) --prod_index - (int) cq->cons_index >= 0)
Both operands are uint32_t. Promoting them to int and then subtracting
is undefined behaviour when the result overflows (C11 §6.5p5). GCC and
Clang exploit that UB: they fold "(int)a - (int)b >= 0" into the plain
signed compare "(int)a >= (int)b", which has no exit when cons_index is
0x80000000 (INT_MIN), causing an infinite loop with the CQ spinlock held.
Replace with a plain unsigned equality check — identical fix to the one
applied to providers/mlx5/cq.c and providers/mlx4/cq.c:
while (prod_index != cq->cons_index) { --prod_index; ... }
prod_index starts at the value found by the forward scan, which begins
at cons_index and only increments, so prod_index >= cons_index always
holds. Decrementing prod_index each iteration reaches cons_index in
exactly (prod_index - cons_index) steps. No arithmetic on the loop
condition, no signed casts, no compiler-visible UB.
Fixes: f0721148654c ("Fix long request lists for Tavor HCAs")
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Signed-off-by: Nicolas Morey <nmorey@suse.com>
diff --git a/providers/mthca/cq.c b/providers/mthca/cq.c
index dd8baca..3fff17f 100644
--- a/providers/mthca/cq.c
+++ b/providers/mthca/cq.c
@@ -563,7 +563,8 @@
* Now sweep backwards through the CQ, removing CQ entries
* that match our QP by copying older entries on top of them.
*/
- while ((int) --prod_index - (int) cq->cons_index >= 0) {
+ while (prod_index != cq->cons_index) {
+ --prod_index;
cqe = get_cqe(cq, prod_index & cq->ibv_cq.cqe);
if (cqe->my_qpn == htobe32(qpn)) {
if (srq && is_recv_cqe(cqe))