Hello, On 6/4/24 10:45, Alan Stern wrote: > On Tue, Jun 04, 2024 at 10:21:15AM -0700, Kees Cook wrote: >> On Tue, Jun 04, 2024 at 10:09:43AM -0700, Nikita Zhandarovich wrote: >>> Hi, >>> >>> On 6/4/24 07:15, Jiri Kosina wrote: >>>> On Tue, 4 Jun 2024, Kees Cook wrote: >>>> >>>>> This isn't the right solution. The problem is that hid_class_descriptor >>>>> is a flexible array but was sized as a single element fake flexible >>>>> array: >>>>> >>>>> struct hid_descriptor { >>>>> __u8 bLength; >>>>> __u8 bDescriptorType; >>>>> __le16 bcdHID; >>>>> __u8 bCountryCode; >>>>> __u8 bNumDescriptors; >>>>> >>>>> struct hid_class_descriptor desc[1]; >>>>> } __attribute__ ((packed)); >>>>> >>>>> This likely needs to be: >>>>> >>>>> struct hid_class_descriptor desc[] __counted_by(bNumDescriptors); >>>>> >>>>> And then check for any sizeof() uses of the struct that might have changed. Alan, I finally got around to preparing a revised version of the required patch and encountered a few issues. I could use some advice in this matter... If we change 'struct hid_descriptor' as you suggested, which does make sense, most occurrences of that type are easy enough to fix. 1) usbhid_parse() starts working properly if there are more than 1 descriptors, sizeof(struct hid_descriptor) may be turned into something crude but straightforward like sizeof(struct hid_descriptor) + sizeof(struct hid_class_descriptor). 2) 'hid_descriptor' in drivers/hid/hid-hyperv.c remains innocuous as well as only 1 descriptor expected there. My impression is only some small changes are needed there. However, the issue that stumps me is the following: static struct hid_descriptor hidg_desc in drivers/usb/gadget/function/f_hid.c relies on a static nature of that one descriptor. hidg_desc ends up being used elsewhere, in other static structures. Basically, using __counted_by requires a lot of changes, as I see it, out of scope of merely closing an UBSAN error. Is this approach still worthy pursuing or should I look into some neater solution? Best regards, Nikita >>>> >>>> Ah, you are of course right, not sure what I was thinking. Thanks a lot >>>> for catching my brainfart. >>>> >>>> I am dropping the patch for now; Nikita, will you please send a refreshed >>>> one? >>>> >>> >>> Thanks for catching my mistake. >>> >>> I'll gladly send a revised version, hoping to do it very soon. >> >> I spent a little more time looking at this, and I'm not sure I >> understand where the actual space for the descriptors comes from? >> There's interface->extra that is being parsed, and effectively >> hid_descriptor is being mapped into it, but it uses "sizeof(struct >> hid_descriptor)" for the limit. > > That's a lower limit, not an upper limit. The hid_descriptor must > include at least one hid_class_descriptor, but it can include more. > That's what the min_t() calculation of num_descriptors is meant to > figure out. > >> Is more than 1 descriptor expected to >> work correctly? > > More than one hid_class_descriptor -- yes. > >> Or is the limit being ignored? I'm a bit confused by >> this code... > > Does this explain it? > > Alan Stern