[PATCH v2 3/7] s390/vfio_ccw: fix out of bounds check on CCW array

From: Eric Farman

Date: Mon Jul 20 2026 - 16:23:37 EST


The routine ccwchain_calc_length() counts the number of channel
command words (CCWs) that are chained together in a single channel
program, and rejects anything larger than CCWCHAIN_LEN_MAX (256) CCWs.

The loop itself is "do..while (count < 257)", and while the logic in
is_cpa_within_range() correctly adjusts between the 0-index array of
CCWs and the count of CCWs starting at 1, this means it would look
at a possible 257th CCW before ending the loop and (correctly)
returning an error.

Fix this by restructuring the loop to break as soon as 256 CCWs
(thus indexes 0-255) are examined, without looking at memory
outside the range.

Fixes: 0a19e61e6d4c ("vfio: ccw: introduce channel program interfaces")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Eric Farman <farman@xxxxxxxxxxxxx>
---
drivers/s390/cio/vfio_ccw_cp.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 7abdebd8f7c3..ce61858c82eb 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -393,11 +393,14 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
if (!ccw_is_chain(ccw) && !is_tic_within_range(ccw, iova, cnt))
break;

- ccw++;
- } while (cnt < CCWCHAIN_LEN_MAX + 1);
+ /* Exit the loop when we reach the maximum */
+ if (cnt >= CCWCHAIN_LEN_MAX) {
+ cnt = -EINVAL;
+ break;
+ }

- if (cnt == CCWCHAIN_LEN_MAX + 1)
- cnt = -EINVAL;
+ ccw++;
+ } while (1);

return cnt;
}
--
2.53.0