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.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Wei Jie Law <redacted>
---
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 d73002b2c21a..76c2d98b49df 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