| .. | .. |
|---|
| 56 | 56 | if (READ_ONCE(cqe->flags) & SIW_WQE_VALID) { |
|---|
| 57 | 57 | memset(wc, 0, sizeof(*wc)); |
|---|
| 58 | 58 | wc->wr_id = cqe->id; |
|---|
| 59 | | - wc->status = map_cqe_status[cqe->status].ib; |
|---|
| 60 | | - wc->opcode = map_wc_opcode[cqe->opcode]; |
|---|
| 61 | 59 | wc->byte_len = cqe->bytes; |
|---|
| 62 | 60 | |
|---|
| 63 | 61 | /* |
|---|
| .. | .. |
|---|
| 71 | 69 | wc->wc_flags = IB_WC_WITH_INVALIDATE; |
|---|
| 72 | 70 | } |
|---|
| 73 | 71 | wc->qp = cqe->base_qp; |
|---|
| 72 | + wc->opcode = map_wc_opcode[cqe->opcode]; |
|---|
| 73 | + wc->status = map_cqe_status[cqe->status].ib; |
|---|
| 74 | 74 | siw_dbg_cq(cq, |
|---|
| 75 | 75 | "idx %u, type %d, flags %2x, id 0x%pK\n", |
|---|
| 76 | 76 | cq->cq_get % cq->num_cqe, cqe->opcode, |
|---|
| 77 | 77 | cqe->flags, (void *)(uintptr_t)cqe->id); |
|---|
| 78 | + } else { |
|---|
| 79 | + /* |
|---|
| 80 | + * A malicious user may set invalid opcode or |
|---|
| 81 | + * status in the user mmapped CQE array. |
|---|
| 82 | + * Sanity check and correct values in that case |
|---|
| 83 | + * to avoid out-of-bounds access to global arrays |
|---|
| 84 | + * for opcode and status mapping. |
|---|
| 85 | + */ |
|---|
| 86 | + u8 opcode = cqe->opcode; |
|---|
| 87 | + u16 status = cqe->status; |
|---|
| 88 | + |
|---|
| 89 | + if (opcode >= SIW_NUM_OPCODES) { |
|---|
| 90 | + opcode = 0; |
|---|
| 91 | + status = SIW_WC_GENERAL_ERR; |
|---|
| 92 | + } else if (status >= SIW_NUM_WC_STATUS) { |
|---|
| 93 | + status = SIW_WC_GENERAL_ERR; |
|---|
| 94 | + } |
|---|
| 95 | + wc->opcode = map_wc_opcode[opcode]; |
|---|
| 96 | + wc->status = map_cqe_status[status].ib; |
|---|
| 97 | + |
|---|
| 78 | 98 | } |
|---|
| 79 | 99 | WRITE_ONCE(cqe->flags, 0); |
|---|
| 80 | 100 | cq->cq_get++; |
|---|