* [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths
@ 2026-06-11 12:30 Michael Bommarito
2026-06-11 12:30 ` [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it Michael Bommarito
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Michael Bommarito @ 2026-06-11 12:30 UTC (permalink / raw)
To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
Cc: xen-devel, linux-scsi, stable, linux-kernel
scsiback_get_pend_req() hands a pvSCSI frontend request a session tag and
a zeroed se_cmd. Two error paths that run before the command completes
through the target core mishandle that command and leak (or, in one case,
underflow) the tag.
Impact: a pvSCSI guest can exhaust a LUN's per-session command tag pool,
stopping the LUN, via crafted ring requests; for the first case the
refcount underflow also panics the host under panic_on_warn.
Patch 1 fixes scsiback_do_cmd_fn(): on a failed grant map and on an
unknown request type the never-initialised command (cmd_kref == 0) is
freed with transport_generic_free_cmd(), which underflows the zero
refcount and leaks the tag.
Patch 2 fixes scsiback_device_action(): when target_submit_tmr() fails the
err: path frees nothing. transport_generic_free_cmd() cannot be used there
either, since the command is initialised by then and se_tmr_req has already
been freed on one error sub-path.
Both paths go through one helper that returns just the tag.
Patch 1's underflow was reproduced on a Xen dom0 (guest to host, with a
panic_on_warn host panic); with the series applied the same request is
handled with no underflow.
Michael Bommarito (2):
xen/scsiback: free unsubmitted command instead of double-putting it
xen/scsiback: free the command tag on the TMR submit-failure path
drivers/xen/xen-scsiback.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it
2026-06-11 12:30 [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Michael Bommarito
@ 2026-06-11 12:30 ` Michael Bommarito
2026-06-15 15:14 ` Juergen Gross
2026-06-11 12:30 ` [PATCH 2/2] xen/scsiback: free the command tag on the TMR submit-failure path Michael Bommarito
2026-06-16 2:00 ` [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Martin K. Petersen
2 siblings, 1 reply; 6+ messages in thread
From: Michael Bommarito @ 2026-06-11 12:30 UTC (permalink / raw)
To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
Cc: xen-devel, linux-scsi, stable, linux-kernel
scsiback_get_pend_req() obtains a command tag and returns a
vscsibk_pend whose embedded se_cmd has only been memset to 0, so
its cmd_kref is 0; the se_cmd is initialised (kref_init() via
target_init_cmd()) only later, in scsiback_cmd_exec(), on the
successful VSCSIIF_ACT_SCSI_CDB path. The two error paths in
scsiback_do_cmd_fn() taken before the command is submitted -- a
failed scsiback_gnttab_data_map() and an unknown ring_req.act --
call transport_generic_free_cmd(&pending_req->se_cmd, 0), which
kref_put()s a refcount of 0. That underflows it ("refcount_t:
underflow; use-after-free") and, as the release function is not
run, leaks the command tag.
Impact: a pvSCSI guest can leak every command tag of a LUN's
session, stopping the LUN, by submitting requests with a bad
grant reference or an unknown request type; under panic_on_warn
the refcount underflow panics the host.
Add a helper that just returns the tag with target_free_tag() and
sends the error response. It frees the tag while the v2p reference
still pins the session, and snapshots the response fields
beforehand because freeing the tag can let another ring reuse the
pending_req slot.
Fixes: 2dbcdf33dbf6 ("xen-scsiback: Convert to percpu_ida tag allocation")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
Reproduced on a Xen dom0 (Linux 6.1.y) exporting a pvSCSI LUN to a guest.
A frontend that sends a single ring request with an unknown action type
drives scsiback_do_cmd_fn() into transport_generic_free_cmd() on the
never-initialised command and logs
refcount_t: underflow; use-after-free
WARNING: ... refcount_warn_saturate
transport_generic_free_cmd+0x... [target_core_mod]
scsiback_do_cmd_fn+0x... [xen_scsiback]
scsiback_irq_fn+0x... [xen_scsiback]
from the vscsiif IRQ thread, and panics the dom0 under panic_on_warn. The
failed grant-map path reaches the same free. With this patch the same
request is answered with DID_ERROR and the tag is returned, with no
underflow. These error paths are unchanged since 2dbcdf33dbf6, so mainline
is affected identically.
drivers/xen/xen-scsiback.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index e33f95c91b096..f324732eba7f8 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -611,6 +611,25 @@ static void scsiback_disconnect(struct vscsibk_info *info)
xenbus_unmap_ring_vfree(info->dev, info->ring.sring);
}
+/*
+ * Send the error response for a request that did not reach the target core
+ * and return its tag. Free the tag before the response drops the v2p
+ * reference that keeps the session alive, and snapshot what the response
+ * needs since returning the tag can let the slot be reused.
+ */
+static void scsiback_resp_and_free(struct vscsibk_pend *pending_req,
+ int32_t result)
+{
+ struct vscsibk_info *info = pending_req->info;
+ struct v2p_entry *v2p = pending_req->v2p;
+ struct se_session *se_sess = v2p->tpg->tpg_nexus->tvn_se_sess;
+ u16 rqid = pending_req->rqid;
+
+ target_free_tag(se_sess, &pending_req->se_cmd);
+ scsiback_send_response(info, NULL, result, 0, rqid);
+ kref_put(&v2p->kref, scsiback_free_translation_entry);
+}
+
static void scsiback_device_action(struct vscsibk_pend *pending_req,
enum tcm_tmreq_table act, int tag)
{
@@ -792,9 +811,8 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info,
case VSCSIIF_ACT_SCSI_CDB:
if (scsiback_gnttab_data_map(&ring_req, pending_req)) {
scsiback_fast_flush_area(pending_req);
- scsiback_do_resp_with_sense(NULL,
- DID_ERROR << 16, 0, pending_req);
- transport_generic_free_cmd(&pending_req->se_cmd, 0);
+ scsiback_resp_and_free(pending_req,
+ DID_ERROR << 16);
} else {
scsiback_cmd_exec(pending_req);
}
@@ -808,9 +826,7 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info,
break;
default:
pr_err_ratelimited("invalid request\n");
- scsiback_do_resp_with_sense(NULL, DID_ERROR << 16, 0,
- pending_req);
- transport_generic_free_cmd(&pending_req->se_cmd, 0);
+ scsiback_resp_and_free(pending_req, DID_ERROR << 16);
break;
}
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] xen/scsiback: free the command tag on the TMR submit-failure path
2026-06-11 12:30 [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Michael Bommarito
2026-06-11 12:30 ` [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it Michael Bommarito
@ 2026-06-11 12:30 ` Michael Bommarito
2026-06-15 15:14 ` Juergen Gross
2026-06-16 2:00 ` [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Martin K. Petersen
2 siblings, 1 reply; 6+ messages in thread
From: Michael Bommarito @ 2026-06-11 12:30 UTC (permalink / raw)
To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
Cc: xen-devel, linux-scsi, stable, linux-kernel
scsiback_device_action() obtains a command tag in
scsiback_get_pend_req() and submits a task-management request with
target_submit_tmr(). When target_submit_tmr() fails it returns < 0
and scsiback jumps to the err: label, which sends a response but
frees nothing, leaking the tag.
Impact: a pvSCSI guest can leak the command tags of a LUN's
session, stopping the LUN, by issuing VSCSIIF_ACT_SCSI_ABORT or
RESET requests whenever target_submit_tmr() fails.
transport_generic_free_cmd() cannot be used here. By the time
target_submit_tmr() returns an error it has already run
__target_init_cmd() (so se_cmd->cmd_kref is one, not zero), and on
its target_get_sess_cmd() error path it has freed se_cmd->se_tmr_req
via core_tmr_release_req() while leaving SCF_SCSI_TMR_CDB set and
the pointer dangling. Letting the command release run
target_free_cmd_mem() would then double-free se_tmr_req.
Use the same helper, which returns just the tag, on this path too.
Fixes: 2dbcdf33dbf6 ("xen-scsiback: Convert to percpu_ida tag allocation")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/xen/xen-scsiback.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index f324732eba7f8..c7036e0e41bda 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -658,7 +658,7 @@ static void scsiback_device_action(struct vscsibk_pend *pending_req,
return;
err:
- scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
+ scsiback_resp_and_free(pending_req, err);
}
/*
--
2.53.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it
2026-06-11 12:30 ` [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it Michael Bommarito
@ 2026-06-15 15:14 ` Juergen Gross
0 siblings, 0 replies; 6+ messages in thread
From: Juergen Gross @ 2026-06-15 15:14 UTC (permalink / raw)
To: Michael Bommarito, Stefano Stabellini, Oleksandr Tyshchenko
Cc: xen-devel, linux-scsi, stable, linux-kernel
[-- Attachment #1.1.1: Type: text/plain, Size: 1549 bytes --]
On 11.06.26 14:30, Michael Bommarito wrote:
> scsiback_get_pend_req() obtains a command tag and returns a
> vscsibk_pend whose embedded se_cmd has only been memset to 0, so
> its cmd_kref is 0; the se_cmd is initialised (kref_init() via
> target_init_cmd()) only later, in scsiback_cmd_exec(), on the
> successful VSCSIIF_ACT_SCSI_CDB path. The two error paths in
> scsiback_do_cmd_fn() taken before the command is submitted -- a
> failed scsiback_gnttab_data_map() and an unknown ring_req.act --
> call transport_generic_free_cmd(&pending_req->se_cmd, 0), which
> kref_put()s a refcount of 0. That underflows it ("refcount_t:
> underflow; use-after-free") and, as the release function is not
> run, leaks the command tag.
>
> Impact: a pvSCSI guest can leak every command tag of a LUN's
> session, stopping the LUN, by submitting requests with a bad
> grant reference or an unknown request type; under panic_on_warn
> the refcount underflow panics the host.
>
> Add a helper that just returns the tag with target_free_tag() and
> sends the error response. It frees the tag while the v2p reference
> still pins the session, and snapshots the response fields
> beforehand because freeing the tag can let another ring reuse the
> pending_req slot.
>
> Fixes: 2dbcdf33dbf6 ("xen-scsiback: Convert to percpu_ida tag allocation")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] xen/scsiback: free the command tag on the TMR submit-failure path
2026-06-11 12:30 ` [PATCH 2/2] xen/scsiback: free the command tag on the TMR submit-failure path Michael Bommarito
@ 2026-06-15 15:14 ` Juergen Gross
0 siblings, 0 replies; 6+ messages in thread
From: Juergen Gross @ 2026-06-15 15:14 UTC (permalink / raw)
To: Michael Bommarito, Stefano Stabellini, Oleksandr Tyshchenko
Cc: xen-devel, linux-scsi, stable, linux-kernel
[-- Attachment #1.1.1: Type: text/plain, Size: 1337 bytes --]
On 11.06.26 14:30, Michael Bommarito wrote:
> scsiback_device_action() obtains a command tag in
> scsiback_get_pend_req() and submits a task-management request with
> target_submit_tmr(). When target_submit_tmr() fails it returns < 0
> and scsiback jumps to the err: label, which sends a response but
> frees nothing, leaking the tag.
>
> Impact: a pvSCSI guest can leak the command tags of a LUN's
> session, stopping the LUN, by issuing VSCSIIF_ACT_SCSI_ABORT or
> RESET requests whenever target_submit_tmr() fails.
>
> transport_generic_free_cmd() cannot be used here. By the time
> target_submit_tmr() returns an error it has already run
> __target_init_cmd() (so se_cmd->cmd_kref is one, not zero), and on
> its target_get_sess_cmd() error path it has freed se_cmd->se_tmr_req
> via core_tmr_release_req() while leaving SCF_SCSI_TMR_CDB set and
> the pointer dangling. Letting the command release run
> target_free_cmd_mem() would then double-free se_tmr_req.
>
> Use the same helper, which returns just the tag, on this path too.
>
> Fixes: 2dbcdf33dbf6 ("xen-scsiback: Convert to percpu_ida tag allocation")
> Cc: stable@vger.kernel.org
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Juergen
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths
2026-06-11 12:30 [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Michael Bommarito
2026-06-11 12:30 ` [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it Michael Bommarito
2026-06-11 12:30 ` [PATCH 2/2] xen/scsiback: free the command tag on the TMR submit-failure path Michael Bommarito
@ 2026-06-16 2:00 ` Martin K. Petersen
2 siblings, 0 replies; 6+ messages in thread
From: Martin K. Petersen @ 2026-06-16 2:00 UTC (permalink / raw)
To: Michael Bommarito
Cc: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko,
xen-devel, linux-scsi, stable, linux-kernel
Michael,
> scsiback_get_pend_req() hands a pvSCSI frontend request a session tag
> and a zeroed se_cmd. Two error paths that run before the command
> completes through the target core mishandle that command and leak (or,
> in one case, underflow) the tag.
Applied to 7.2/scsi-staging, thanks!
--
Martin K. Petersen
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-06-16 2:01 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-11 12:30 [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Michael Bommarito
2026-06-11 12:30 ` [PATCH 1/2] xen/scsiback: free unsubmitted command instead of double-putting it Michael Bommarito
2026-06-15 15:14 ` Juergen Gross
2026-06-11 12:30 ` [PATCH 2/2] xen/scsiback: free the command tag on the TMR submit-failure path Michael Bommarito
2026-06-15 15:14 ` Juergen Gross
2026-06-16 2:00 ` [PATCH 0/2] xen/scsiback: fix command-tag handling on pre-completion error paths Martin K. Petersen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox