<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/drivers/target, branch v7.2-rc6</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>scsi: target: Clear cmd_cnt when initial counter enrollment fails</title>
<updated>2026-07-29T01:52:09+00:00</updated>
<author>
<name>Leon Romanovsky</name>
<email>leonro@nvidia.com</email>
</author>
<published>2026-07-22T06:30:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=a8ddfd2425bbbafadae8700d63ed8a61a4109878'/>
<id>a8ddfd2425bbbafadae8700d63ed8a61a4109878</id>
<content type='text'>
When target_get_sess_cmd() fails during session shutdown because
percpu_ref_tryget_live() returns false, the command keeps the
se_cmd-&gt;cmd_cnt pointer that __target_init_cmd() assigned earlier
without owning a reference. Final release through
target_release_cmd_kref() then issues an unmatched percpu_ref_put().

Commit 8e288be8606a ("scsi: target: Pass in cmd counter to use during
cmd setup") moved the cmd_cnt assignment ahead of the reference
acquisition.  Clear se_cmd-&gt;cmd_cnt whenever the initial
target_get_sess_cmd() fails in target_init_cmd() and
target_submit_tmr(), so release performs exactly one matching put per
acquired reference.

Fixes: 8e288be8606a ("scsi: target: Pass in cmd counter to use during cmd setup")
Signed-off-by: Leon Romanovsky &lt;leonro@nvidia.com&gt;
Reviewed-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Link: https://patch.msgid.link/20260722-reference-count-underflow-in-target-v1-1-63ab664f12fd@nvidia.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>
When target_get_sess_cmd() fails during session shutdown because
percpu_ref_tryget_live() returns false, the command keeps the
se_cmd-&gt;cmd_cnt pointer that __target_init_cmd() assigned earlier
without owning a reference. Final release through
target_release_cmd_kref() then issues an unmatched percpu_ref_put().

Commit 8e288be8606a ("scsi: target: Pass in cmd counter to use during
cmd setup") moved the cmd_cnt assignment ahead of the reference
acquisition.  Clear se_cmd-&gt;cmd_cnt whenever the initial
target_get_sess_cmd() fails in target_init_cmd() and
target_submit_tmr(), so release performs exactly one matching put per
acquired reference.

Fixes: 8e288be8606a ("scsi: target: Pass in cmd counter to use during cmd setup")
Signed-off-by: Leon Romanovsky &lt;leonro@nvidia.com&gt;
Reviewed-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Link: https://patch.msgid.link/20260722-reference-count-underflow-in-target-v1-1-63ab664f12fd@nvidia.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: iblock: Fix wrong PR ops NULL check for PREEMPT/RELEASE</title>
<updated>2026-07-29T01:52:08+00:00</updated>
<author>
<name>TanZheng</name>
<email>tanzheng@kylinos.cn</email>
</author>
<published>2026-07-24T07:58:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=9c33222bd387312874fbe36ca8002e5c945b9653'/>
<id>9c33222bd387312874fbe36ca8002e5c945b9653</id>
<content type='text'>
In the iblock_execute_pr_out() function, PRO_PREEMPT,
PRO_PREEMPT_AND_ABORT, and PRO_RELEASE all perform callback capability
checks through ops-&gt;pr_clear. The error check allows unimplemented hooks
to pass through the gate, resulting dereferencing a NULL function
pointer.

Check whether the hooks that need to be called are supported.

Fixes: 394f81184882 ("scsi: target: Add block PR support to iblock")
Signed-off-by: TanZheng &lt;tanzheng@kylinos.cn&gt;
Reviewed-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Link: https://patch.msgid.link/20260724075850.280699-1-kensanya@163.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>
In the iblock_execute_pr_out() function, PRO_PREEMPT,
PRO_PREEMPT_AND_ABORT, and PRO_RELEASE all perform callback capability
checks through ops-&gt;pr_clear. The error check allows unimplemented hooks
to pass through the gate, resulting dereferencing a NULL function
pointer.

Check whether the hooks that need to be called are supported.

Fixes: 394f81184882 ("scsi: target: Add block PR support to iblock")
Signed-off-by: TanZheng &lt;tanzheng@kylinos.cn&gt;
Reviewed-by: Mike Christie &lt;michael.christie@oracle.com&gt;
Link: https://patch.msgid.link/20260724075850.280699-1-kensanya@163.com
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: core: Fix iSCSI ISID use-after-free in REGISTER AND MOVE</title>
<updated>2026-07-13T02:21:22+00:00</updated>
<author>
<name>Bryam Vargas</name>
<email>hexlabsecurity@proton.me</email>
</author>
<published>2026-06-10T04:22:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=fda6a1f3c3d7047b5ce5654487649c2daa738bfc'/>
<id>fda6a1f3c3d7047b5ce5654487649c2daa738bfc</id>
<content type='text'>
core_scsi3_emulate_pro_register_and_move() maps the PERSISTENT RESERVE OUT
parameter list with transport_kmap_data_sg() and parses the destination
TransportID with target_parse_pr_out_transport_id(). For an iSCSI
TransportID (FORMAT CODE 01b), iscsi_parse_pr_out_transport_id() returns
the ISID in iport_ptr as a raw pointer into that mapped buffer.

The function then unmaps the buffer with transport_kunmap_data_sg() before
dereferencing iport_ptr in strcmp(), __core_scsi3_locate_pr_reg() and
core_scsi3_alloc_registration(). When the parameter list spans more than
one page (PARAMETER LIST LENGTH &gt; 4096), transport_kmap_data_sg() uses
vmap() and transport_kunmap_data_sg() does vunmap(), so the kernel virtual
address backing iport_ptr is torn down and every subsequent dereference is
a use-after-free read of the unmapped region.

Keep the parameter list mapped until iport_ptr is no longer needed: drop
the early transport_kunmap_data_sg() and unmap once on the success path,
right before returning. The error paths already unmap through the existing
"if (buf) transport_kunmap_data_sg(cmd)" at the out: label, which now runs
on every post-map error exit because buf is no longer cleared early. Only
reads of the mapping happen while spinlocks are held; the map and unmap
calls remain outside any lock. The sibling caller
core_scsi3_decode_spec_i_port() already uses the buffer before unmapping it
and is left unchanged.

Fixes: 4949314c7283 ("target: Allow control CDBs with data &gt; 1 page")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas &lt;hexlabsecurity@proton.me&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: David Disseldorp &lt;ddiss@suse.de&gt;
Link: https://patch.msgid.link/20260610042245.35473-1-hexlabsecurity@proton.me
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>
core_scsi3_emulate_pro_register_and_move() maps the PERSISTENT RESERVE OUT
parameter list with transport_kmap_data_sg() and parses the destination
TransportID with target_parse_pr_out_transport_id(). For an iSCSI
TransportID (FORMAT CODE 01b), iscsi_parse_pr_out_transport_id() returns
the ISID in iport_ptr as a raw pointer into that mapped buffer.

The function then unmaps the buffer with transport_kunmap_data_sg() before
dereferencing iport_ptr in strcmp(), __core_scsi3_locate_pr_reg() and
core_scsi3_alloc_registration(). When the parameter list spans more than
one page (PARAMETER LIST LENGTH &gt; 4096), transport_kmap_data_sg() uses
vmap() and transport_kunmap_data_sg() does vunmap(), so the kernel virtual
address backing iport_ptr is torn down and every subsequent dereference is
a use-after-free read of the unmapped region.

Keep the parameter list mapped until iport_ptr is no longer needed: drop
the early transport_kunmap_data_sg() and unmap once on the success path,
right before returning. The error paths already unmap through the existing
"if (buf) transport_kunmap_data_sg(cmd)" at the out: label, which now runs
on every post-map error exit because buf is no longer cleared early. Only
reads of the mapping happen while spinlocks are held; the map and unmap
calls remain outside any lock. The sibling caller
core_scsi3_decode_spec_i_port() already uses the buffer before unmapping it
and is left unchanged.

Fixes: 4949314c7283 ("target: Allow control CDBs with data &gt; 1 page")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas &lt;hexlabsecurity@proton.me&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: David Disseldorp &lt;ddiss@suse.de&gt;
Link: https://patch.msgid.link/20260610042245.35473-1-hexlabsecurity@proton.me
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>scsi: target: Bound PR-OUT TransportID parsing to the received buffer</title>
<updated>2026-07-13T02:21:22+00:00</updated>
<author>
<name>Bryam Vargas</name>
<email>hexlabsecurity@proton.me</email>
</author>
<published>2026-06-11T18:42:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=d04a179085c262c9ed577d0a4cbc6482ff1fd9a3'/>
<id>d04a179085c262c9ed577d0a4cbc6482ff1fd9a3</id>
<content type='text'>
core_scsi3_decode_spec_i_port() and core_scsi3_emulate_register_and_move()
hand the raw PERSISTENT RESERVE OUT parameter buffer to
target_parse_pr_out_transport_id() without telling it how many bytes are
valid.  For an iSCSI TransportID (FORMAT CODE 01b),
iscsi_parse_pr_out_transport_id() locates the ",i,0x" ISID separator with
an unbounded strstr() (and on the error path prints the name with a further
unbounded "%s").  An initiator can submit a TransportID whose iSCSI name
contains neither a ",i,0x" substring nor a NUL terminator, filling the
parameter list to its end, so the scan runs off the end of the buffer.

When the parameter list spans more than one page the buffer is a multi-page
vmap (transport_kmap_data_sg()), so the over-read walks into the trailing
vmalloc guard page and oopses (KASAN: vmalloc-out-of-bounds in strstr).  It
is reachable by any fabric that delivers a PR OUT to a device exported
through an iSCSI TPG, including a guest via vhost-scsi.

Pass the number of received bytes down to the parser and validate the iSCSI
TransportID's own self-described length (ADDITIONAL LENGTH + 4) once, up
front: reject it if it is below the spc4r17 minimum or larger than the
received buffer, then bound the separator search, the ISID walk and the
name copy by that length.  This is the length check the callers already
perform after the parse (core_scsi3_decode_spec_i_port() compares tid_len
against tpdl, core_scsi3_emulate_register_and_move() validates it against
data_length), moved ahead of the scan.  Also drop the unbounded "%s" of the
unterminated name.

Add per-format explicit name-length checks before copying into i_str,
rather than silently truncating with min_t: for FORMAT CODE 00b reject if
the descriptor body (tid_len - 4 bytes) cannot fit in
i_str[TRANSPORT_IQN_LEN]; for FORMAT CODE 01b reject if the name portion
(from &amp;buf[4] up to the separator) cannot fit.  Both checks make the bounds
intent explicit at each format branch.

While here, also reject a FORMAT CODE 01b TransportID whose ",i,0x"
separator sits at the very end of the descriptor: that leaves an empty ISID
and points the returned port nexus pointer at buf + tid_len, one past the
descriptor, which the registration code (__core_scsi3_locate_pr_reg(),
__core_scsi3_alloc_registration()) then dereferences as the ISID string --
the same over-read of the parameter buffer for a malformed descriptor.

Fixes: c66ac9db8d4a ("[SCSI] target: Add LIO target core v4.0.0-rc6")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas &lt;hexlabsecurity@proton.me&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: David Disseldorp &lt;ddiss@suse.de&gt;
Link: https://patch.msgid.link/20260611-b4-disp-9f20739e-v6-1-f6630e2aae44@proton.me
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>
core_scsi3_decode_spec_i_port() and core_scsi3_emulate_register_and_move()
hand the raw PERSISTENT RESERVE OUT parameter buffer to
target_parse_pr_out_transport_id() without telling it how many bytes are
valid.  For an iSCSI TransportID (FORMAT CODE 01b),
iscsi_parse_pr_out_transport_id() locates the ",i,0x" ISID separator with
an unbounded strstr() (and on the error path prints the name with a further
unbounded "%s").  An initiator can submit a TransportID whose iSCSI name
contains neither a ",i,0x" substring nor a NUL terminator, filling the
parameter list to its end, so the scan runs off the end of the buffer.

When the parameter list spans more than one page the buffer is a multi-page
vmap (transport_kmap_data_sg()), so the over-read walks into the trailing
vmalloc guard page and oopses (KASAN: vmalloc-out-of-bounds in strstr).  It
is reachable by any fabric that delivers a PR OUT to a device exported
through an iSCSI TPG, including a guest via vhost-scsi.

Pass the number of received bytes down to the parser and validate the iSCSI
TransportID's own self-described length (ADDITIONAL LENGTH + 4) once, up
front: reject it if it is below the spc4r17 minimum or larger than the
received buffer, then bound the separator search, the ISID walk and the
name copy by that length.  This is the length check the callers already
perform after the parse (core_scsi3_decode_spec_i_port() compares tid_len
against tpdl, core_scsi3_emulate_register_and_move() validates it against
data_length), moved ahead of the scan.  Also drop the unbounded "%s" of the
unterminated name.

Add per-format explicit name-length checks before copying into i_str,
rather than silently truncating with min_t: for FORMAT CODE 00b reject if
the descriptor body (tid_len - 4 bytes) cannot fit in
i_str[TRANSPORT_IQN_LEN]; for FORMAT CODE 01b reject if the name portion
(from &amp;buf[4] up to the separator) cannot fit.  Both checks make the bounds
intent explicit at each format branch.

While here, also reject a FORMAT CODE 01b TransportID whose ",i,0x"
separator sits at the very end of the descriptor: that leaves an empty ISID
and points the returned port nexus pointer at buf + tid_len, one past the
descriptor, which the registration code (__core_scsi3_locate_pr_reg(),
__core_scsi3_alloc_registration()) then dereferences as the ISID string --
the same over-read of the parameter buffer for a malformed descriptor.

Fixes: c66ac9db8d4a ("[SCSI] target: Add LIO target core v4.0.0-rc6")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas &lt;hexlabsecurity@proton.me&gt;
Reviewed-by: John Garry &lt;john.g.garry@oracle.com&gt;
Reviewed-by: David Disseldorp &lt;ddiss@suse.de&gt;
Link: https://patch.msgid.link/20260611-b4-disp-9f20739e-v6-1-f6630e2aae44@proton.me
Signed-off-by: Martin K. Petersen &lt;martin.petersen@oracle.com&gt;
</pre>
</div>
</content>
</entry>
<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>
</feed>
