Linux USB
 help / color / mirror / Atom feed
* [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba
@ 2025-11-16  5:22 =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
  2025-11-16 12:07 ` gregkh
  0 siblings, 1 reply; 4+ messages in thread
From: =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?= @ 2025-11-16  5:22 UTC (permalink / raw)
  To: linux-usb; +Cc: gregkh

From c63dc814b5e51713222462e6bf27d7956a933834 Mon Sep 17 00:00:00 2001
From: Tianchu Chen <flynnnchen@tencent.com>
Date: Sun, 16 Nov 2025 12:46:18 +0800
Subject: [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba

Discovered by Atuin - Automated Vulnerability Discovery Engine.

new_pba comes from the status packet returned after each write.
A bogus device could report values beyond the block count derived
from info->capacity, letting the driver walk off the end of
pba_to_lba[] and corrupt heap memory.

Reject PBAs that exceed the computed block count and fail the
transfer so we avoid touching out-of-range mapping entries.

Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
---
 drivers/usb/storage/sddr55.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index b323f0a36..9d813727e 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -469,6 +469,12 @@ static int sddr55_write_data(struct us_data *us,
 		new_pba = (status[3] + (status[4] << 8) + (status[5] << 16))
 						  >> info->blockshift;
 
+		/* check if device-reported new_pba is out of range */
+		if (new_pba >= (info->capacity >> (info->blockshift + info->pageshift))) {
+			result = USB_STOR_TRANSPORT_FAILED;
+			goto leave;
+		}
+
 		/* check status for error */
 		if (status[0] == 0xff && status[1] == 0x4) {
 			info->pba_to_lba[new_pba] = BAD_BLOCK;
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba
  2025-11-16  5:22 [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
@ 2025-11-16 12:07 ` gregkh
  2025-11-16 13:15   ` =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
  0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2025-11-16 12:07 UTC (permalink / raw)
  To: flynnnchen(陈天楚); +Cc: linux-usb

On Sun, Nov 16, 2025 at 01:22:01PM +0800, flynnnchen(陈天楚) wrote:
> From c63dc814b5e51713222462e6bf27d7956a933834 Mon Sep 17 00:00:00 2001
> From: Tianchu Chen <flynnnchen@tencent.com>
> Date: Sun, 16 Nov 2025 12:46:18 +0800
> Subject: [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba

You can use git send-email to not have this show up in the body of the
email in the future :)

> Discovered by Atuin - Automated Vulnerability Discovery Engine.
> 
> new_pba comes from the status packet returned after each write.
> A bogus device could report values beyond the block count derived
> from info->capacity, letting the driver walk off the end of
> pba_to_lba[] and corrupt heap memory.
> 
> Reject PBAs that exceed the computed block count and fail the
> transfer so we avoid touching out-of-range mapping entries.
> 
> Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> ---
>  drivers/usb/storage/sddr55.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
> index b323f0a36..9d813727e 100644
> --- a/drivers/usb/storage/sddr55.c
> +++ b/drivers/usb/storage/sddr55.c
> @@ -469,6 +469,12 @@ static int sddr55_write_data(struct us_data *us,
>  		new_pba = (status[3] + (status[4] << 8) + (status[5] << 16))
>  						  >> info->blockshift;
>  
> +		/* check if device-reported new_pba is out of range */
> +		if (new_pba >= (info->capacity >> (info->blockshift + info->pageshift))) {
> +			result = USB_STOR_TRANSPORT_FAILED;
> +			goto leave;
> +		}

Any chance you tested this with real hardware?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Re: [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba
  2025-11-16 12:07 ` gregkh
@ 2025-11-16 13:15   ` =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
  2025-11-16 13:28     ` gregkh
  0 siblings, 1 reply; 4+ messages in thread
From: =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?= @ 2025-11-16 13:15 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb

On Sun, Nov 16, 2025 at 07:07:57AM -0500, gregkh wrote:

>On Sun, Nov 16, 2025 at 01:22:01PM +0800, flynnnchen(陈天楚) wrote:
>> Discovered by Atuin - Automated Vulnerability Discovery Engine.
>> 
>> new_pba comes from the status packet returned after each write.
>> A bogus device could report values beyond the block count derived
>> from info->capacity, letting the driver walk off the end of
>> pba_to_lba[] and corrupt heap memory.
>> 
>> Reject PBAs that exceed the computed block count and fail the
>> transfer so we avoid touching out-of-range mapping entries.
>> 
>> Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
>> ---
>>  drivers/usb/storage/sddr55.c | 6 ++++++
>>  1 file changed, 6 insertions(+)
>> 
>> diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
>> index b323f0a36..9d813727e 100644
>> --- a/drivers/usb/storage/sddr55.c
>> +++ b/drivers/usb/storage/sddr55.c
>> @@ -469,6 +469,12 @@ static int sddr55_write_data(struct us_data *us,
>>  		new_pba = (status[3] + (status[4] << 8) + (status[5] << 16))
>>  						  >> info->blockshift;
>>  
>> +		/* check if device-reported new_pba is out of range */
>> +		if (new_pba >= (info->capacity >> (info->blockshift + info->pageshift))) {
>> +			result = USB_STOR_TRANSPORT_FAILED;
>> +			goto leave;
>> +		}
>
>Any chance you tested this with real hardware?
>
>thanks,
>
>greg k-h


Unfortunately, I do not own the real hardware, and have not tested it on a
a real device.

Some of my thoughts on this patch, from static analysis:

Q: What if this code is called, before info->capacity is set?
A: If sddr55_write_data is called before sddr55_get_capacity,
info->capacity and pba_to_lba should both be 0, in the patched code it will
always fail, while in the original code it will cause NULL-deref.

Q: Is checking new_pba here essential in all cases?
A: Yes, in all the code path beneath it, new_pba is always used to index
the array, with no exception.

Q: What if device reports write success, and gives back an OOB new_pba?
A: For the patched code, it will fail the write transfer. In the original
one, it is very likely to fail as well, because:

		/* check that new_pba wasn't already being used */
		if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) {  <--- Very likely to fail here
			printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n",
				new_pba, info->pba_to_lba[new_pba]);
			info->fatal_error = 1;
			set_sense_info (3, 0x31, 0);
			result = USB_STOR_TRANSPORT_FAILED;
			goto leave;
		}

The original code OOB-reads info->pba_to_lba[new_pba], which is very
unlikely to equal to UNUSED_BLOCK (i32 0x3ff) by chance, thus the original
code will also fail the transfer in most cases.

From my understanding, the patched code solves the OOB issue, while being
aligned with the original behavior in most cases I have imagined.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Re: [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba
  2025-11-16 13:15   ` =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
@ 2025-11-16 13:28     ` gregkh
  0 siblings, 0 replies; 4+ messages in thread
From: gregkh @ 2025-11-16 13:28 UTC (permalink / raw)
  To: flynnnchen(陈天楚); +Cc: linux-usb

On Sun, Nov 16, 2025 at 09:15:05PM +0800, flynnnchen(陈天楚) wrote:
> On Sun, Nov 16, 2025 at 07:07:57AM -0500, gregkh wrote:
> 
> >On Sun, Nov 16, 2025 at 01:22:01PM +0800, flynnnchen(陈天楚) wrote:
> >> Discovered by Atuin - Automated Vulnerability Discovery Engine.
> >> 
> >> new_pba comes from the status packet returned after each write.
> >> A bogus device could report values beyond the block count derived
> >> from info->capacity, letting the driver walk off the end of
> >> pba_to_lba[] and corrupt heap memory.
> >> 
> >> Reject PBAs that exceed the computed block count and fail the
> >> transfer so we avoid touching out-of-range mapping entries.
> >> 
> >> Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> >> ---
> >>  drivers/usb/storage/sddr55.c | 6 ++++++
> >>  1 file changed, 6 insertions(+)
> >> 
> >> diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
> >> index b323f0a36..9d813727e 100644
> >> --- a/drivers/usb/storage/sddr55.c
> >> +++ b/drivers/usb/storage/sddr55.c
> >> @@ -469,6 +469,12 @@ static int sddr55_write_data(struct us_data *us,
> >>  		new_pba = (status[3] + (status[4] << 8) + (status[5] << 16))
> >>  						  >> info->blockshift;
> >>  
> >> +		/* check if device-reported new_pba is out of range */
> >> +		if (new_pba >= (info->capacity >> (info->blockshift + info->pageshift))) {
> >> +			result = USB_STOR_TRANSPORT_FAILED;
> >> +			goto leave;
> >> +		}
> >
> >Any chance you tested this with real hardware?
> >
> >thanks,
> >
> >greg k-h
> 
> 
> Unfortunately, I do not own the real hardware, and have not tested it on a
> a real device.
> 
> Some of my thoughts on this patch, from static analysis:
> 
> Q: What if this code is called, before info->capacity is set?
> A: If sddr55_write_data is called before sddr55_get_capacity,
> info->capacity and pba_to_lba should both be 0, in the patched code it will
> always fail, while in the original code it will cause NULL-deref.

But how can that out-of-order calling happen?

> Q: Is checking new_pba here essential in all cases?
> A: Yes, in all the code path beneath it, new_pba is always used to index
> the array, with no exception.

Fair enough :)

> Q: What if device reports write success, and gives back an OOB new_pba?
> A: For the patched code, it will fail the write transfer. In the original
> one, it is very likely to fail as well, because:
> 
> 		/* check that new_pba wasn't already being used */
> 		if (info->pba_to_lba[new_pba] != UNUSED_BLOCK) {  <--- Very likely to fail here
> 			printk(KERN_ERR "sddr55 error: new PBA %04X already in use for LBA %04X\n",
> 				new_pba, info->pba_to_lba[new_pba]);
> 			info->fatal_error = 1;
> 			set_sense_info (3, 0x31, 0);
> 			result = USB_STOR_TRANSPORT_FAILED;
> 			goto leave;
> 		}
> 
> The original code OOB-reads info->pba_to_lba[new_pba], which is very
> unlikely to equal to UNUSED_BLOCK (i32 0x3ff) by chance, thus the original
> code will also fail the transfer in most cases.
> 
> From my understanding, the patched code solves the OOB issue, while being
> aligned with the original behavior in most cases I have imagined.

Ok, seems sane, I'll be glad to take this, just wanted to be sure.  I
kind of doubt anyone has this hardware anymore anyway :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-11-16 13:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-16  5:22 [PATCH] usb: storage: sddr55: Reject out-of-bound new_pba =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
2025-11-16 12:07 ` gregkh
2025-11-16 13:15   ` =?gb18030?B?Zmx5bm5uY2hlbiizwszss/4p?=
2025-11-16 13:28     ` gregkh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox