* [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
@ 2026-06-03 23:55 Samuel Moelius
2026-06-04 13:38 ` James Bottomley
0 siblings, 1 reply; 9+ messages in thread
From: Samuel Moelius @ 2026-06-03 23:55 UTC (permalink / raw)
To: James E.J. Bottomley
Cc: Samuel Moelius, Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
The tape setup path writes partition metadata one element past the
allocated tape_blocks array when a one-partition configuration is
selected.
That corrupts adjacent state during device initialization before any
command is issued.
Reject a declared multi-partition layout that has no space for partition
1, and initialize partition 1's marker only when partition 1 exists.
Assisted-by: Codex:gpt-5.5-cyber-preview
Signed-off-by: Samuel Moelius <sam.moelius@trailofbits.com>
---
Changes in v2
- Fixed handling of part_1_size == 0 case
drivers/scsi/scsi_debug.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 1515495fd9ea..edcc2f5f6977 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3661,12 +3661,18 @@ static int partition_tape(struct sdebug_dev_info *devip, int nbr_partitions,
if (part_0_size + part_1_size > TAPE_UNITS)
return -1;
+ if (nbr_partitions > 1 && part_1_size <= 0)
+ return -1;
devip->tape_eop[0] = part_0_size;
devip->tape_blocks[0]->fl_size = TAPE_BLOCK_EOD_FLAG;
devip->tape_eop[1] = part_1_size;
- devip->tape_blocks[1] = devip->tape_blocks[0] +
- devip->tape_eop[0];
- devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
+ if (nbr_partitions > 1) {
+ devip->tape_blocks[1] = devip->tape_blocks[0] +
+ devip->tape_eop[0];
+ devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
+ } else {
+ devip->tape_blocks[1] = NULL;
+ }
for (i = 0 ; i < TAPE_MAX_PARTITIONS; i++)
devip->tape_location[i] = 0;
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-03 23:55 [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds Samuel Moelius
@ 2026-06-04 13:38 ` James Bottomley
2026-06-04 14:52 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 18:33 ` Samuel Moelius
0 siblings, 2 replies; 9+ messages in thread
From: James Bottomley @ 2026-06-04 13:38 UTC (permalink / raw)
To: Samuel Moelius; +Cc: Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
> The tape setup path writes partition metadata one element past the
> allocated tape_blocks array when a one-partition configuration is
> selected.
>
> That corrupts adjacent state during device initialization before any
> command is issued.
I still don't get what the actual problem is. For a single partition
tape I can't see where scsi_debug would actually do anything with
tape_blocks[1]. What is it that you're seeing when using scsi_debug
that motivates this?
Regards,
James
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 13:38 ` James Bottomley
@ 2026-06-04 14:52 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 16:16 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 18:33 ` Samuel Moelius
1 sibling, 1 reply; 9+ messages in thread
From: "Kai Mäkisara (Kolumbus)" @ 2026-06-04 14:52 UTC (permalink / raw)
To: James Bottomley
Cc: Samuel Moelius, Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
> On 4. Jun 2026, at 16.38, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
>> The tape setup path writes partition metadata one element past the
>> allocated tape_blocks array when a one-partition configuration is
>> selected.
>>
>> That corrupts adjacent state during device initialization before any
>> command is issued.
>
> I still don't get what the actual problem is. For a single partition
> tape I can't see where scsi_debug would actually do anything with
> tape_blocks[1]. What is it that you're seeing when using scsi_debug
> that motivates this?
>
The code marks partition 1 as EOD and does not corrupt anything. The tape has partitions
until either EOD partition is encountered or TAPE_MAX_PARTITIONS is reached. I would
be very hesitant to remove this initialization.
Thanks,
Kai
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 14:52 ` "Kai Mäkisara (Kolumbus)"
@ 2026-06-04 16:16 ` "Kai Mäkisara (Kolumbus)"
0 siblings, 0 replies; 9+ messages in thread
From: "Kai Mäkisara (Kolumbus)" @ 2026-06-04 16:16 UTC (permalink / raw)
To: James Bottomley
Cc: Samuel Moelius, Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
> On 4. Jun 2026, at 17.52, Kai Mäkisara (Kolumbus) <kai.makisara@kolumbus.fi> wrote:
>
>
>
>> On 4. Jun 2026, at 16.38, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>>
>> On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
>>> The tape setup path writes partition metadata one element past the
>>> allocated tape_blocks array when a one-partition configuration is
>>> selected.
>>>
>>> That corrupts adjacent state during device initialization before any
>>> command is issued.
>>
>> I still don't get what the actual problem is. For a single partition
>> tape I can't see where scsi_debug would actually do anything with
>> tape_blocks[1]. What is it that you're seeing when using scsi_debug
>> that motivates this?
>>
> The code marks partition 1 as EOD and does not corrupt anything. The tape has partitions
> until either EOD partition is encountered or TAPE_MAX_PARTITIONS is reached. I would
> be very hesitant to remove this initialization.
>
I looked more carefully at the code:-) Each partition ends at EOD block. But I would still not like
to remove this initialization because, even if it is not necessary, it is harmless. There has been a
reason to do the initialization like that at some time. And the code is simpler as it is now.
Thanks,
Kai
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 13:38 ` James Bottomley
2026-06-04 14:52 ` "Kai Mäkisara (Kolumbus)"
@ 2026-06-04 18:33 ` Samuel Moelius
2026-06-04 19:14 ` "Kai Mäkisara (Kolumbus)"
1 sibling, 1 reply; 9+ messages in thread
From: Samuel Moelius @ 2026-06-04 18:33 UTC (permalink / raw)
To: James Bottomley; +Cc: Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
On Thu, Jun 4, 2026 at 9:38 AM James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
>
> On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
> > The tape setup path writes partition metadata one element past the
> > allocated tape_blocks array when a one-partition configuration is
> > selected.
> >
> > That corrupts adjacent state during device initialization before any
> > command is issued.
>
> I still don't get what the actual problem is. For a single partition
> tape I can't see where scsi_debug would actually do anything with
> tape_blocks[1]. What is it that you're seeing when using scsi_debug
> that motivates this?
The bug is a kernel OOB write. I can share a PoC if desired. The PoC
sends this SCSI command through /dev/sgN:
unsigned char format_medium[6] = { 0x04, 0, 0, 0, 0, 0 };
rc = sg_cmd(fd, "format_medium_one_partition",
format_medium, sizeof(format_medium));
Inside sg_cmd(), that becomes an SG_IO ioctl:
hdr.interface_id = 'S';
hdr.dxfer_direction = SG_DXFER_NONE;
hdr.cmd_len = cdb_len;
hdr.cmdp = cdb;
hdr.timeout = 10000;
ioctl(fd, SG_IO, &hdr);
For scsi_debug tape devices, opcode 0x04 dispatches here:
{ 0, 0x4, 0, DS_SSC, 0, resp_format_medium, NULL,
/* FORMAT MEDIUM (6) */ }
resp_format_medium() sees cmd[2] == 0, meaning the default
one-partition format path:
if (cmd[2] != 0) {
...
} else {
res = partition_tape(devip, 1, TAPE_UNITS, 0);
}
So partition_tape() is called with:
nbr_partitions = 1
part_0_size = TAPE_UNITS = 10000
part_1_size = 0
The unpatched code only checked total size:
if (part_0_size + part_1_size > TAPE_UNITS)
return -1;
That passes:
10000 + 0 == 10000
Then it initializes partition 0:
devip->tape_eop[0] = part_0_size;
devip->tape_blocks[0]->fl_size = TAPE_BLOCK_EOD_FLAG;
Then the bug: it initializes partition 1 even though there is only one
partition:
devip->tape_eop[1] = part_1_size;
devip->tape_blocks[1] = devip->tape_blocks[0] +
devip->tape_eop[0];
devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
Because devip->tape_eop[0] == 10000, this computes:
devip->tape_blocks[1] = devip->tape_blocks[0] + 10000
But the allocation has only 10000 elements. So this write is one
element past the allocation.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 18:33 ` Samuel Moelius
@ 2026-06-04 19:14 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 19:29 ` James Bottomley
0 siblings, 1 reply; 9+ messages in thread
From: "Kai Mäkisara (Kolumbus)" @ 2026-06-04 19:14 UTC (permalink / raw)
To: Samuel Moelius
Cc: James Bottomley, Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
> On 4. Jun 2026, at 21.33, Samuel Moelius <sam.moelius@trailofbits.com> wrote:
>
> On Thu, Jun 4, 2026 at 9:38 AM James Bottomley
> <James.Bottomley@hansenpartnership.com> wrote:
>>
>> On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
>>> The tape setup path writes partition metadata one element past the
>>> allocated tape_blocks array when a one-partition configuration is
>>> selected.
>>>
>>> That corrupts adjacent state during device initialization before any
>>> command is issued.
>>
>> I still don't get what the actual problem is. For a single partition
>> tape I can't see where scsi_debug would actually do anything with
>> tape_blocks[1]. What is it that you're seeing when using scsi_debug
>> that motivates this?
>
> The bug is a kernel OOB write. I can share a PoC if desired. The PoC
> sends this SCSI command through /dev/sgN:
>
> ...
> Then the bug: it initializes partition 1 even though there is only one
> partition:
>
> devip->tape_eop[1] = part_1_size;
> devip->tape_blocks[1] = devip->tape_blocks[0] +
> devip->tape_eop[0];
> devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
>
> Because devip->tape_eop[0] == 10000, this computes:
>
> devip->tape_blocks[1] = devip->tape_blocks[0] + 10000
>
> But the allocation has only 10000 elements. So this write is one
> element past the allocation.
OK. The bug is not initialization of the pointer but writing the fl_size using the
pointer. Good catch!
But the patch is not quite correct. If nbr_partitions == 2 and partition_1_size == 0,
it sets tape_nbr_partitions = 2 but does not initialize the second partition. This
will cause problems.
I think partition_tape() should return -1 if nbr_partitions > 0 && part_1_size == 0.
All call sites of partition_page() check for error, but the error case has never
happened. The code should be checked so that an error return does not cause
problems later.
Thanks,
Kai
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 19:14 ` "Kai Mäkisara (Kolumbus)"
@ 2026-06-04 19:29 ` James Bottomley
2026-06-04 19:41 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 23:47 ` Samuel Moelius
0 siblings, 2 replies; 9+ messages in thread
From: James Bottomley @ 2026-06-04 19:29 UTC (permalink / raw)
To: "Kai Mäkisara (Kolumbus)", Samuel Moelius
Cc: Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
On Thu, 2026-06-04 at 22:14 +0300, Kai Mäkisara (Kolumbus) wrote:
>
> > On 4. Jun 2026, at 21.33, Samuel Moelius
> > <sam.moelius@trailofbits.com> wrote:
> >
> > On Thu, Jun 4, 2026 at 9:38 AM James Bottomley
> > <James.Bottomley@hansenpartnership.com> wrote:
> > >
> > > On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
> > > > The tape setup path writes partition metadata one element past
> > > > the
> > > > allocated tape_blocks array when a one-partition configuration
> > > > is
> > > > selected.
> > > >
> > > > That corrupts adjacent state during device initialization
> > > > before any
> > > > command is issued.
> > >
> > > I still don't get what the actual problem is. For a single
> > > partition
> > > tape I can't see where scsi_debug would actually do anything with
> > > tape_blocks[1]. What is it that you're seeing when using
> > > scsi_debug
> > > that motivates this?
> >
> > The bug is a kernel OOB write. I can share a PoC if desired. The
> > PoC
> > sends this SCSI command through /dev/sgN:
> >
> > ...
>
> > Then the bug: it initializes partition 1 even though there is only
> > one
> > partition:
> >
> > devip->tape_eop[1] = part_1_size;
> > devip->tape_blocks[1] = devip->tape_blocks[0] +
> > devip->tape_eop[0];
> > devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
> >
> > Because devip->tape_eop[0] == 10000, this computes:
> >
> > devip->tape_blocks[1] = devip->tape_blocks[0] + 10000
> >
> > But the allocation has only 10000 elements. So this write is one
> > element past the allocation.
>
> OK. The bug is not initialization of the pointer but writing the
> fl_size using the pointer. Good catch!
Isn't the fix actually to allocate an extra block for the EOF:
@@ -6648,7 +6648,7 @@ static int scsi_debug_sdev_configure(struct scsi_device *sdp,
if (sdebug_ptype == TYPE_TAPE) {
if (!devip->tape_blocks[0]) {
devip->tape_blocks[0] =
- kzalloc_objs(struct tape_block, TAPE_UNITS);
+ kzalloc_objs(struct tape_block, TAPE_UNITS + 1);
if (!devip->tape_blocks[0])
return 1;
?
Regards,
James
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 19:29 ` James Bottomley
@ 2026-06-04 19:41 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 23:47 ` Samuel Moelius
1 sibling, 0 replies; 9+ messages in thread
From: "Kai Mäkisara (Kolumbus)" @ 2026-06-04 19:41 UTC (permalink / raw)
To: James Bottomley
Cc: Samuel Moelius, Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
> On 4. Jun 2026, at 22.29, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
>
> On Thu, 2026-06-04 at 22:14 +0300, Kai Mäkisara (Kolumbus) wrote:
>>
>>> On 4. Jun 2026, at 21.33, Samuel Moelius
>>> <sam.moelius@trailofbits.com> wrote:
>>>
>>> On Thu, Jun 4, 2026 at 9:38 AM James Bottomley
>>> <James.Bottomley@hansenpartnership.com> wrote:
>>>>
>>>> On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
>>>>> The tape setup path writes partition metadata one element past
>>>>> the
>>>>> allocated tape_blocks array when a one-partition configuration
>>>>> is
>>>>> selected.
>>>>>
>>>>> That corrupts adjacent state during device initialization
>>>>> before any
>>>>> command is issued.
>>>>
>>>> I still don't get what the actual problem is. For a single
>>>> partition
>>>> tape I can't see where scsi_debug would actually do anything with
>>>> tape_blocks[1]. What is it that you're seeing when using
>>>> scsi_debug
>>>> that motivates this?
>>>
>>> The bug is a kernel OOB write. I can share a PoC if desired. The
>>> PoC
>>> sends this SCSI command through /dev/sgN:
>>>
>>> ...
>>
>>> Then the bug: it initializes partition 1 even though there is only
>>> one
>>> partition:
>>>
>>> devip->tape_eop[1] = part_1_size;
>>> devip->tape_blocks[1] = devip->tape_blocks[0] +
>>> devip->tape_eop[0];
>>> devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
>>>
>>> Because devip->tape_eop[0] == 10000, this computes:
>>>
>>> devip->tape_blocks[1] = devip->tape_blocks[0] + 10000
>>>
>>> But the allocation has only 10000 elements. So this write is one
>>> element past the allocation.
>>
>> OK. The bug is not initialization of the pointer but writing the
>> fl_size using the pointer. Good catch!
>
> Isn't the fix actually to allocate an extra block for the EOF:
>
> @@ -6648,7 +6648,7 @@ static int scsi_debug_sdev_configure(struct scsi_device *sdp,
> if (sdebug_ptype == TYPE_TAPE) {
> if (!devip->tape_blocks[0]) {
> devip->tape_blocks[0] =
> - kzalloc_objs(struct tape_block, TAPE_UNITS);
> + kzalloc_objs(struct tape_block, TAPE_UNITS + 1);
> if (!devip->tape_blocks[0])
> return 1;
>
> ?
That came into my mind, too. But I considered it a workaround, not a real fix.
But after considering the other alternatives and possible problems that should be checked,
I think your suggestion is the best way. It solves tha OOB write, but does not change the code
paths.
Thanks,
Kai
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds
2026-06-04 19:29 ` James Bottomley
2026-06-04 19:41 ` "Kai Mäkisara (Kolumbus)"
@ 2026-06-04 23:47 ` Samuel Moelius
1 sibling, 0 replies; 9+ messages in thread
From: Samuel Moelius @ 2026-06-04 23:47 UTC (permalink / raw)
To: James Bottomley
Cc: Kai Mäkisara (Kolumbus),
Martin K. Petersen, open list:SCSI SUBSYSTEM, open list
On Thu, Jun 4, 2026 at 3:29 PM James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
>
> On Thu, 2026-06-04 at 22:14 +0300, Kai Mäkisara (Kolumbus) wrote:
> >
> > > On 4. Jun 2026, at 21.33, Samuel Moelius
> > > <sam.moelius@trailofbits.com> wrote:
> > >
> > > On Thu, Jun 4, 2026 at 9:38 AM James Bottomley
> > > <James.Bottomley@hansenpartnership.com> wrote:
> > > >
> > > > On Wed, 2026-06-03 at 23:55 +0000, Samuel Moelius wrote:
> > > > > The tape setup path writes partition metadata one element past
> > > > > the
> > > > > allocated tape_blocks array when a one-partition configuration
> > > > > is
> > > > > selected.
> > > > >
> > > > > That corrupts adjacent state during device initialization
> > > > > before any
> > > > > command is issued.
> > > >
> > > > I still don't get what the actual problem is. For a single
> > > > partition
> > > > tape I can't see where scsi_debug would actually do anything with
> > > > tape_blocks[1]. What is it that you're seeing when using
> > > > scsi_debug
> > > > that motivates this?
> > >
> > > The bug is a kernel OOB write. I can share a PoC if desired. The
> > > PoC
> > > sends this SCSI command through /dev/sgN:
> > >
> > > ...
> >
> > > Then the bug: it initializes partition 1 even though there is only
> > > one
> > > partition:
> > >
> > > devip->tape_eop[1] = part_1_size;
> > > devip->tape_blocks[1] = devip->tape_blocks[0] +
> > > devip->tape_eop[0];
> > > devip->tape_blocks[1]->fl_size = TAPE_BLOCK_EOD_FLAG;
> > >
> > > Because devip->tape_eop[0] == 10000, this computes:
> > >
> > > devip->tape_blocks[1] = devip->tape_blocks[0] + 10000
> > >
> > > But the allocation has only 10000 elements. So this write is one
> > > element past the allocation.
> >
> > OK. The bug is not initialization of the pointer but writing the
> > fl_size using the pointer. Good catch!
>
> Isn't the fix actually to allocate an extra block for the EOF:
>
> @@ -6648,7 +6648,7 @@ static int scsi_debug_sdev_configure(struct scsi_device *sdp,
> if (sdebug_ptype == TYPE_TAPE) {
> if (!devip->tape_blocks[0]) {
> devip->tape_blocks[0] =
> - kzalloc_objs(struct tape_block, TAPE_UNITS);
> + kzalloc_objs(struct tape_block, TAPE_UNITS + 1);
> if (!devip->tape_blocks[0])
> return 1;
I'll send a v3 that uses that approach.
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-06-04 23:47 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-03 23:55 [PATCH v2] scsi: scsi_debug: fix one-partition tape setup bounds Samuel Moelius
2026-06-04 13:38 ` James Bottomley
2026-06-04 14:52 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 16:16 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 18:33 ` Samuel Moelius
2026-06-04 19:14 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 19:29 ` James Bottomley
2026-06-04 19:41 ` "Kai Mäkisara (Kolumbus)"
2026-06-04 23:47 ` Samuel Moelius
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®