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@vger.kernel.org Signed-off-by: Eric Farman --- 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