* [PATCH net v2 0/2] net: usb: lan78xx: do not use uninitialized data after short reads @ 2026-10-18 6:17 Wei Jie Law 2026-10-18 6:17 ` [PATCH net v2 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law 2026-10-18 6:17 ` [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law 0 siblings, 2 replies; 6+ messages in thread From: Wei Jie Law @ 2026-10-18 6:17 UTC (permalink / raw) To: Thangaraj Samynathan, UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni Cc: Woojung Huh, netdev, linux-usb, linux-kernel, Wei Jie Law lan78xx_read_reg() and lan78xx_read_stats() accept a control transfer that returns fewer bytes than requested and then use the uninitialized rest of their kmalloc()ed buffers. A device that sends short replies can get stale heap contents used as the MAC address of the interface, and makes ethtool -S report them to unprivileged users, including kernel text and direct map pointers. Patch 2 makes both helpers fail on short reads. Patch 1 comes first so that a failing statistics read does not report uninitialized stack data instead. The bugs need a malicious or emulated USB device, which Documentation/process/threat-model.rst treats as a regular bug rather than a vulnerability, so they are posted publicly. Testing: the series builds without warnings (W=1) on net and passes checkpatch --strict. It applies unchanged to v6.12.105, where it was tested with a LAN7800 emulated by raw-gadget + dummy_hcd, booted with init_on_alloc=0: - Zero-length statistics replies. Before: 40 to 88 of the 235 ethtool -S counters are non-zero, including usb_api_blocking_completion() and direct map pointers. After: every read fails with -EIO and all counters stay zero. - 100 byte statistics replies. Before: 110 of the 235 counters are non-zero. With patch 1 only: 29 are, so the stale tail of the buffer still gets through. With both patches: the read fails with -EIO and all counters stay zero. - Zero-length RX_ADDRL/RX_ADDRH replies. Before: the MAC address differs on every probe, is programmed into the MAC filter and is used as the address of the interface. After: the probe fails with -EIO. Both bugs were found, and the patches written, with LLM assistance, hence the Assisted-by tags. Changes in v2 (review by Sashiko): - 2/2: the commit message now says that with patch 1 only a partial statistics reply (1 to 187 bytes) still leaks, and that patch 2 depends on patch 1; the MAC address paragraph no longer claims a write-back to RX_ADDRL/RX_ADDRH, which happens only for an invalid address. The cover letter gains a partial-reply test. No code change. Wei Jie Law (2): net: usb: lan78xx: do not update statistics after a failed read net: usb: lan78xx: reject short register and statistics reads drivers/net/usb/lan78xx.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) base-commit: 7ec48f396a1d89532c0537bc38b408b8c31ee37f -- 2.43.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net v2 1/2] net: usb: lan78xx: do not update statistics after a failed read 2026-10-18 6:17 [PATCH net v2 0/2] net: usb: lan78xx: do not use uninitialized data after short reads Wei Jie Law @ 2026-10-18 6:17 ` Wei Jie Law 2026-10-18 6:20 ` sashiko-bot 2026-10-18 6:17 ` [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law 1 sibling, 1 reply; 6+ messages in thread From: Wei Jie Law @ 2026-10-18 6:17 UTC (permalink / raw) To: Thangaraj Samynathan, UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni Cc: Woojung Huh, netdev, linux-usb, linux-kernel, Wei Jie Law, stable From: Wei Jie Law <98lawweijie@gmail.com> lan78xx_update_stats() reads the hardware counters into an on-stack struct lan78xx_statstage. If lan78xx_read_stats() fails, only the rollover check is skipped: the counters are still recomputed from the uninitialized stack buffer and stored in dev->stats.curr_stat, which is then reported to user space by ethtool -S. Keep the previous values when the read fails. Found by code review with LLM assistance. Tested together with the next patch, which makes short reads fail: with an emulated device, ethtool -S then keeps reporting the previous counters. Fixes: 20ff55655a93 ("lan78xx: handle statistics counter rollover") Cc: stable@vger.kernel.org Assisted-by: LLM --- drivers/net/usb/lan78xx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 5655941f1478..cb8204371f5c 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -789,11 +789,13 @@ static void lan78xx_update_stats(struct lan78xx_net *dev) mutex_lock(&dev->stats.access_lock); - if (lan78xx_read_stats(dev, &lan78xx_stats) > 0) + if (lan78xx_read_stats(dev, &lan78xx_stats) > 0) { lan78xx_check_stat_rollover(dev, &lan78xx_stats); - for (i = 0; i < (sizeof(lan78xx_stats) / (sizeof(u32))); i++) - data[i] = (u64)p[i] + ((u64)count[i] * ((u64)max[i] + 1)); + for (i = 0; i < (sizeof(lan78xx_stats) / (sizeof(u32))); i++) + data[i] = (u64)p[i] + + ((u64)count[i] * ((u64)max[i] + 1)); + } mutex_unlock(&dev->stats.access_lock); -- 2.43.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 1/2] net: usb: lan78xx: do not update statistics after a failed read 2026-10-18 6:17 ` [PATCH net v2 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law @ 2026-10-18 6:20 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-10-18 6:20 UTC (permalink / raw) To: Wei Jie Law; +Cc: linux-usb > From: Wei Jie Law <98lawweijie@gmail.com> > > lan78xx_update_stats() reads the hardware counters into an on-stack > struct lan78xx_statstage. If lan78xx_read_stats() fails, only the > rollover check is skipped: the counters are still recomputed from the > uninitialized stack buffer and stored in dev->stats.curr_stat, which is > then reported to user space by ethtool -S. > > Keep the previous values when the read fails. > > Found by code review with LLM assistance. Tested together with the next > patch, which makes short reads fail: with an emulated device, ethtool -S > then keeps reporting the previous counters. > > Fixes: 20ff55655a93 ("lan78xx: handle statistics counter rollover") > Cc: stable@vger.kernel.org > Assisted-by: LLM Sashiko has reviewed this patch and found no issues. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261018061734.19488-1-law.wei.jie@gt.tech.gov.sg?part=1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads 2026-10-18 6:17 [PATCH net v2 0/2] net: usb: lan78xx: do not use uninitialized data after short reads Wei Jie Law 2026-10-18 6:17 ` [PATCH net v2 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law @ 2026-10-18 6:17 ` Wei Jie Law 2026-10-18 6:20 ` sashiko-bot 2026-10-18 16:09 ` Andrew Lunn 1 sibling, 2 replies; 6+ messages in thread From: Wei Jie Law @ 2026-10-18 6:17 UTC (permalink / raw) To: Thangaraj Samynathan, UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni Cc: Woojung Huh, netdev, linux-usb, linux-kernel, Wei Jie Law, stable From: Wei Jie Law <98lawweijie@gmail.com> lan78xx_read_reg() and lan78xx_read_stats() read from the device into a freshly kmalloc()ed buffer, but only treat a negative return value from usb_control_msg() as an error. A device that answers with fewer bytes than requested leaves part or all of the buffer uninitialized, and those bytes are then used as the register value or the counters. With an emulated device on a kernel booted with init_on_alloc=0: - A reply to the statistics request that is shorter than the 188 byte counter block leaves the rest of the kmalloc-192 buffer stale, and ethtool -S, which needs no privileges, reports it. Before the previous patch, a zero-length reply was enough: one counter pair read back as 0xffffffff8a427800, the address of usb_api_blocking_completion(), next to several direct map pointers. With the previous patch a zero-length reply is already harmless, but a reply of 1 to 187 bytes still gets through. - A zero-length reply to the RX_ADDRL/RX_ADDRH reads in lan78xx_init_mac_address() turns uninitialized heap memory into the MAC address (12:85:1f:dc:2e:bd and e6:93:44:41:9b:9f on two probes). Both of those are valid unicast addresses, so they are used as they are: written to MAF_LO(0)/MAF_HI(0) and set as the address of the net device, where anyone can read it. Treat a short transfer as -EIO in both helpers. With this change the same device fails to probe with -EIO, and a short statistics reply fails with -EIO and, with the previous patch, leaves the counters unchanged. This patch needs the previous one. Without it, a failed statistics read would make lan78xx_update_stats() compute the counters from its uninitialized on-stack buffer, so the leak would move from the heap to the stack. Both patches are Cc: stable and should be backported together. Found by code review with LLM assistance and reproduced with an emulated USB device (raw-gadget + dummy_hcd). Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") Cc: stable@vger.kernel.org Assisted-by: LLM --- drivers/net/usb/lan78xx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index cb8204371f5c..e6be066349de 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -612,6 +612,9 @@ static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data) USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, buf, 4, USB_CTRL_GET_TIMEOUT); + if (ret >= 0 && ret != sizeof(*buf)) + ret = -EIO; + if (likely(ret >= 0)) { le32_to_cpus(buf); *data = *buf; @@ -695,6 +698,9 @@ static int lan78xx_read_stats(struct lan78xx_net *dev, (void *)stats, sizeof(*stats), USB_CTRL_SET_TIMEOUT); + if (ret >= 0 && ret != sizeof(*stats)) + ret = -EIO; + if (likely(ret >= 0)) { src = (u32 *)stats; dst = (u32 *)data; -- 2.43.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads 2026-10-18 6:17 ` [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law @ 2026-10-18 6:20 ` sashiko-bot 2026-10-18 16:09 ` Andrew Lunn 1 sibling, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-10-18 6:20 UTC (permalink / raw) To: Wei Jie Law; +Cc: linux-usb > From: Wei Jie Law <98lawweijie@gmail.com> > > lan78xx_read_reg() and lan78xx_read_stats() read from the device into > a freshly kmalloc()ed buffer, but only treat a negative return value > from usb_control_msg() as an error. A device that answers with fewer > bytes than requested leaves part or all of the buffer uninitialized, > and those bytes are then used as the register value or the counters. > > With an emulated device on a kernel booted with init_on_alloc=0: > > - A reply to the statistics request that is shorter than the 188 byte > counter block leaves the rest of the kmalloc-192 buffer stale, and > ethtool -S, which needs no privileges, reports it. Before the > previous patch, a zero-length reply was enough: one counter pair read > back as 0xffffffff8a427800, the address of > [ ... ] > emulated USB device (raw-gadget + dummy_hcd). > > Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") > Cc: stable@vger.kernel.org > Assisted-by: LLM Sashiko has reviewed this patch and found no issues. -- Sashiko AI review · https://sashiko.dev/#/patchset/20261018061734.19488-1-law.wei.jie@gt.tech.gov.sg?part=2 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads 2026-10-18 6:17 ` [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law 2026-10-18 6:20 ` sashiko-bot @ 2026-10-18 16:09 ` Andrew Lunn 1 sibling, 0 replies; 6+ messages in thread From: Andrew Lunn @ 2026-10-18 16:09 UTC (permalink / raw) To: Wei Jie Law Cc: Thangaraj Samynathan, UNGLinuxDriver, Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Woojung Huh, netdev, linux-usb, linux-kernel, Wei Jie Law, stable On Sun, Oct 18, 2026 at 02:17:34PM +0800, Wei Jie Law wrote: > From: Wei Jie Law <98lawweijie@gmail.com> > > lan78xx_read_reg() and lan78xx_read_stats() read from the device into > a freshly kmalloc()ed buffer, but only treat a negative return value > from usb_control_msg() as an error. A device that answers with fewer > bytes than requested leaves part or all of the buffer uninitialized, > and those bytes are then used as the register value or the counters. You are assuming reading registers can fail with sort reads. To be symmetric, don't you have to assume writes can also fail in the same way? Should lan78xx_write_reg() have a similar test? > With an emulated device on a kernel booted with init_on_alloc=0: > > - A reply to the statistics request that is shorter than the 188 byte > counter block leaves the rest of the kmalloc-192 buffer stale, and > ethtool -S, which needs no privileges, reports it. Before the > previous patch, a zero-length reply was enough: one counter pair read > back as 0xffffffff8a427800, the address of > usb_api_blocking_completion(), next to several direct map pointers. > With the previous patch a zero-length reply is already harmless, but > a reply of 1 to 187 bytes still gets through. > > - A zero-length reply to the RX_ADDRL/RX_ADDRH reads in > lan78xx_init_mac_address() turns uninitialized heap memory into the > MAC address (12:85:1f:dc:2e:bd and e6:93:44:41:9b:9f on two probes). > Both of those are valid unicast addresses, so they are used as they > are: written to MAF_LO(0)/MAF_HI(0) and set as the address of the > net device, where anyone can read it. If short reads can happen, bad things are expected to happen. No need for examples. > This patch needs the previous one. Without it, a failed statistics read > would make lan78xx_update_stats() compute the counters from its > uninitialized on-stack buffer, so the leak would move from the heap to > the stack. Both patches are Cc: stable and should be backported > together. This belongs below the --- so that is it not part of the commit message. Andrew --- pw-bot: cr ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-18 16:10 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-18 6:17 [PATCH net v2 0/2] net: usb: lan78xx: do not use uninitialized data after short reads Wei Jie Law 2026-10-18 6:17 ` [PATCH net v2 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law 2026-10-18 6:20 ` sashiko-bot 2026-10-18 6:17 ` [PATCH net v2 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law 2026-10-18 6:20 ` sashiko-bot 2026-10-18 16:09 ` Andrew Lunn
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox