* [PATCH net 0/2] net: usb: lan78xx: do not use uninitialized data after short reads
@ 2026-10-14 2:56 Wei Jie Law
2026-10-14 2:56 ` [PATCH net 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law
2026-10-14 2:56 ` [PATCH net 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law
0 siblings, 2 replies; 5+ messages in thread
From: Wei Jie Law @ 2026-10-14 2:56 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 written back to it as the MAC address, and makes
ethtool -S report them to unprivileged users, including kernel text and
direct map pointers, on systems with init_on_alloc=0.
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.
- Zero-length RX_ADDRL/RX_ADDRH replies. Before: the MAC address
differs on every probe and is written back to the device. After: the
probe fails with -EIO.
Both bugs were found, and the patches written, with LLM assistance,
hence the Assisted-by tags.
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: af32da41b0327b9c6a37856ba82b6760d6c8d10e
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net 1/2] net: usb: lan78xx: do not update statistics after a failed read
2026-10-14 2:56 [PATCH net 0/2] net: usb: lan78xx: do not use uninitialized data after short reads Wei Jie Law
@ 2026-10-14 2:56 ` Wei Jie Law
2026-10-14 3:04 ` sashiko-bot
2026-10-14 2:56 ` [PATCH net 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law
1 sibling, 1 reply; 5+ messages in thread
From: Wei Jie Law @ 2026-10-14 2:56 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
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
Signed-off-by: Wei Jie Law <law.wei.jie@gt.tech.gov.sg>
---
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] 5+ messages in thread
* [PATCH net 2/2] net: usb: lan78xx: reject short register and statistics reads
2026-10-14 2:56 [PATCH net 0/2] net: usb: lan78xx: do not use uninitialized data after short reads Wei Jie Law
2026-10-14 2:56 ` [PATCH net 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law
@ 2026-10-14 2:56 ` Wei Jie Law
2026-10-14 3:04 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Wei Jie Law @ 2026-10-14 2:56 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
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 zero-length reply to the statistics request makes ethtool -S, which
needs no privileges, report the stale contents of the kmalloc-192
buffer. One counter pair read back as 0xffffffff8a427800, the
address of usb_api_blocking_completion(), next to several direct
map pointers.
- 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),
which is then written back to the device in RX_ADDRL/RX_ADDRH and
MAF_LO(0)/MAF_HI(0).
Treat a short transfer as -EIO in both helpers. With this change the
same device fails to probe with -EIO, and with only the statistics
reply cut short all counters stay zero.
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
Signed-off-by: Wei Jie Law <law.wei.jie@gt.tech.gov.sg>
---
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] 5+ messages in thread
* Re: [PATCH net 1/2] net: usb: lan78xx: do not update statistics after a failed read
2026-10-14 2:56 ` [PATCH net 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law
@ 2026-10-14 3:04 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-10-14 3:04 UTC (permalink / raw)
To: Wei Jie Law; +Cc: linux-usb
> 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
> Signed-off-by: Wei Jie Law <law.wei.jie@gt.tech.gov.sg>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261014025602.26334-1-law.wei.jie@gt.tech.gov.sg?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net 2/2] net: usb: lan78xx: reject short register and statistics reads
2026-10-14 2:56 ` [PATCH net 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law
@ 2026-10-14 3:04 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-10-14 3:04 UTC (permalink / raw)
To: Wei Jie Law; +Cc: linux-usb
> 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 zero-length reply to the statistics request makes ethtool -S, which
> needs no privileges, report the stale contents of the kmalloc-192
> buffer. One counter pair read back as 0xffffffff8a427800, the
> address of usb_api_blocking_completion(), next to several direct
> map pointers.
>
> - A zero-length reply to the RX_ADDRL/RX_ADDRH reads in
> [ ... ]
>
> Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Wei Jie Law <law.wei.jie@gt.tech.gov.sg>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261014025602.26334-1-law.wei.jie@gt.tech.gov.sg?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-14 3:04 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 2:56 [PATCH net 0/2] net: usb: lan78xx: do not use uninitialized data after short reads Wei Jie Law
2026-10-14 2:56 ` [PATCH net 1/2] net: usb: lan78xx: do not update statistics after a failed read Wei Jie Law
2026-10-14 3:04 ` sashiko-bot
2026-10-14 2:56 ` [PATCH net 2/2] net: usb: lan78xx: reject short register and statistics reads Wei Jie Law
2026-10-14 3:04 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox