On 20/11/2022 18:25, Marek Vasut wrote:
> On 11/20/22 16:29, Szymon Heidrich wrote:
>> On 20/11/2022 15:43, Marek Vasut wrote:
>>> On 11/17/22 12:50, Fabio Estevam wrote:
>>>> [Adding Lukasz and Marek]
>>>>
>>>> On Thu, Nov 17, 2022 at 6:50 AM Szymon Heidrich
>>>> <szymon.heidr...@gmail.com> wrote:
>>>>>
>>>>> Assure that the control endpoint buffer of size USB_BUFSIZ (4096)
>>>>> can not be overflown during handling of USB control transfer
>>>>> requests with wLength greater than USB_BUFSIZ.
>>>>>
>>>>> Signed-off-by: Szymon Heidrich <szymon.heidr...@gmail.com>
>>>>> ---
>>>>>    drivers/usb/gadget/composite.c | 11 +++++++++++
>>>>>    1 file changed, 11 insertions(+)
>>>>>
>>>>> diff --git a/drivers/usb/gadget/composite.c 
>>>>> b/drivers/usb/gadget/composite.c
>>>>> index 2a309e624e..cb89f6dca9 100644
>>>>> --- a/drivers/usb/gadget/composite.c
>>>>> +++ b/drivers/usb/gadget/composite.c
>>>>> @@ -1019,6 +1019,17 @@ composite_setup(struct usb_gadget *gadget, const 
>>>>> struct usb_ctrlrequest *ctrl)
>>>>>           u8                              endp;
>>>>>           struct usb_configuration        *c;
>>>>>
>>>>> +       if (w_length > USB_BUFSIZ) {
>>>>> +               if (ctrl->bRequestType & USB_DIR_IN) {
>>>>> +                       /* Cast away the const, we are going to overwrite 
>>>>> on purpose. */
>>>>> +                       __le16 *temp = (__le16 *)&ctrl->wLength;
>>>>> +                       *temp = cpu_to_le16(USB_BUFSIZ);
>>>>> +                       w_length = USB_BUFSIZ;
>>>
>>> Won't this end up sending corrupted packets in case they are longer than 
>>> USB_BUFSIZ ?
>>>
>>> Where do such long packets come from ?
>>>
>>> What is the test-case ?
>>
>> The USB host will not attempt to retrieve more than wLenght bytes during 
>> transfer phase.
>> If the device would erroneously attempt to provide more data it would result 
>> in an unexpected state.
>> In case of most implementations the buffer for endpoint 0 along with max 
>> control transfer is limited to 4096 bytes (USB_BUFSIZ for U-Boot and Linux 
>> kernel).
>> Still according to the USB specification wLength is two bytes an the device 
>> may receive requests with wLength larger than 4096 bytes e.g. in case of a 
>> custom/malicious USB host.
>> For example one may build libusb with MAX_CTRL_BUFFER_LENGTH altered to 
>> 0xffff and this will allow the host to send requests with wLength up to 
>> 0xffff.
>> In this case the original implementation may result in buffer overflows as 
>> in multiple locations a value directly derived from wLength is set as the 
>> transfer phase length.
>> With the change applied IN requests with wLength larger than USB_BUFSIZ will 
>> be trimmed to USB_BUFSIZ, otherwise the host would read wLength-USB_BUFSIZ 
>> past cdev->req->buf.
>> I am not aware of any cases where more than USB_BUFSIZ would be provided 
>> from a buffer other than cdev->req->buf. In case I missed such case please 
>> let me know.
> 
> Why shouldn't the patch do simple
> 
> w_length = min(w_length, USB_BUFSIZ);
> 
> ?

The composite_setup function in composite.c uses w_length but function specific 
setup functions are passed the struct usb_ctrlrequest *ctrl so both must be 
updated.
If only w_length is updated using min(w_length, USB_BUFSIZ) than function 
specific setup will still receive the original request including unaltered 
wLength so it 
may again return a number of bytes greater than buffer size resulting in an 
overflow.

Reply via email to