Re: [PATCHv2] Check whether divisor is non-zero before division

From: Alan Stern
Date: Thu May 23 2024 - 10:15:26 EST


On Thu, May 23, 2024 at 09:58:21AM -0400, Alan Stern wrote:
> On Thu, May 23, 2024 at 05:26:08PM +0800, Shichao Lai wrote:
> > Since uzonesize may be zero, so judgements for non-zero are nessesary in both place.
> > Previous check is moved out of loop, and one more check is added in alauda_write_lba.
> >
> > Reported-by: xingwei lee <xrivendell7@xxxxxxxxx>
> > Reported-by: yue sun <samsun1006219@xxxxxxxxx>
> > Signed-off-by: Shichao Lai <shichaorai@xxxxxxxxx>
> > ---
> > drivers/usb/storage/alauda.c | 4 ++++
> > 1 file changed, 4 insertions(+)
> >
> > diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
> > index 115f05a6201a..a6e60ef5cb0d 100644
> > --- a/drivers/usb/storage/alauda.c
> > +++ b/drivers/usb/storage/alauda.c
> > @@ -818,6 +818,8 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
> > unsigned int blocksize = MEDIA_INFO(us).blocksize;
> > unsigned int lba_offset = lba % uzonesize;
> > unsigned int new_pba_offset;
> > + if (!uzonesize)
> > + return USB_STOR_TRANSPORT_ERROR;
> > unsigned int zone = lba / uzonesize;
> >
> > alauda_ensure_map_for_zone(us, zone);
> > @@ -923,6 +925,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
> > unsigned int uzonesize = MEDIA_INFO(us).uzonesize;
> > struct scatterlist *sg;
> > int result;
> > + if (!uzonesize)
> > + return USB_STOR_TRANSPORT_ERROR;
> >
> > /*
> > * Since we only read in one block at a time, we have to create
>
> This is definitely NOT the right way to fix the bug!
>
> uzonesize is set once, when the device is probed, in
> alauda_init_media(). That is where the check belongs; if uzonesize is 0
> then the function should print a warning and return
> USB_STOR_TRANSPORT_ERROR, because the device is unusable.
>
> It's probably a good idea to check pagesize, blocksize, and zonesize at
> the same time, even though none of them are used for any divisions.

Wait a minute. I just went through the code more carefully. It should
not be possible for uzonesize to be 0, because it is defined by:

MEDIA_INFO(us).uzonesize = ((1 << media_info->zoneshift) / 128) * 125;

where media_info->zoneshift is always a value between 8 and 12.

So the whole idea behind this patch is misguided. The real problem is
to find out why uzonesize ended up being 0.

(And it's not necessary to check pagesize, blocksize, or zonesize,
because none of them can ever be 0 either.)

Alan Stern