mvumi_hs_process_page() checksums and parses a handshake page using frame_length from the page header, a u16 the firmware fills in, without checking it against the HSP_MAX_SIZE buffer the page lives in. mvumi_calculate_checksum() then walks frame_length bytes of frame_content with an unsigned char loop counter, so a frame_length of 256 or more never terminates and the probe path hangs; values between the buffer size and 255 read past the page. Reject a frame_length that does not fit the handshake buffer before using it. Read frame_length once into a local and use it for both the bound check and the checksum, so the device cannot change the value in the DMA page between the two, and use READ_ONCE() so the single fetch is guaranteed rather than left to the compiler. Fixes: f0c568a478f0 ("[SCSI] mvumi: Add Marvell UMI driver") Cc: stable@vger.kernel.org Signed-off-by: Yehyeong Lee --- drivers/scsi/mvumi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 38a92f8c25f5b..2378b676a7a78 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -1039,9 +1039,15 @@ static int mvumi_hs_process_page(struct mvumi_hba *mhba, { struct mvumi_hs_page1 *hs_page1; unsigned char page_checksum; + u16 frame_length = READ_ONCE(hs_header->frame_length); - page_checksum = mvumi_calculate_checksum(hs_header, - hs_header->frame_length); + if (frame_length > HSP_MAX_SIZE - sizeof(struct mvumi_hs_header)) { + dev_err(&mhba->pdev->dev, "invalid handshake frame length %d\n", + frame_length); + return -1; + } + + page_checksum = mvumi_calculate_checksum(hs_header, frame_length); if (page_checksum != hs_header->checksum) { dev_err(&mhba->pdev->dev, "checksum error\n"); return -1; -- 2.43.0