From d5116a1588ee63ff92d5c4e6dcdb6645ce2bd5e5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 3 Aug 2026 13:27:16 +0100 Subject: [PATCH] [fcp] Avoid potential integer overflow in parsing response data Signed-off-by: Michael Brown --- src/net/fcp.c | 56 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/src/net/fcp.c b/src/net/fcp.c index d3809aa8e..5bb6ebff2 100644 --- a/src/net/fcp.c +++ b/src/net/fcp.c @@ -555,40 +555,67 @@ static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd, struct xfer_metadata *meta __unused ) { struct fcp_device *fcpdev = fcpcmd->fcpdev; struct scsi_cmd *command = &fcpcmd->command; - struct fcp_rsp *rsp = iobuf->data; + struct fcp_rsp *rsp; struct scsi_rsp response; + void *response_data; + void *sense_data; + size_t response_data_len; + size_t sense_data_len; + size_t remaining; int rc; - /* Sanity check */ - if ( ( iob_len ( iobuf ) < sizeof ( *rsp ) ) || - ( iob_len ( iobuf ) < ( sizeof ( *rsp ) + - fcp_rsp_response_data_len ( rsp ) + - fcp_rsp_sense_data_len ( rsp ) ) ) ) { + /* Parse response */ + remaining = iob_len ( iobuf ); + if ( remaining < sizeof ( *rsp ) ) { DBGC ( fcpdev, "FCP %p xchg %04x received invalid response " "IU:\n", fcpdev, fcpcmd->xchg_id ); DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) ); rc = -EPROTO; goto done; } + rsp = iobuf->data; + remaining -= sizeof ( *rsp ); DBGC2 ( fcpdev, "FCP %p xchg %04x RSP stat %02x resid %08x flags %02x" "%s%s%s%s\n", fcpdev, fcpcmd->xchg_id, rsp->status, ntohl ( rsp->residual ), rsp->flags, ( ( rsp->flags & FCP_RSP_RESPONSE_LEN_VALID ) ? " resp" : "" ), ( ( rsp->flags & FCP_RSP_SENSE_LEN_VALID ) ? " sense" : "" ), ( ( rsp->flags & FCP_RSP_RESIDUAL_OVERRUN ) ? " over" : "" ), - ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "" )); - if ( fcp_rsp_response_data ( rsp ) ) { + ( ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) ? " under" : "")); + + /* Parse response data */ + response_data_len = fcp_rsp_response_data_len ( rsp ); + if ( remaining < response_data_len ) { + DBGC ( fcpdev, "FCP %p xchg %04x received overlength " + "response data:\n", fcpdev, fcpcmd->xchg_id ); + DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) ); + rc = -EPROTO; + goto done; + } + response_data = fcp_rsp_response_data ( rsp ); + if ( response_data ) { DBGC2 ( fcpdev, "FCP %p xchg %04x response data:\n", fcpdev, fcpcmd->xchg_id ); - DBGC2_HDA ( fcpdev, 0, fcp_rsp_response_data ( rsp ), - fcp_rsp_response_data_len ( rsp ) ); + DBGC2_HDA ( fcpdev, 0, response_data, response_data_len ); + } + remaining -= response_data_len; + + /* Parse sense data */ + sense_data_len = fcp_rsp_sense_data_len ( rsp ); + if ( remaining < sense_data_len ) { + DBGC ( fcpdev, "FCP %p xchg %04x received overlength " + "sense data:\n", fcpdev, fcpcmd->xchg_id ); + DBGC_HDA ( fcpdev, 0, iobuf->data, iob_len ( iobuf ) ); + rc = -EPROTO; + goto done; } - if ( fcp_rsp_sense_data ( rsp ) ) { + sense_data = fcp_rsp_sense_data ( rsp ); + if ( sense_data ) { DBGC2 ( fcpdev, "FCP %p xchg %04x sense data:\n", fcpdev, fcpcmd->xchg_id ); - DBGC2_HDA ( fcpdev, 0, fcp_rsp_sense_data ( rsp ), - fcp_rsp_sense_data_len ( rsp ) ); + DBGC2_HDA ( fcpdev, 0, sense_data, sense_data_len ); } + remaining -= sense_data_len; /* Check for locally-detected command underrun */ if ( ( rsp->status == 0 ) && @@ -611,8 +638,7 @@ static int fcpcmd_recv_rsp ( struct fcp_command *fcpcmd, if ( rsp->flags & FCP_RSP_RESIDUAL_UNDERRUN ) response.overrun = -response.overrun; } - scsi_parse_sense ( fcp_rsp_sense_data ( rsp ), - fcp_rsp_sense_data_len ( rsp ), &response.sense ); + scsi_parse_sense ( sense_data, sense_data_len, &response.sense ); /* Free buffer before sending response, to minimise * out-of-memory errors. -- 2.47.3