<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/drivers/target, branch v7.2-rc1</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>Merge branch 7.1/scsi-fixes into 7.2/scsi-staging</title>
<updated>2026-06-16T01:01:30+00:00</updated>
<author>
<name>Martin K. Petersen</name>
<email>martin.petersen@oracle.com</email>
</author>
<published>2026-06-16T01:01:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=4f87e9068bf3aaf45f226261d5efd50bec42c12c'/>
<id>4f87e9068bf3aaf45f226261d5efd50bec42c12c</id>
<content type='text'>
Pull in outstanding commits from 7.1 branch.

Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Pull in outstanding commits from 7.1 branch.

Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: Remove tcm_loop target reset handling</title>
<updated>2026-06-08T21:50:48+00:00</updated>
<author>
<name>Mike Christie</name>
<email>michael.christie@oracle.com</email>
</author>
<published>2026-05-30T05:23:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=7c08d430835a90414cd962e3a9602e5b002dee3b'/>
<id>7c08d430835a90414cd962e3a9602e5b002dee3b</id>
<content type='text'>
tcm_loop_target_reset is supposed to handle all the LUNs on a target but
it's only doing a TMR_LUN_RESET so only that one LUN is handled.  This
will cause us to return early while IOs to other LUNs are still hung in
lower layers. This just removes the target reset handler for the driver
because LIO doesn't support target resets and for the common case where
this is run from the scsi-ml error hamdler we have already tried an
abort and lun reset so waiting again is most likely useless.

Fixes: 1333eee56cdf ("scsi: target: tcm_loop: Drain commands in target_reset handler")
Signed-off-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Reviewed-by: Hannes Reinecke &lt;hare@kernel.org&gt;
Link: https://patch.msgid.link/20260530052349.5134-1-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
tcm_loop_target_reset is supposed to handle all the LUNs on a target but
it's only doing a TMR_LUN_RESET so only that one LUN is handled.  This
will cause us to return early while IOs to other LUNs are still hung in
lower layers. This just removes the target reset handler for the driver
because LIO doesn't support target resets and for the common case where
this is run from the scsi-ml error hamdler we have already tried an
abort and lun reset so waiting again is most likely useless.

Fixes: 1333eee56cdf ("scsi: target: tcm_loop: Drain commands in target_reset handler")
Signed-off-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Reviewed-by: Hannes Reinecke &lt;hare@kernel.org&gt;
Link: https://patch.msgid.link/20260530052349.5134-1-michael.christie@oracle.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: Use constant-time crypto_memneq() for CHAP digests</title>
<updated>2026-06-08T21:20:33+00:00</updated>
<author>
<name>David Disseldorp</name>
<email>ddiss@suse.de</email>
</author>
<published>2026-06-05T12:16:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=cf14fc2be868840c4c9e0e46a472995798b59712'/>
<id>cf14fc2be868840c4c9e0e46a472995798b59712</id>
<content type='text'>
A constant-time memory comparison is more suitable than plain memcmp()
for authentication digest comparison.  CHAP digests use an
authenticator-provided random challenge, so any timing side-channel
shouldn't be easily exploitable.

Reported-by: Sashiko (gemini/gemini-3.1-pro-preview)
Link: https://sashiko.dev/#/patchset/20260521151121.808477-1-hossu.alexandru%40gmail.com
Signed-off-by: David Disseldorp &lt;ddiss@suse.de&gt;
Reviewed-by: Lee Duncan &lt;lduncan@suse.com&gt;
Link: https://patch.msgid.link/20260605122019.24146-3-ddiss@suse.de
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A constant-time memory comparison is more suitable than plain memcmp()
for authentication digest comparison.  CHAP digests use an
authenticator-provided random challenge, so any timing side-channel
shouldn't be easily exploitable.

Reported-by: Sashiko (gemini/gemini-3.1-pro-preview)
Link: https://sashiko.dev/#/patchset/20260521151121.808477-1-hossu.alexandru%40gmail.com
Signed-off-by: David Disseldorp &lt;ddiss@suse.de&gt;
Reviewed-by: Lee Duncan &lt;lduncan@suse.com&gt;
Link: https://patch.msgid.link/20260605122019.24146-3-ddiss@suse.de
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: Fix hexadecimal CHAP_I handling</title>
<updated>2026-06-08T21:20:33+00:00</updated>
<author>
<name>David Disseldorp</name>
<email>ddiss@suse.de</email>
</author>
<published>2026-06-05T12:16:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=7e161211f1dd5288b4ea802b30e70ef919ebc3da'/>
<id>7e161211f1dd5288b4ea802b30e70ef919ebc3da</id>
<content type='text'>
A mutual CHAP handshake requires target processing of an initiator-sent
CHAP_I identifier. The RFC 3720 specification states:

  11.1.4.  Challenge Handshake Authentication Protocol (CHAP)
  ...
  CHAP_A=&lt;A&gt; CHAP_I=&lt;I&gt; CHAP_C=&lt;C&gt;
  ...
  Where N, (A,A1,A2), I, C, and R are (correspondingly) the Name,
  Algorithm, Identifier, Challenge, and Response as defined in
  [RFC1994], N is a text string, A,A1,A2, and I are numbers

CHAP_I parsing currently calls extract_param(), which returns the
@identifier string (stripped of any 0b/0B or 0x/0X prefix) and a @type
which indicates DECIMAL, HEX, or BASE64 encoding (based on any stripped
prefix).

Any HEX encoded CHAP_I string is further processed via:

  ret = kstrtoul(&amp;identifier[2], 0, &amp;id);

This is incorrect for two reasons:

 * The @identifier string has already been stripped of the 0x/0X prefix,
   so skipping the first two bytes omits part of the number.

 * The kstrtoul() call specifies a base of 0, which will see
   &amp;identifier[2] parsed as a decimal, unless a '0x' or (octal) '0' is
   erroneously present at that offset.

Fix this by passing the (zero-offset) identifier string to kstrtoul()
along with a base=16 parameter. Also add an explicit error handler for
BASE64 encoding.

Hex-encoded CHAP_I handling can be testing using the libiscsi EncodedI
test linked below.

Reported-by: Sashiko (gemini/gemini-3.1-pro-preview)
Link: https://sashiko.dev/#/patchset/20260521151121.808477-1-hossu.alexandru%40gmail.com
Link: https://github.com/sahlberg/libiscsi/pull/473
Fixes: 85db7391310b ("scsi: target: iscsi: Validate CHAP_R length before base64 decode")
Signed-off-by: David Disseldorp &lt;ddiss@suse.de&gt;
Reviewed-by: Lee Duncan &lt;lduncan@suse.com&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Link: https://patch.msgid.link/20260605122019.24146-2-ddiss@suse.de
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A mutual CHAP handshake requires target processing of an initiator-sent
CHAP_I identifier. The RFC 3720 specification states:

  11.1.4.  Challenge Handshake Authentication Protocol (CHAP)
  ...
  CHAP_A=&lt;A&gt; CHAP_I=&lt;I&gt; CHAP_C=&lt;C&gt;
  ...
  Where N, (A,A1,A2), I, C, and R are (correspondingly) the Name,
  Algorithm, Identifier, Challenge, and Response as defined in
  [RFC1994], N is a text string, A,A1,A2, and I are numbers

CHAP_I parsing currently calls extract_param(), which returns the
@identifier string (stripped of any 0b/0B or 0x/0X prefix) and a @type
which indicates DECIMAL, HEX, or BASE64 encoding (based on any stripped
prefix).

Any HEX encoded CHAP_I string is further processed via:

  ret = kstrtoul(&amp;identifier[2], 0, &amp;id);

This is incorrect for two reasons:

 * The @identifier string has already been stripped of the 0x/0X prefix,
   so skipping the first two bytes omits part of the number.

 * The kstrtoul() call specifies a base of 0, which will see
   &amp;identifier[2] parsed as a decimal, unless a '0x' or (octal) '0' is
   erroneously present at that offset.

Fix this by passing the (zero-offset) identifier string to kstrtoul()
along with a base=16 parameter. Also add an explicit error handler for
BASE64 encoding.

Hex-encoded CHAP_I handling can be testing using the libiscsi EncodedI
test linked below.

Reported-by: Sashiko (gemini/gemini-3.1-pro-preview)
Link: https://sashiko.dev/#/patchset/20260521151121.808477-1-hossu.alexandru%40gmail.com
Link: https://github.com/sahlberg/libiscsi/pull/473
Fixes: 85db7391310b ("scsi: target: iscsi: Validate CHAP_R length before base64 decode")
Signed-off-by: David Disseldorp &lt;ddiss@suse.de&gt;
Reviewed-by: Lee Duncan &lt;lduncan@suse.com&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Link: https://patch.msgid.link/20260605122019.24146-2-ddiss@suse.de
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: iscsi: Validate CHAP_R length before base64 decode</title>
<updated>2026-05-23T03:06:00+00:00</updated>
<author>
<name>Alexandru Hossu</name>
<email>hossu.alexandru@gmail.com</email>
</author>
<published>2026-05-21T15:11:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=85db7391310b1304d2dc8ae3b0b12105a9567147'/>
<id>85db7391310b1304d2dc8ae3b0b12105a9567147</id>
<content type='text'>
chap_server_compute_hash() allocates client_digest as
kzalloc(chap-&gt;digest_size) and then, for BASE64-encoded responses,
passes chap_r directly to chap_base64_decode() without checking whether
the input length could produce more than digest_size bytes of output.

chap_base64_decode() writes to the destination unconditionally as long
as there is input to consume. With MAX_RESPONSE_LENGTH set to 128 and
the "0b" prefix stripped by extract_param(), up to 127 base64 characters
can reach the decoder. 127 characters decode to 95 bytes. For SHA-256
(digest_size=32) this overflows client_digest by 63 bytes; for MD5
(digest_size=16) the overflow is 79 bytes.

The length check at line 344 fires after the write has already happened.

The HEX branch in the same switch statement already validates the length
up front. Apply the same approach to the BASE64 branch: strip trailing
base64 padding characters, then reject any input whose data length
exceeds DIV_ROUND_UP(digest_size * 4, 3) before calling the decoder.

Stripping trailing '=' before the comparison handles both padded and
unpadded encodings. chap_base64_decode() already returns early on '=',
so the full original string is still passed to the decoder unchanged.

The mutual CHAP path decodes CHAP_C into initiatorchg_binhex, which is
kzalloc(CHAP_CHALLENGE_STR_LEN). extract_param() caps initiatorchg at
CHAP_CHALLENGE_STR_LEN characters, so at most CHAP_CHALLENGE_STR_LEN-1
base64 characters reach the decoder. The maximum decoded size,
DIV_ROUND_UP((CHAP_CHALLENGE_STR_LEN-1) * 3, 4), is less than
CHAP_CHALLENGE_STR_LEN, so no overflow is possible there. A comment is
added at the call site to document this.

Fixes: 1e5733883421 ("scsi: target: iscsi: Support base64 in CHAP")
Cc: stable@vger.kernel.org
Signed-off-by: Alexandru Hossu &lt;hossu.alexandru@gmail.com&gt;
Reviewed-by: David Disseldorp &lt;ddiss@suse.de&gt;
Link: https://patch.msgid.link/20260521151121.808477-1-hossu.alexandru@gmail.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
chap_server_compute_hash() allocates client_digest as
kzalloc(chap-&gt;digest_size) and then, for BASE64-encoded responses,
passes chap_r directly to chap_base64_decode() without checking whether
the input length could produce more than digest_size bytes of output.

chap_base64_decode() writes to the destination unconditionally as long
as there is input to consume. With MAX_RESPONSE_LENGTH set to 128 and
the "0b" prefix stripped by extract_param(), up to 127 base64 characters
can reach the decoder. 127 characters decode to 95 bytes. For SHA-256
(digest_size=32) this overflows client_digest by 63 bytes; for MD5
(digest_size=16) the overflow is 79 bytes.

The length check at line 344 fires after the write has already happened.

The HEX branch in the same switch statement already validates the length
up front. Apply the same approach to the BASE64 branch: strip trailing
base64 padding characters, then reject any input whose data length
exceeds DIV_ROUND_UP(digest_size * 4, 3) before calling the decoder.

Stripping trailing '=' before the comparison handles both padded and
unpadded encodings. chap_base64_decode() already returns early on '=',
so the full original string is still passed to the decoder unchanged.

The mutual CHAP path decodes CHAP_C into initiatorchg_binhex, which is
kzalloc(CHAP_CHALLENGE_STR_LEN). extract_param() caps initiatorchg at
CHAP_CHALLENGE_STR_LEN characters, so at most CHAP_CHALLENGE_STR_LEN-1
base64 characters reach the decoder. The maximum decoded size,
DIV_ROUND_UP((CHAP_CHALLENGE_STR_LEN-1) * 3, 4), is less than
CHAP_CHALLENGE_STR_LEN, so no overflow is possible there. A comment is
added at the call site to document this.

Fixes: 1e5733883421 ("scsi: target: iscsi: Support base64 in CHAP")
Cc: stable@vger.kernel.org
Signed-off-by: Alexandru Hossu &lt;hossu.alexandru@gmail.com&gt;
Reviewed-by: David Disseldorp &lt;ddiss@suse.de&gt;
Link: https://patch.msgid.link/20260521151121.808477-1-hossu.alexandru@gmail.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: iscsi: Bound iscsi_encode_text_output() appends to rsp_buf</title>
<updated>2026-05-23T03:04:36+00:00</updated>
<author>
<name>Michael Bommarito</name>
<email>michael.bommarito@gmail.com</email>
</author>
<published>2026-05-11T18:49:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=bf33e01f88388c43e285492a63e539df6ffed64c'/>
<id>bf33e01f88388c43e285492a63e539df6ffed64c</id>
<content type='text'>
iscsi_encode_text_output() concatenates "key=value\0" records into
login-&gt;rsp_buf, an 8192-byte kzalloc(MAX_KEY_VALUE_PAIRS) buffer
allocated in iscsit_alloc_login_setup_buffer(). The three sprintf() call
sites in this function (lines 1398, 1411, 1424 in v7.1-rc2) never check
the remaining buffer capacity:

	*length += sprintf(output_buf, "%s=%s", er-&gt;key, er-&gt;value);
	*length += 1;
	output_buf = textbuf + *length;

The 8192-byte ceiling at iscsi_target_check_login_request() bounds the
*input* Login PDU payload, but a single PDU can carry up to 2048 minimal
four-byte "a=b\0" pairs, each unknown key expanding to a 16-byte
"a=NotUnderstood\0" output record via iscsi_add_notunderstood_response().
2048 * 16 = 32 KiB of output into an 8 KiB buffer, producing a ~24 KiB
heap overrun in the kmalloc-8k slab.

The fix introduces a static iscsi_encode_text_record() helper that uses
snprintf() with a per-call bounds check against the remaining buffer,
and threads a u32 textbuf_size parameter through
iscsi_encode_text_output(). Both call sites in
iscsi_target_handle_csg_zero() (PHASE_SECURITY) and
iscsi_target_handle_csg_one() (PHASE_OPERATIONAL) pass
MAX_KEY_VALUE_PAIRS. On overflow the encoder logs the condition, calls
iscsi_release_extra_responses() to drop queued records, and returns -1;
both caller sites now emit ISCSI_STATUS_CLS_INITIATOR_ERR /
ISCSI_LOGIN_STATUS_INIT_ERR via iscsit_tx_login_rsp() before returning,
so the initiator sees an explicit failed-login response rather than a
silent connection drop. (Prior to this patch only the PHASE_OPERATIONAL
caller did that; the PHASE_SECURITY caller is converted to the same
shape.)

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito &lt;michael.bommarito@gmail.com&gt;
Tested-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
iscsi_encode_text_output() concatenates "key=value\0" records into
login-&gt;rsp_buf, an 8192-byte kzalloc(MAX_KEY_VALUE_PAIRS) buffer
allocated in iscsit_alloc_login_setup_buffer(). The three sprintf() call
sites in this function (lines 1398, 1411, 1424 in v7.1-rc2) never check
the remaining buffer capacity:

	*length += sprintf(output_buf, "%s=%s", er-&gt;key, er-&gt;value);
	*length += 1;
	output_buf = textbuf + *length;

The 8192-byte ceiling at iscsi_target_check_login_request() bounds the
*input* Login PDU payload, but a single PDU can carry up to 2048 minimal
four-byte "a=b\0" pairs, each unknown key expanding to a 16-byte
"a=NotUnderstood\0" output record via iscsi_add_notunderstood_response().
2048 * 16 = 32 KiB of output into an 8 KiB buffer, producing a ~24 KiB
heap overrun in the kmalloc-8k slab.

The fix introduces a static iscsi_encode_text_record() helper that uses
snprintf() with a per-call bounds check against the remaining buffer,
and threads a u32 textbuf_size parameter through
iscsi_encode_text_output(). Both call sites in
iscsi_target_handle_csg_zero() (PHASE_SECURITY) and
iscsi_target_handle_csg_one() (PHASE_OPERATIONAL) pass
MAX_KEY_VALUE_PAIRS. On overflow the encoder logs the condition, calls
iscsi_release_extra_responses() to drop queued records, and returns -1;
both caller sites now emit ISCSI_STATUS_CLS_INITIATOR_ERR /
ISCSI_LOGIN_STATUS_INIT_ERR via iscsit_tx_login_rsp() before returning,
so the initiator sees an explicit failed-login response rather than a
silent connection drop. (Prior to this patch only the PHASE_OPERATIONAL
caller did that; the PHASE_SECURITY caller is converted to the same
shape.)

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito &lt;michael.bommarito@gmail.com&gt;
Tested-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd()</title>
<updated>2026-05-23T02:24:16+00:00</updated>
<author>
<name>Michael Bommarito</name>
<email>michael.bommarito@gmail.com</email>
</author>
<published>2026-04-18T15:49:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=778c2ab142c625a8a8afa570e0f9b7873f445d99'/>
<id>778c2ab142c625a8a8afa570e0f9b7873f445d99</id>
<content type='text'>
Two latent bugs in the Text-phase handler, both present since the
original LIO integration in commit e48354ce078c ("iscsi-target: Add
iSCSI fabric support for target v4.1"):

1) DataDigest CRC buffer overread (4 bytes past text_in).

   text_in is kzalloc()'d at ALIGN(payload_length, 4).  rx_size is then
   incremented by ISCSI_CRC_LEN to make room for the received DataDigest
   in the iovec, but the same (now-bumped) rx_size is passed as the
   buffer length to iscsit_crc_buf():

       if (conn-&gt;conn_ops-&gt;DataDigest) {
               ...
               rx_size += ISCSI_CRC_LEN;
       }
       ...
       if (conn-&gt;conn_ops-&gt;DataDigest) {
               data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL);

   iscsit_crc_buf() walks rx_size bytes of text_in with crc32c(), so
   when DataDigest is negotiated it reads 4 bytes past the end of the
   text_in allocation.  KASAN reproduces this directly on the unpatched
   mainline tree as slab-out-of-bounds in crc32c() called from the Text
   PDU path.  The OOB bytes feed crc32c() and are then compared against
   the initiator-supplied checksum, so the value does not flow back to
   the attacker, but the kernel does read past the buffer on every Text
   PDU with DataDigest=CRC32C.

   Fix by passing the actual padded payload length
   (ALIGN(payload_length, 4)) that was used for the kzalloc().

2) Stale cmd-&gt;text_in_ptr re-free (double-free) on ERL&gt;0 bad DataDigest
   drop.

   On DataDigest mismatch with ErrorRecoveryLevel &gt; 0 the handler
   silently drops the PDU and lets the initiator plug the CmdSN gap:

               kfree(text_in);
               return 0;

   cmd-&gt;text_in_ptr still points at the freed buffer.  The next Text
   Request on the same ITT re-enters iscsit_setup_text_cmd(), which
   unconditionally does

       kfree(cmd-&gt;text_in_ptr);
       cmd-&gt;text_in_ptr = NULL;

   freeing the same pointer a second time.  Session teardown via
   iscsit_release_cmd() has the same shape and hits the same double-free
   if the connection is dropped before a second Text Request arrives.

   On an unmodified mainline tree the bug-1 CRC overread fires first on
   the initial valid Text Request and perturbs the subsequent state, so
   #4 was isolated by building a kernel with only the bug-1 hunk of this
   patch applied plus temporary printk() observability around the three
   relevant kfree() sites.  The observability prints are not part of
   this patch.  On that build, a three-PDU Text Request sequence after
   login produces two back-to-back splats:

       BUG: KASAN: double-free in iscsit_setup_text_cmd+0x??
       BUG: KASAN: double-free in iscsit_release_cmd+0x??

   showing the same pointer freed in the ERL&gt;0 drop path and again in
   iscsit_setup_text_cmd() (next Text Request on the same ITT) and once
   more in iscsit_release_cmd() (session teardown).  On distro kernels
   with CONFIG_SLAB_FREELIST_HARDENED=y (default) the double-free
   becomes a remote kernel BUG(); on non-hardened kernels it corrupts
   the slab freelist.

   Fix by clearing cmd-&gt;text_in_ptr after the kfree() in the ERL&gt;0 drop
   path.  With both hunks applied #4 is directly observable on the stock
   tree without observability printks; fixing bug-1 alone would mask #4
   less, not more, so the hunks are submitted together.

Both fixes are one-liners.  The Text PDU state machine is unchanged and
the wire protocol is unaffected.

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito &lt;michael.bommarito@gmail.com&gt;
Tested-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Two latent bugs in the Text-phase handler, both present since the
original LIO integration in commit e48354ce078c ("iscsi-target: Add
iSCSI fabric support for target v4.1"):

1) DataDigest CRC buffer overread (4 bytes past text_in).

   text_in is kzalloc()'d at ALIGN(payload_length, 4).  rx_size is then
   incremented by ISCSI_CRC_LEN to make room for the received DataDigest
   in the iovec, but the same (now-bumped) rx_size is passed as the
   buffer length to iscsit_crc_buf():

       if (conn-&gt;conn_ops-&gt;DataDigest) {
               ...
               rx_size += ISCSI_CRC_LEN;
       }
       ...
       if (conn-&gt;conn_ops-&gt;DataDigest) {
               data_crc = iscsit_crc_buf(text_in, rx_size, 0, NULL);

   iscsit_crc_buf() walks rx_size bytes of text_in with crc32c(), so
   when DataDigest is negotiated it reads 4 bytes past the end of the
   text_in allocation.  KASAN reproduces this directly on the unpatched
   mainline tree as slab-out-of-bounds in crc32c() called from the Text
   PDU path.  The OOB bytes feed crc32c() and are then compared against
   the initiator-supplied checksum, so the value does not flow back to
   the attacker, but the kernel does read past the buffer on every Text
   PDU with DataDigest=CRC32C.

   Fix by passing the actual padded payload length
   (ALIGN(payload_length, 4)) that was used for the kzalloc().

2) Stale cmd-&gt;text_in_ptr re-free (double-free) on ERL&gt;0 bad DataDigest
   drop.

   On DataDigest mismatch with ErrorRecoveryLevel &gt; 0 the handler
   silently drops the PDU and lets the initiator plug the CmdSN gap:

               kfree(text_in);
               return 0;

   cmd-&gt;text_in_ptr still points at the freed buffer.  The next Text
   Request on the same ITT re-enters iscsit_setup_text_cmd(), which
   unconditionally does

       kfree(cmd-&gt;text_in_ptr);
       cmd-&gt;text_in_ptr = NULL;

   freeing the same pointer a second time.  Session teardown via
   iscsit_release_cmd() has the same shape and hits the same double-free
   if the connection is dropped before a second Text Request arrives.

   On an unmodified mainline tree the bug-1 CRC overread fires first on
   the initial valid Text Request and perturbs the subsequent state, so
   #4 was isolated by building a kernel with only the bug-1 hunk of this
   patch applied plus temporary printk() observability around the three
   relevant kfree() sites.  The observability prints are not part of
   this patch.  On that build, a three-PDU Text Request sequence after
   login produces two back-to-back splats:

       BUG: KASAN: double-free in iscsit_setup_text_cmd+0x??
       BUG: KASAN: double-free in iscsit_release_cmd+0x??

   showing the same pointer freed in the ERL&gt;0 drop path and again in
   iscsit_setup_text_cmd() (next Text Request on the same ITT) and once
   more in iscsit_release_cmd() (session teardown).  On distro kernels
   with CONFIG_SLAB_FREELIST_HARDENED=y (default) the double-free
   becomes a remote kernel BUG(); on non-hardened kernels it corrupts
   the slab freelist.

   Fix by clearing cmd-&gt;text_in_ptr after the kfree() in the ERL&gt;0 drop
   path.  With both hunks applied #4 is directly observable on the stock
   tree without observability printks; fixing bug-1 alone would mask #4
   less, not more, so the hunks are submitted together.

Both fixes are one-liners.  The Text PDU state machine is unchanged and
the wire protocol is unaffected.

Fixes: e48354ce078c ("iscsi-target: Add iSCSI fabric support for target v4.1")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito &lt;michael.bommarito@gmail.com&gt;
Tested-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: tcm_loop: Fix NULL ptr dereference</title>
<updated>2026-05-15T02:21:01+00:00</updated>
<author>
<name>Guixin Liu</name>
<email>kanie@linux.alibaba.com</email>
</author>
<published>2026-04-24T01:39:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=b71cb088b2e3427924a470fc43e7aedb8a40d2e3'/>
<id>b71cb088b2e3427924a470fc43e7aedb8a40d2e3</id>
<content type='text'>
The TCM_LOOP LUN creation process calls device_register() to create the
device, which in turn invokes tcm_loop_driver_probe() registered with
the TCM_LOOP bus to create and register the scsi_host.  However, if the
scsi_host memory allocation fails or scsi_add_host() fails, the
device_register() process still returns success.  Subsequently, when the
user binds the LUN to a specific backend device, it accesses the NULL or
freed scsi_host.

Crash Call Trace:
  RIP: 0010:scsi_is_host_device+0x7/0x20
  scsi_alloc_target+0x32/0x2c0
  __scsi_add_device+0x41/0xf0
  scsi_add_device+0xd/0x30
  tcm_loop_port_link+0x25/0x50 [tcm_loop]
  target_fabric_port_link+0x9c/0xb0 [target_core_mod]
  ...

This issue is fixed by:

 1. Setting the tcm_loop_hba's scsi_host to NULL, if scsi_add_host()
    fails.

 2. Checking the tcm_loop_hba's scsi_host after device_register().

 3. Checking the tcm_loop_hba's scsi_host in tcm_loop_driver_remove().

Fixes: 3703b2c5d041 ("[SCSI] tcm_loop: Add multi-fabric Linux/SCSI LLD fabric module")
Signed-off-by: Guixin Liu &lt;kanie@linux.alibaba.com&gt;
Reviewed-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Link: https://patch.msgid.link/20260424013923.25998-1-kanie@linux.alibaba.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The TCM_LOOP LUN creation process calls device_register() to create the
device, which in turn invokes tcm_loop_driver_probe() registered with
the TCM_LOOP bus to create and register the scsi_host.  However, if the
scsi_host memory allocation fails or scsi_add_host() fails, the
device_register() process still returns success.  Subsequently, when the
user binds the LUN to a specific backend device, it accesses the NULL or
freed scsi_host.

Crash Call Trace:
  RIP: 0010:scsi_is_host_device+0x7/0x20
  scsi_alloc_target+0x32/0x2c0
  __scsi_add_device+0x41/0xf0
  scsi_add_device+0xd/0x30
  tcm_loop_port_link+0x25/0x50 [tcm_loop]
  target_fabric_port_link+0x9c/0xb0 [target_core_mod]
  ...

This issue is fixed by:

 1. Setting the tcm_loop_hba's scsi_host to NULL, if scsi_add_host()
    fails.

 2. Checking the tcm_loop_hba's scsi_host after device_register().

 3. Checking the tcm_loop_hba's scsi_host in tcm_loop_driver_remove().

Fixes: 3703b2c5d041 ("[SCSI] tcm_loop: Add multi-fabric Linux/SCSI LLD fabric module")
Signed-off-by: Guixin Liu &lt;kanie@linux.alibaba.com&gt;
Reviewed-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Link: https://patch.msgid.link/20260424013923.25998-1-kanie@linux.alibaba.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge branch '7.1/scsi-queue' into 7.1/scsi-fixes</title>
<updated>2026-04-27T01:15:04+00:00</updated>
<author>
<name>Martin K. Petersen</name>
<email>martin.petersen@oracle.com</email>
</author>
<published>2026-04-27T01:15:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=98f69975d4c0434ca2e6e8cfa1d8d51647a20593'/>
<id>98f69975d4c0434ca2e6e8cfa1d8d51647a20593</id>
<content type='text'>
Pull in remaining commits from 7.1/scsi-queue.

Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Pull in remaining commits from 7.1/scsi-queue.

Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: iscsi: reject invalid size Extended CDB AHS</title>
<updated>2026-04-22T01:08:25+00:00</updated>
<author>
<name>Carlos Bilbao</name>
<email>carlos.bilbao@kernel.org</email>
</author>
<published>2026-04-15T04:07:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=2f3835771dff512750205aa5f5f61aec0f2b8cb7'/>
<id>2f3835771dff512750205aa5f5f61aec0f2b8cb7</id>
<content type='text'>
If ecdb_ahdr-&gt;ahslength is zero, two bugs follow:

  kmalloc(be16_to_cpu(ecdb_ahdr-&gt;ahslength) + 15, ...)

allocates 15 bytes, but the immediately following memcpy writes
ISCSI_CDB_SIZE (16) bytes into it, a one-byte heap overflow. Also:

  memcpy(cdb + ISCSI_CDB_SIZE, ecdb_ahdr-&gt;ecdb,
           be16_to_cpu(ecdb_ahdr-&gt;ahslength) - 1);

(u16)0 - 1 promotes to (int)-1 which converts to SIZE_MAX as size_t,
causing a massive out-of-bounds write.

Reject ahslength == 0 with ISCSI_REASON_PROTOCOL_ERROR before the kmalloc.
Also reject ahslength values that exceed the actual AHS buffer advertised.

Fixes: 8f1f7d297bce ("scsi: target: iscsi: Add support for extended CDB AHS")
Signed-off-by: Carlos Bilbao &lt;carlos.bilbao@kernel.org&gt;
Reviewed-by: Dmitry Bogdanov &lt;d.bogdanov@yadro.com&gt;
Link: https://patch.msgid.link/20260415040728.187680-1-carlos.bilbao@kernel.org
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If ecdb_ahdr-&gt;ahslength is zero, two bugs follow:

  kmalloc(be16_to_cpu(ecdb_ahdr-&gt;ahslength) + 15, ...)

allocates 15 bytes, but the immediately following memcpy writes
ISCSI_CDB_SIZE (16) bytes into it, a one-byte heap overflow. Also:

  memcpy(cdb + ISCSI_CDB_SIZE, ecdb_ahdr-&gt;ecdb,
           be16_to_cpu(ecdb_ahdr-&gt;ahslength) - 1);

(u16)0 - 1 promotes to (int)-1 which converts to SIZE_MAX as size_t,
causing a massive out-of-bounds write.

Reject ahslength == 0 with ISCSI_REASON_PROTOCOL_ERROR before the kmalloc.
Also reject ahslength values that exceed the actual AHS buffer advertised.

Fixes: 8f1f7d297bce ("scsi: target: iscsi: Add support for extended CDB AHS")
Signed-off-by: Carlos Bilbao &lt;carlos.bilbao@kernel.org&gt;
Reviewed-by: Dmitry Bogdanov &lt;d.bogdanov@yadro.com&gt;
Link: https://patch.msgid.link/20260415040728.187680-1-carlos.bilbao@kernel.org
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
