| From 3dce4182dfe55296250fc77ec39161375bff6225 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 28 Oct 2025 22:26:57 +0530 |
| Subject: usb: raw-gadget: cap raw_io transfer length to KMALLOC_MAX_SIZE |
| |
| From: Gopi Krishna Menon <krishnagopi487@gmail.com> |
| |
| [ Upstream commit a5160af78be7fcf3ade6caab0a14e349560c96d7 ] |
| |
| The previous commit removed the PAGE_SIZE limit on transfer length of |
| raw_io buffer in order to avoid any problems with emulating USB devices |
| whose full configuration descriptor exceeds PAGE_SIZE in length. However |
| this also removes the upperbound on user supplied length, allowing very |
| large values to be passed to the allocator. |
| |
| syzbot on fuzzing the transfer length with very large value (1.81GB) |
| results in kmalloc() to fall back to the page allocator, which triggers |
| a kernel warning as the page allocator cannot handle allocations more |
| than MAX_PAGE_ORDER/KMALLOC_MAX_SIZE. |
| |
| Since there is no limit imposed on the size of buffer for both control |
| and non control transfers, cap the raw_io transfer length to |
| KMALLOC_MAX_SIZE and return -EINVAL for larger transfer length to |
| prevent any warnings from the page allocator. |
| |
| Fixes: 37b9dd0d114a ("usb: raw-gadget: do not limit transfer length") |
| Tested-by: syzbot+d8fd35fa6177afa8c92b@syzkaller.appspotmail.com |
| Reported-by: syzbot+d8fd35fa6177afa8c92b@syzkaller.appspotmail.com |
| Closes: https://lore.kernel.org/all/68fc07a0.a70a0220.3bf6c6.01ab.GAE@google.com/ |
| Signed-off-by: Gopi Krishna Menon <krishnagopi487@gmail.com> |
| Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com> |
| Link: https://patch.msgid.link/20251028165659.50962-1-krishnagopi487@gmail.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/usb/gadget/legacy/raw_gadget.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c |
| index d9cbbde8ff59d..a82c6e19572b6 100644 |
| --- a/drivers/usb/gadget/legacy/raw_gadget.c |
| +++ b/drivers/usb/gadget/legacy/raw_gadget.c |
| @@ -38,6 +38,7 @@ MODULE_LICENSE("GPL"); |
| |
| static DEFINE_IDA(driver_id_numbers); |
| #define DRIVER_DRIVER_NAME_LENGTH_MAX 32 |
| +#define USB_RAW_IO_LENGTH_MAX KMALLOC_MAX_SIZE |
| |
| #define RAW_EVENT_QUEUE_SIZE 16 |
| |
| @@ -619,6 +620,8 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, |
| return ERR_PTR(-EINVAL); |
| if (!usb_raw_io_flags_valid(io->flags)) |
| return ERR_PTR(-EINVAL); |
| + if (io->length > USB_RAW_IO_LENGTH_MAX) |
| + return ERR_PTR(-EINVAL); |
| if (get_from_user) |
| data = memdup_user(ptr + sizeof(*io), io->length); |
| else { |
| -- |
| 2.51.0 |
| |