Message ID | 20250520113240.2369438-1-n.zhandarovich@fintech.ru |
---|---|
State | New |
Headers | show |
Series | [net-next] net: usb: aqc111: fix error handling of usbnet read calls | expand |
On Tue, May 20, 2025 at 02:32:39PM +0300, Nikita Zhandarovich wrote: > Syzkaller, courtesy of syzbot, identified an error (see report [1]) in > aqc111 driver, caused by incomplete sanitation of usb read calls' > results. This problem is quite similar to the one fixed in commit > 920a9fa27e78 ("net: asix: add proper error handling of usb read errors"). > > For instance, usbnet_read_cmd() may read fewer than 'size' bytes, > even if the caller expected the full amount, and aqc111_read_cmd() > will not check its result properly. As [1] shows, this may lead > to MAC address in aqc111_bind() being only partly initialized, > triggering KMSAN warnings. It looks like __ax88179_read_cmd() has the same issue? Please could you have a look around and see if more of the same problem exists. Are there any use cases where usbnet_read_cmd() can actually return less than size and it not being an error? Maybe this check for ret != size can be moved inside usbnet_read_cmd()? Andrew
On 5/21/25 2:34 PM, Andrew Lunn wrote: > On Tue, May 20, 2025 at 02:32:39PM +0300, Nikita Zhandarovich wrote: >> Syzkaller, courtesy of syzbot, identified an error (see report [1]) in >> aqc111 driver, caused by incomplete sanitation of usb read calls' >> results. This problem is quite similar to the one fixed in commit >> 920a9fa27e78 ("net: asix: add proper error handling of usb read errors"). >> >> For instance, usbnet_read_cmd() may read fewer than 'size' bytes, >> even if the caller expected the full amount, and aqc111_read_cmd() >> will not check its result properly. As [1] shows, this may lead >> to MAC address in aqc111_bind() being only partly initialized, >> triggering KMSAN warnings. > > It looks like __ax88179_read_cmd() has the same issue? Please could > you have a look around and see if more of the same problem exists. > > Are there any use cases where usbnet_read_cmd() can actually return > less than size and it not being an error? Maybe this check for ret != > size can be moved inside usbnet_read_cmd()? Judging from __usbnet_read_cmd() implementation, it's actually expected that such helper could return a partial copy. The centralized check could possibly break some users, I think check the return value on a per-device basis is safer. Side note: the patch should have targeted the 'net' tree as the blamed commit is present there, given we are now in the merge window and net-next PR is somewhat upcoming, applying it to net-next will yield the same result. /P
Hello: This patch was applied to netdev/net-next.git (main) by Paolo Abeni <pabeni@redhat.com>: On Tue, 20 May 2025 14:32:39 +0300 you wrote: > Syzkaller, courtesy of syzbot, identified an error (see report [1]) in > aqc111 driver, caused by incomplete sanitation of usb read calls' > results. This problem is quite similar to the one fixed in commit > 920a9fa27e78 ("net: asix: add proper error handling of usb read errors"). > > For instance, usbnet_read_cmd() may read fewer than 'size' bytes, > even if the caller expected the full amount, and aqc111_read_cmd() > will not check its result properly. As [1] shows, this may lead > to MAC address in aqc111_bind() being only partly initialized, > triggering KMSAN warnings. > > [...] Here is the summary with links: - [net-next] net: usb: aqc111: fix error handling of usbnet read calls https://git.kernel.org/netdev/net-next/c/405b0d610745 You are awesome, thank you!
diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c index ff5be2cbf17b..453a2cf82753 100644 --- a/drivers/net/usb/aqc111.c +++ b/drivers/net/usb/aqc111.c @@ -30,10 +30,13 @@ static int aqc111_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, ret = usbnet_read_cmd_nopm(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, data, size); - if (unlikely(ret < 0)) + if (unlikely(ret < size)) { + ret = ret < 0 ? ret : -ENODATA; + netdev_warn(dev->net, "Failed to read(0x%x) reg index 0x%04x: %d\n", cmd, index, ret); + } return ret; } @@ -46,10 +49,13 @@ static int aqc111_read_cmd(struct usbnet *dev, u8 cmd, u16 value, ret = usbnet_read_cmd(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, data, size); - if (unlikely(ret < 0)) + if (unlikely(ret < size)) { + ret = ret < 0 ? ret : -ENODATA; + netdev_warn(dev->net, "Failed to read(0x%x) reg index 0x%04x: %d\n", cmd, index, ret); + } return ret; }