Linux s390 Architecture development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ajaykumar Rajappa" <ajaykr@linux.ibm.com>
Cc: "Christian Borntraeger" <borntraeger@linux.ibm.com>,
	linux-s390@vger.kernel.org,
	"Alexander Gordeev" <agordeev@linux.ibm.com>,
	"Heiko Carstens" <hca@linux.ibm.com>,
	"Vasily Gorbik" <gor@linux.ibm.com>
Subject: Re: [PATCH v5] zfcp: Fix integer underflow in status read buffer payload length
Date: Thu, 08 Oct 2026 10:28:52 +0000	[thread overview]
Message-ID: <sashiko-outbox-164011@kernel.org> (raw)
In-Reply-To: <20261008101707.2708257-1-ajaykr@linux.ibm.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] zfcp: missing upper-bound check on srb->length causes out-of-bounds read in tracing
- [Medium] zfcp: trace skipping optimization in zfcp_dbf_san() is broken by full SRB length
--

commit 20c6d5c42ce9fd226b707fb82b26a43e90bfdc4b
Author: Ajaykumar Rajappa <ajaykr@linux.ibm.com>

zfcp: Fix integer underflow in status read buffer payload length

This commit adds checks to prevent integer underflow when calculating
the payload length of a status read buffer (SRB) by verifying that
srb->length is greater than the payload offset. It also modifies
tracing logic for both HBA and SAN paths to conditionally access the
payload only when it exists, while preserving length reporting.

> diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
> index 81fb8af408e9c..fb55d58e363b9 100644
> --- a/drivers/s390/scsi/zfcp_dbf.c
> +++ b/drivers/s390/scsi/zfcp_dbf.c
[ ... ]
> @@ -253,11 +254,15 @@ void zfcp_dbf_hba_fsf_uss(char *tag, struct zfcp_fsf_req *req)
>  	rec->u.uss.s_id = ntoh24(srb->s_id);
>  	memcpy(&rec->u.uss.res4, &srb->res4, sizeof(rec->u.uss.res4));
>  
> -	/* status read buffer payload length */
> -	rec->pl_len = (!srb->length) ? 0 : srb->length -
> -			offsetof(struct fsf_status_read_buffer, payload);
> +	/* Unconditionally store value-shifted SRB length: pl_len is a bijective
> +	 * map of srb->length (pl_len + pay_offset == srb->length). A bogus
> +	 * srb->length < pay_offset wraps to a large non-zero pl_len, which is
> +	 * unambiguously distinguishable from pl_len == 0(genuine empty payload)
> +	 */
> +	rec->pl_len = (u16)(srb->length - pay_offset);
>  
> -	if (rec->pl_len)
> +	/* Only access payload bytes when srb->length actually covers them. */
> +	if (srb->length > pay_offset)
> +		zfcp_dbf_pl_write(dbf, srb->payload.data, rec->pl_len,
> +				  "fsf_uss", req->req_id, ZFCP_DBF_PAY_LEVEL);

[Severity: High]
Does this code allow an out-of-bounds read if the hardware or firmware returns
an unusually large srb->length?

While the lower bound underflow is now checked, the srb->length field is an
untrusted 32-bit value populated by hardware/firmware via DMA into a buffer
allocated as a single PAGE_SIZE (4096 bytes) element.

If srb->length is a large value (e.g., 0xFFFF), rec->pl_len will be very
large.

Since there is no upper-bound check against FSF_STATUS_READ_PAYLOAD_SIZE,
could zfcp_dbf_pl_write() read thousands of bytes beyond the allocated
page boundary?

[ ... ]
> @@ -714,17 +719,28 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf)
>  	struct zfcp_dbf *dbf = fsf->adapter->dbf;
>  	struct fsf_status_read_buffer *srb =
>  		(struct fsf_status_read_buffer *) fsf->data;
> -	u16 length;
> +	u16 length, cap_length;
>  	struct scatterlist sg;
> +	const u32 pay_offset = offsetof(struct fsf_status_read_buffer, payload);
>  
>  	if (unlikely(!debug_level_enabled(dbf->san, ZFCP_DBF_SAN_LEVEL)))
>  		return;
>  
> -	length = (u16)(srb->length -
> -			offsetof(struct fsf_status_read_buffer, payload));
> -	sg_init_one(&sg, srb->payload.data, length);
> -	zfcp_dbf_san(tag, dbf, "san_els", &sg, ZFCP_DBF_SAN_ELS, length,
> -		     fsf->req_id, ntoh24(srb->d_id), length);
> +	/*
> +	 * Store the original channel-reported SRB length in pl_len.
> +	 * cap_length specifies the number of payload bytes that may be read.
> +	 */
> +	length = (u16)srb->length;
> +	cap_length = 0;
> +	if (srb->length > pay_offset) {
> +		/* Payload present beyond the fixed header. */
> +		cap_length = (u16)(srb->length - pay_offset);
> +		sg_init_one(&sg, srb->payload.data, cap_length);

[Severity: High]
Could an unvalidated large srb->length result in an oversized cap_length here
as well?

If a large value is returned, sg_init_one() will initialize a scatterlist
length that extends well beyond the page boundary, causing zfcp_dbf_san() to
read out-of-bounds memory.

> +	}
> +
> +	zfcp_dbf_san(tag, dbf, "san_els", cap_length ? &sg : NULL,
> +		     ZFCP_DBF_SAN_ELS, length, fsf->req_id,
> +		     ntoh24(srb->d_id), cap_length);

[Severity: Medium]
Will this change break the trace skipping optimization in zfcp_dbf_san()?

By passing the full srb->length (including the header) as the len parameter
(the 6th argument) to zfcp_dbf_san(), the len value will always be at least
64 bytes for any valid payload.

Inside zfcp_dbf_san(), the optimization checks:

    if (len <= rec_len)
        goto out; /* skip pay record if full content in rec->payload */

Since rec_len is capped at ZFCP_DBF_SAN_MAX_PAYLOAD (48 bytes), this
condition will always evaluate to false, causing the driver to unconditionally
duplicate small payloads into the secondary pay_buf trace ring.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261008101707.2708257-1-ajaykr@linux.ibm.com?part=1

  reply	other threads:[~2026-10-08 10:28 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-08 10:17 [PATCH v5] zfcp: Fix integer underflow in status read buffer payload length Ajaykumar Rajappa
2026-10-08 10:28 ` sashiko-bot [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-10-08  9:57 Ajaykumar Rajappa
2026-10-08 10:08 ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-164011@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=agordeev@linux.ibm.com \
    --cc=ajaykr@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=gor@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=linux-s390@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox