Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lan743x: fix for potential NULL pointer dereference with bare card

This is the 3rd revision of the patch fix for potential null pointer dereference
with lan743x card.

The simpliest way to reproduce: boot with bare lan743x and issue "ethtool ethN"
commant where ethN is the interface with lan743x card. Example:

$ sudo ethtool eth7
dmesg:
[ 103.510336] BUG: kernel NULL pointer dereference, address: 0000000000000340
...
[ 103.510836] RIP: 0010:phy_ethtool_get_wol+0x5/0x30 [libphy]
...
[ 103.511629] Call Trace:
[ 103.511666] lan743x_ethtool_get_wol+0x21/0x40 [lan743x]
[ 103.511724] dev_ethtool+0x1507/0x29d0
[ 103.511769] ? avc_has_extended_perms+0x17f/0x440
[ 103.511820] ? tomoyo_init_request_info+0x84/0x90
[ 103.511870] ? tomoyo_path_number_perm+0x68/0x1e0
[ 103.511919] ? tty_insert_flip_string_fixed_flag+0x82/0xe0
[ 103.511973] ? inet_ioctl+0x187/0x1d0
[ 103.512016] dev_ioctl+0xb5/0x560
[ 103.512055] sock_do_ioctl+0xa0/0x140
[ 103.512098] sock_ioctl+0x2cb/0x3c0
[ 103.512139] __x64_sys_ioctl+0x84/0xc0
[ 103.512183] do_syscall_64+0x33/0x80
[ 103.512224] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 103.512274] RIP: 0033:0x7f54a9cba427
...

Previous versions can be found at:
v1:
initial version
https://lkml.org/lkml/2020/10/28/921

v2:
do not return from lan743x_ethtool_set_wol if netdev->phydev == NULL, just skip
the call of phy_ethtool_set_wol() instead.
https://lkml.org/lkml/2020/10/31/380

v3:
in function lan743x_ethtool_set_wol:
use ternary operator instead of if-else sentence (review by Markus Elfring)
return -ENETDOWN insted of -EIO (review by Andrew Lunn)

Signed-off-by: Sergej Bauer <sbauer@blackbox.su>

Link: https://lore.kernel.org/r/20201101223556.16116-1-sbauer@blackbox.su
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Sergej Bauer and committed by
Jakub Kicinski
e9e13b6a 870f531e

+5 -4
+5 -4
drivers/net/ethernet/microchip/lan743x_ethtool.c
··· 780 780 781 781 wol->supported = 0; 782 782 wol->wolopts = 0; 783 - phy_ethtool_get_wol(netdev->phydev, wol); 783 + 784 + if (netdev->phydev) 785 + phy_ethtool_get_wol(netdev->phydev, wol); 784 786 785 787 wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | 786 788 WAKE_MAGIC | WAKE_PHY | WAKE_ARP; ··· 811 809 812 810 device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts); 813 811 814 - phy_ethtool_set_wol(netdev->phydev, wol); 815 - 816 - return 0; 812 + return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol) 813 + : -ENETDOWN; 817 814 } 818 815 #endif /* CONFIG_PM */ 819 816