Re: [PATCH] USB: hub: make sure stale buffers are not enumerated

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jul 24, 2023 at 02:40:57PM +0200, Oliver Neukum wrote:
> Quoting Alan Stern on why we cannot just check errors:
> 
> The operation carried out here is deliberately unsafe (for full-speed
> devices).  It is made before we know the actual maxpacket size for ep0,
> and as a result it might return an error code even when it works okay.
> This shouldn't happen, but a lot of USB hardware is unreliable.
> 
> Therefore we must not ignore the result merely because r < 0.  If we do
> that, the kernel might stop working with some devices.
> 
> He is absolutely right. However, we must make sure that in case
> we read nothing or a short answer, the buffer contains nothing
> that can be misinterpreted as a valid answer.
> So we have to zero it before we use it for IO.
> 
> Reported-by: liulongfang <liulongfang@xxxxxxxxxx>
> Signed-off-by: Oliver Neukum <oneukum@xxxxxxxx>
> ---
>  drivers/usb/core/hub.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index a739403a9e45..9772716925c3 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -4873,7 +4873,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
>  			}
>  
>  #define GET_DESCRIPTOR_BUFSIZE	64
> -			buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
> +			/* zeroed so we don't operate on a stale buffer on errors */
> +			buf = kzalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
>  			if (!buf) {
>  				retval = -ENOMEM;
>  				continue;

There is no need for kzalloc.

The only accesses we do to buf (besides feeding it to usb_control_msg) 
are to read buf->bMaxPacketSize0 and buf->bDescriptorType.  The only 
field that actually needs to be initialized is bMaxPacketSize0, and the 
code already sets it to 0 before calling usb_control_msg.  Furthermore, 
we don't try to read bDescriptorType if bMaxPacketSize0 is invalid after 
the I/O operation.

I guess if you really want to be safe, you could do:

-			udev->descriptor.bMaxPacketSize0 =
-					buf->bMaxPacketSize0;
+			if (r == 0)
+				udev->descriptor.bMaxPacketSize0 =
+						buf->bMaxPacketSize0;

at line 4918.  But even that's not necessary, since the following call 
to hub_port_reset doesn't use udev->descriptor.bMaxPacketSize0, so it 
doesn't matter if that field contains garbage.

Alan Stern



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux