From: Sasha Levin Date: Fri, 8 Mar 2024 17:00:19 +0000 (-0500) Subject: Fixes for 4.19 X-Git-Tag: v6.8.1~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=695d3763b312af0dcb6a2f0e8db63081c8da36e3;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch b/queue-4.19/geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch new file mode 100644 index 00000000000..9adbf3c4d3b --- /dev/null +++ b/queue-4.19/geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch @@ -0,0 +1,139 @@ +From 255e6c79af3a3427936fa4dd63eada642ba67c34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Feb 2024 13:11:52 +0000 +Subject: geneve: make sure to pull inner header in geneve_rx() + +From: Eric Dumazet + +[ Upstream commit 1ca1ba465e55b9460e4e75dec9fff31e708fec74 ] + +syzbot triggered a bug in geneve_rx() [1] + +Issue is similar to the one I fixed in commit 8d975c15c0cd +("ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv()") + +We have to save skb->network_header in a temporary variable +in order to be able to recompute the network_header pointer +after a pskb_inet_may_pull() call. + +pskb_inet_may_pull() makes sure the needed headers are in skb->head. + +[1] +BUG: KMSAN: uninit-value in IP_ECN_decapsulate include/net/inet_ecn.h:302 [inline] + BUG: KMSAN: uninit-value in geneve_rx drivers/net/geneve.c:279 [inline] + BUG: KMSAN: uninit-value in geneve_udp_encap_recv+0x36f9/0x3c10 drivers/net/geneve.c:391 + IP_ECN_decapsulate include/net/inet_ecn.h:302 [inline] + geneve_rx drivers/net/geneve.c:279 [inline] + geneve_udp_encap_recv+0x36f9/0x3c10 drivers/net/geneve.c:391 + udp_queue_rcv_one_skb+0x1d39/0x1f20 net/ipv4/udp.c:2108 + udp_queue_rcv_skb+0x6ae/0x6e0 net/ipv4/udp.c:2186 + udp_unicast_rcv_skb+0x184/0x4b0 net/ipv4/udp.c:2346 + __udp4_lib_rcv+0x1c6b/0x3010 net/ipv4/udp.c:2422 + udp_rcv+0x7d/0xa0 net/ipv4/udp.c:2604 + ip_protocol_deliver_rcu+0x264/0x1300 net/ipv4/ip_input.c:205 + ip_local_deliver_finish+0x2b8/0x440 net/ipv4/ip_input.c:233 + NF_HOOK include/linux/netfilter.h:314 [inline] + ip_local_deliver+0x21f/0x490 net/ipv4/ip_input.c:254 + dst_input include/net/dst.h:461 [inline] + ip_rcv_finish net/ipv4/ip_input.c:449 [inline] + NF_HOOK include/linux/netfilter.h:314 [inline] + ip_rcv+0x46f/0x760 net/ipv4/ip_input.c:569 + __netif_receive_skb_one_core net/core/dev.c:5534 [inline] + __netif_receive_skb+0x1a6/0x5a0 net/core/dev.c:5648 + process_backlog+0x480/0x8b0 net/core/dev.c:5976 + __napi_poll+0xe3/0x980 net/core/dev.c:6576 + napi_poll net/core/dev.c:6645 [inline] + net_rx_action+0x8b8/0x1870 net/core/dev.c:6778 + __do_softirq+0x1b7/0x7c5 kernel/softirq.c:553 + do_softirq+0x9a/0xf0 kernel/softirq.c:454 + __local_bh_enable_ip+0x9b/0xa0 kernel/softirq.c:381 + local_bh_enable include/linux/bottom_half.h:33 [inline] + rcu_read_unlock_bh include/linux/rcupdate.h:820 [inline] + __dev_queue_xmit+0x2768/0x51c0 net/core/dev.c:4378 + dev_queue_xmit include/linux/netdevice.h:3171 [inline] + packet_xmit+0x9c/0x6b0 net/packet/af_packet.c:276 + packet_snd net/packet/af_packet.c:3081 [inline] + packet_sendmsg+0x8aef/0x9f10 net/packet/af_packet.c:3113 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg net/socket.c:745 [inline] + __sys_sendto+0x735/0xa10 net/socket.c:2191 + __do_sys_sendto net/socket.c:2203 [inline] + __se_sys_sendto net/socket.c:2199 [inline] + __x64_sys_sendto+0x125/0x1c0 net/socket.c:2199 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x63/0x6b + +Uninit was created at: + slab_post_alloc_hook mm/slub.c:3819 [inline] + slab_alloc_node mm/slub.c:3860 [inline] + kmem_cache_alloc_node+0x5cb/0xbc0 mm/slub.c:3903 + kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:560 + __alloc_skb+0x352/0x790 net/core/skbuff.c:651 + alloc_skb include/linux/skbuff.h:1296 [inline] + alloc_skb_with_frags+0xc8/0xbd0 net/core/skbuff.c:6394 + sock_alloc_send_pskb+0xa80/0xbf0 net/core/sock.c:2783 + packet_alloc_skb net/packet/af_packet.c:2930 [inline] + packet_snd net/packet/af_packet.c:3024 [inline] + packet_sendmsg+0x70c2/0x9f10 net/packet/af_packet.c:3113 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg net/socket.c:745 [inline] + __sys_sendto+0x735/0xa10 net/socket.c:2191 + __do_sys_sendto net/socket.c:2203 [inline] + __se_sys_sendto net/socket.c:2199 [inline] + __x64_sys_sendto+0x125/0x1c0 net/socket.c:2199 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x63/0x6b + +Fixes: 2d07dc79fe04 ("geneve: add initial netdev driver for GENEVE tunnels") +Reported-and-tested-by: syzbot+6a1423ff3f97159aae64@syzkaller.appspotmail.com +Signed-off-by: Eric Dumazet +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/geneve.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index a19e04f8bcc8f..8aa04b37c5fe0 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -217,7 +217,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, + struct metadata_dst *tun_dst = NULL; + struct pcpu_sw_netstats *stats; + unsigned int len; +- int err = 0; ++ int nh, err = 0; + void *oiph; + + if (ip_tunnel_collect_metadata() || gs->collect_md) { +@@ -261,9 +261,23 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, + goto drop; + } + +- oiph = skb_network_header(skb); ++ /* Save offset of outer header relative to skb->head, ++ * because we are going to reset the network header to the inner header ++ * and might change skb->head. ++ */ ++ nh = skb_network_header(skb) - skb->head; ++ + skb_reset_network_header(skb); + ++ if (!pskb_inet_may_pull(skb)) { ++ DEV_STATS_INC(geneve->dev, rx_length_errors); ++ DEV_STATS_INC(geneve->dev, rx_errors); ++ goto drop; ++ } ++ ++ /* Get the outer header. */ ++ oiph = skb->head + nh; ++ + if (geneve_get_sk_family(gs) == AF_INET) + err = IP_ECN_decapsulate(oiph, skb); + #if IS_ENABLED(CONFIG_IPV6) +-- +2.43.0 + diff --git a/queue-4.19/lan78xx-add-missing-return-code-checks.patch b/queue-4.19/lan78xx-add-missing-return-code-checks.patch new file mode 100644 index 00000000000..3827cf279ee --- /dev/null +++ b/queue-4.19/lan78xx-add-missing-return-code-checks.patch @@ -0,0 +1,776 @@ +From 91fb10f556fb427fb61229523a2e90ea403c6a5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Aug 2021 19:56:08 +0100 +Subject: lan78xx: Add missing return code checks + +From: John Efstathiades + +[ Upstream commit 3415f6baaddb9b39d7112247ab39ef3c700f882e ] + +There are many places in the driver where the return code from a +function call is captured but without a subsequent test of the +return code and appropriate action taken. + +This patch adds the missing return code tests and action. In most +cases the action is an early exit from the calling function. + +The function lan78xx_set_suspend() was also updated to make it +consistent with lan78xx_suspend(). + +Signed-off-by: John Efstathiades +Signed-off-by: David S. Miller +Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop") +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 399 +++++++++++++++++++++++++++++++------- + 1 file changed, 333 insertions(+), 66 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 2f4f85e03df2c..a20aff073b865 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -1176,7 +1176,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) + /* clear LAN78xx interrupt status */ + ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_); + if (unlikely(ret < 0)) +- return -EIO; ++ return ret; + + mutex_lock(&phydev->lock); + phy_read_status(phydev); +@@ -1189,11 +1189,11 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) + /* reset MAC */ + ret = lan78xx_read_reg(dev, MAC_CR, &buf); + if (unlikely(ret < 0)) +- return -EIO; ++ return ret; + buf |= MAC_CR_RST_; + ret = lan78xx_write_reg(dev, MAC_CR, buf); + if (unlikely(ret < 0)) +- return -EIO; ++ return ret; + + del_timer(&dev->stat_monitor); + } else if (link && !dev->link_on) { +@@ -1205,18 +1205,30 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) + if (ecmd.base.speed == 1000) { + /* disable U2 */ + ret = lan78xx_read_reg(dev, USB_CFG1, &buf); ++ if (ret < 0) ++ return ret; + buf &= ~USB_CFG1_DEV_U2_INIT_EN_; + ret = lan78xx_write_reg(dev, USB_CFG1, buf); ++ if (ret < 0) ++ return ret; + /* enable U1 */ + ret = lan78xx_read_reg(dev, USB_CFG1, &buf); ++ if (ret < 0) ++ return ret; + buf |= USB_CFG1_DEV_U1_INIT_EN_; + ret = lan78xx_write_reg(dev, USB_CFG1, buf); ++ if (ret < 0) ++ return ret; + } else { + /* enable U1 & U2 */ + ret = lan78xx_read_reg(dev, USB_CFG1, &buf); ++ if (ret < 0) ++ return ret; + buf |= USB_CFG1_DEV_U2_INIT_EN_; + buf |= USB_CFG1_DEV_U1_INIT_EN_; + ret = lan78xx_write_reg(dev, USB_CFG1, buf); ++ if (ret < 0) ++ return ret; + } + } + +@@ -1234,6 +1246,8 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) + + ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv, + radv); ++ if (ret < 0) ++ return ret; + + if (!timer_pending(&dev->stat_monitor)) { + dev->delta = 1; +@@ -1244,7 +1258,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev) + tasklet_schedule(&dev->bh); + } + +- return ret; ++ return 0; + } + + /* some work can't be done in tasklets, so we use keventd +@@ -2469,23 +2483,33 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev) + static int lan78xx_reset(struct lan78xx_net *dev) + { + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); +- u32 buf; +- int ret = 0; + unsigned long timeout; ++ int ret; ++ u32 buf; + u8 sig; + + ret = lan78xx_read_reg(dev, HW_CFG, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= HW_CFG_LRST_; ++ + ret = lan78xx_write_reg(dev, HW_CFG, buf); ++ if (ret < 0) ++ return ret; + + timeout = jiffies + HZ; + do { + mdelay(1); + ret = lan78xx_read_reg(dev, HW_CFG, &buf); ++ if (ret < 0) ++ return ret; ++ + if (time_after(jiffies, timeout)) { + netdev_warn(dev->net, + "timeout on completion of LiteReset"); +- return -EIO; ++ ret = -ETIMEDOUT; ++ return ret; + } + } while (buf & HW_CFG_LRST_); + +@@ -2493,13 +2517,22 @@ static int lan78xx_reset(struct lan78xx_net *dev) + + /* save DEVID for later usage */ + ret = lan78xx_read_reg(dev, ID_REV, &buf); ++ if (ret < 0) ++ return ret; ++ + dev->chipid = (buf & ID_REV_CHIP_ID_MASK_) >> 16; + dev->chiprev = buf & ID_REV_CHIP_REV_MASK_; + + /* Respond to the IN token with a NAK */ + ret = lan78xx_read_reg(dev, USB_CFG0, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= USB_CFG_BIR_; ++ + ret = lan78xx_write_reg(dev, USB_CFG0, buf); ++ if (ret < 0) ++ return ret; + + /* Init LTM */ + lan78xx_init_ltm(dev); +@@ -2522,53 +2555,105 @@ static int lan78xx_reset(struct lan78xx_net *dev) + } + + ret = lan78xx_write_reg(dev, BURST_CAP, buf); ++ if (ret < 0) ++ return ret; ++ + ret = lan78xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, HW_CFG, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= HW_CFG_MEF_; ++ + ret = lan78xx_write_reg(dev, HW_CFG, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, USB_CFG0, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= USB_CFG_BCE_; ++ + ret = lan78xx_write_reg(dev, USB_CFG0, buf); ++ if (ret < 0) ++ return ret; + + /* set FIFO sizes */ + buf = (MAX_RX_FIFO_SIZE - 512) / 512; ++ + ret = lan78xx_write_reg(dev, FCT_RX_FIFO_END, buf); ++ if (ret < 0) ++ return ret; + + buf = (MAX_TX_FIFO_SIZE - 512) / 512; ++ + ret = lan78xx_write_reg(dev, FCT_TX_FIFO_END, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_); ++ if (ret < 0) ++ return ret; ++ + ret = lan78xx_write_reg(dev, FLOW, 0); ++ if (ret < 0) ++ return ret; ++ + ret = lan78xx_write_reg(dev, FCT_FLOW, 0); ++ if (ret < 0) ++ return ret; + + /* Don't need rfe_ctl_lock during initialisation */ + ret = lan78xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl); ++ if (ret < 0) ++ return ret; ++ + pdata->rfe_ctl |= RFE_CTL_BCAST_EN_ | RFE_CTL_DA_PERFECT_; ++ + ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); ++ if (ret < 0) ++ return ret; + + /* Enable or disable checksum offload engines */ +- lan78xx_set_features(dev->net, dev->net->features); ++ ret = lan78xx_set_features(dev->net, dev->net->features); ++ if (ret < 0) ++ return ret; + + lan78xx_set_multicast(dev->net); + + /* reset PHY */ + ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= PMT_CTL_PHY_RST_; ++ + ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ return ret; + + timeout = jiffies + HZ; + do { + mdelay(1); + ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ + if (time_after(jiffies, timeout)) { + netdev_warn(dev->net, "timeout waiting for PHY Reset"); +- return -EIO; ++ ret = -ETIMEDOUT; ++ return ret; + } + } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_)); + + ret = lan78xx_read_reg(dev, MAC_CR, &buf); ++ if (ret < 0) ++ return ret; ++ + /* LAN7801 only has RGMII mode */ + if (dev->chipid == ID_REV_CHIP_ID_7801_) + buf &= ~MAC_CR_GMII_EN_; +@@ -2583,25 +2668,53 @@ static int lan78xx_reset(struct lan78xx_net *dev) + } + } + ret = lan78xx_write_reg(dev, MAC_CR, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= MAC_TX_TXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_TX, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, FCT_TX_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= FCT_TX_CTL_EN_; ++ + ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_set_rx_max_frame_length(dev, + dev->net->mtu + VLAN_ETH_HLEN); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= MAC_RX_RXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, FCT_RX_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= FCT_RX_CTL_EN_; ++ + ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf); ++ if (ret < 0) ++ return ret; + + return 0; + } +@@ -2639,7 +2752,7 @@ static int lan78xx_open(struct net_device *net) + + ret = usb_autopm_get_interface(dev->intf); + if (ret < 0) +- goto out; ++ return ret; + + phy_start(net->phydev); + +@@ -2667,7 +2780,6 @@ static int lan78xx_open(struct net_device *net) + done: + usb_autopm_put_interface(dev->intf); + +-out: + return ret; + } + +@@ -3838,35 +3950,62 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len) + + static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + { +- u32 buf; +- int mask_index; +- u16 crc; +- u32 temp_wucsr; +- u32 temp_pmt_ctl; + const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E }; + const u8 ipv6_multicast[3] = { 0x33, 0x33 }; + const u8 arp_type[2] = { 0x08, 0x06 }; ++ u32 temp_pmt_ctl; ++ int mask_index; ++ u32 temp_wucsr; ++ u32 buf; ++ u16 crc; ++ int ret; ++ ++ ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ if (ret < 0) ++ return ret; + +- lan78xx_read_reg(dev, MAC_TX, &buf); + buf &= ~MAC_TX_TXEN_; +- lan78xx_write_reg(dev, MAC_TX, buf); +- lan78xx_read_reg(dev, MAC_RX, &buf); ++ ++ ret = lan78xx_write_reg(dev, MAC_TX, buf); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf &= ~MAC_RX_RXEN_; +- lan78xx_write_reg(dev, MAC_RX, buf); + +- lan78xx_write_reg(dev, WUCSR, 0); +- lan78xx_write_reg(dev, WUCSR2, 0); +- lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); ++ ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_write_reg(dev, WUCSR, 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUCSR2, 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); ++ if (ret < 0) ++ return ret; + + temp_wucsr = 0; + + temp_pmt_ctl = 0; +- lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl); ++ ++ ret = lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl); ++ if (ret < 0) ++ return ret; ++ + temp_pmt_ctl &= ~PMT_CTL_RES_CLR_WKP_EN_; + temp_pmt_ctl |= PMT_CTL_RES_CLR_WKP_STS_; + +- for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++) +- lan78xx_write_reg(dev, WUF_CFG(mask_index), 0); ++ for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++) { ++ ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ } + + mask_index = 0; + if (wol & WAKE_PHY) { +@@ -3895,30 +4034,52 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + + /* set WUF_CFG & WUF_MASK for IPv4 Multicast */ + crc = lan78xx_wakeframe_crc16(ipv4_multicast, 3); +- lan78xx_write_reg(dev, WUF_CFG(mask_index), +- WUF_CFGX_EN_ | +- WUF_CFGX_TYPE_MCAST_ | +- (0 << WUF_CFGX_OFFSET_SHIFT_) | +- (crc & WUF_CFGX_CRC16_MASK_)); +- +- lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7); +- lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +- lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); +- lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), ++ WUF_CFGX_EN_ | ++ WUF_CFGX_TYPE_MCAST_ | ++ (0 << WUF_CFGX_OFFSET_SHIFT_) | ++ (crc & WUF_CFGX_CRC16_MASK_)); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ + mask_index++; + + /* for IPv6 Multicast */ + crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2); +- lan78xx_write_reg(dev, WUF_CFG(mask_index), +- WUF_CFGX_EN_ | +- WUF_CFGX_TYPE_MCAST_ | +- (0 << WUF_CFGX_OFFSET_SHIFT_) | +- (crc & WUF_CFGX_CRC16_MASK_)); +- +- lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3); +- lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +- lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); +- lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), ++ WUF_CFGX_EN_ | ++ WUF_CFGX_TYPE_MCAST_ | ++ (0 << WUF_CFGX_OFFSET_SHIFT_) | ++ (crc & WUF_CFGX_CRC16_MASK_)); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ + mask_index++; + + temp_pmt_ctl |= PMT_CTL_WOL_EN_; +@@ -3939,16 +4100,27 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + * for packettype (offset 12,13) = ARP (0x0806) + */ + crc = lan78xx_wakeframe_crc16(arp_type, 2); +- lan78xx_write_reg(dev, WUF_CFG(mask_index), +- WUF_CFGX_EN_ | +- WUF_CFGX_TYPE_ALL_ | +- (0 << WUF_CFGX_OFFSET_SHIFT_) | +- (crc & WUF_CFGX_CRC16_MASK_)); +- +- lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000); +- lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +- lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); +- lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), ++ WUF_CFGX_EN_ | ++ WUF_CFGX_TYPE_ALL_ | ++ (0 << WUF_CFGX_OFFSET_SHIFT_) | ++ (crc & WUF_CFGX_CRC16_MASK_)); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ if (ret < 0) ++ return ret; ++ + mask_index++; + + temp_pmt_ctl |= PMT_CTL_WOL_EN_; +@@ -3956,7 +4128,9 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_; + } + +- lan78xx_write_reg(dev, WUCSR, temp_wucsr); ++ ret = lan78xx_write_reg(dev, WUCSR, temp_wucsr); ++ if (ret < 0) ++ return ret; + + /* when multiple WOL bits are set */ + if (hweight_long((unsigned long)wol) > 1) { +@@ -3964,16 +4138,30 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + temp_pmt_ctl &= ~PMT_CTL_SUS_MODE_MASK_; + temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_; + } +- lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl); ++ ret = lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl); ++ if (ret < 0) ++ return ret; + + /* clear WUPS */ +- lan78xx_read_reg(dev, PMT_CTL, &buf); ++ ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= PMT_CTL_WUPS_MASK_; +- lan78xx_write_reg(dev, PMT_CTL, buf); ++ ++ ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ return ret; + + lan78xx_read_reg(dev, MAC_RX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= MAC_RX_RXEN_; ++ + lan78xx_write_reg(dev, MAC_RX, buf); ++ if (ret < 0) ++ return ret; + + return 0; + } +@@ -3981,7 +4169,6 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + { + struct lan78xx_net *dev = usb_get_intfdata(intf); +- struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + u32 buf; + int ret; + int event; +@@ -4004,11 +4191,24 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + + /* stop TX & RX */ + ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf &= ~MAC_TX_TXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_TX, buf); ++ if (ret < 0) ++ return ret; ++ + ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf &= ~MAC_RX_RXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ if (ret < 0) ++ return ret; + + /* empty out the rx and queues */ + netif_device_detach(dev->net); +@@ -4025,25 +4225,50 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + if (PMSG_IS_AUTO(message)) { + /* auto suspend (selective suspend) */ + ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf &= ~MAC_TX_TXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_TX, buf); ++ if (ret < 0) ++ return ret; ++ + ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf &= ~MAC_RX_RXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_write_reg(dev, WUCSR, 0); ++ if (ret < 0) ++ return ret; + ret = lan78xx_write_reg(dev, WUCSR2, 0); ++ if (ret < 0) ++ return ret; + ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); ++ if (ret < 0) ++ return ret; + + /* set goodframe wakeup */ + ret = lan78xx_read_reg(dev, WUCSR, &buf); ++ if (ret < 0) ++ return ret; + + buf |= WUCSR_RFE_WAKE_EN_; + buf |= WUCSR_STORE_WAKE_; + + ret = lan78xx_write_reg(dev, WUCSR, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; + + buf &= ~PMT_CTL_RES_CLR_WKP_EN_; + buf |= PMT_CTL_RES_CLR_WKP_STS_; +@@ -4054,18 +4279,36 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + buf |= PMT_CTL_SUS_MODE_3_; + + ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; + + buf |= PMT_CTL_WUPS_MASK_; + + ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= MAC_RX_RXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ if (ret < 0) ++ return ret; + } else { +- lan78xx_set_suspend(dev, pdata->wol); ++ struct lan78xx_priv *pdata; ++ ++ pdata = (struct lan78xx_priv *)(dev->data[0]); ++ ++ ret = lan78xx_set_suspend(dev, pdata->wol); ++ if (ret < 0) ++ return ret; + } + } + +@@ -4090,8 +4333,11 @@ static int lan78xx_resume(struct usb_interface *intf) + + if (!--dev->suspend_count) { + /* resume interrupt URBs */ +- if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) +- usb_submit_urb(dev->urb_intr, GFP_NOIO); ++ if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) { ++ ret = usb_submit_urb(dev->urb_intr, GFP_NOIO); ++ if (ret < 0) ++ return ret; ++ } + + spin_lock_irq(&dev->txq.lock); + while ((res = usb_get_from_anchor(&dev->deferred))) { +@@ -4118,13 +4364,21 @@ static int lan78xx_resume(struct usb_interface *intf) + } + + ret = lan78xx_write_reg(dev, WUCSR2, 0); ++ if (ret < 0) ++ return ret; + ret = lan78xx_write_reg(dev, WUCSR, 0); ++ if (ret < 0) ++ return ret; + ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_write_reg(dev, WUCSR2, WUCSR2_NS_RCD_ | + WUCSR2_ARP_RCD_ | + WUCSR2_IPV6_TCPSYN_RCD_ | + WUCSR2_IPV4_TCPSYN_RCD_); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_write_reg(dev, WUCSR, WUCSR_EEE_TX_WAKE_ | + WUCSR_EEE_RX_WAKE_ | +@@ -4133,10 +4387,18 @@ static int lan78xx_resume(struct usb_interface *intf) + WUCSR_WUFR_ | + WUCSR_MPR_ | + WUCSR_BCST_FR_); ++ if (ret < 0) ++ return ret; + + ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ if (ret < 0) ++ return ret; ++ + buf |= MAC_TX_TXEN_; ++ + ret = lan78xx_write_reg(dev, MAC_TX, buf); ++ if (ret < 0) ++ return ret; + + return 0; + } +@@ -4144,12 +4406,17 @@ static int lan78xx_resume(struct usb_interface *intf) + static int lan78xx_reset_resume(struct usb_interface *intf) + { + struct lan78xx_net *dev = usb_get_intfdata(intf); ++ int ret; + +- lan78xx_reset(dev); ++ ret = lan78xx_reset(dev); ++ if (ret < 0) ++ return ret; + + phy_start(dev->net->phydev); + +- return lan78xx_resume(intf); ++ ret = lan78xx_resume(intf); ++ ++ return ret; + } + + static const struct usb_device_id products[] = { +-- +2.43.0 + diff --git a/queue-4.19/lan78xx-fix-partial-packet-errors-on-suspend-resume.patch b/queue-4.19/lan78xx-fix-partial-packet-errors-on-suspend-resume.patch new file mode 100644 index 00000000000..9fb19799b78 --- /dev/null +++ b/queue-4.19/lan78xx-fix-partial-packet-errors-on-suspend-resume.patch @@ -0,0 +1,455 @@ +From fd0a9c62f6c22bb0384ec545f5ecdd6a8635237f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Aug 2021 19:56:10 +0100 +Subject: lan78xx: Fix partial packet errors on suspend/resume + +From: John Efstathiades + +[ Upstream commit e1210fe63bf8b080edd0805240e90b81b6b069c1 ] + +The MAC can get out of step with the internal packet FIFOs if the +system goes to sleep when the link is active, especially at high +data rates. This can result in partial frames in the packet FIFOs +that in result in malformed frames being delivered to the host. +This occurs because the driver does not enable/disable the internal +packet FIFOs in step with the corresponding MAC data path. The +following changes fix this problem. + +Update code that enables/disables the MAC receiver and transmitter +to the more general Rx and Tx data path, where the data path in each +direction consists of both the MAC function (Tx or Rx) and the +corresponding packet FIFO. + +In the receive path the packet FIFO must be enabled before the MAC +receiver but disabled after the MAC receiver. + +In the transmit path the opposite is true: the packet FIFO must be +enabled after the MAC transmitter but disabled before the MAC +transmitter. + +The packet FIFOs can be flushed safely once the corresponding data +path is stopped. + +Signed-off-by: John Efstathiades +Signed-off-by: David S. Miller +Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop") +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 303 +++++++++++++++++++++++++------------- + 1 file changed, 197 insertions(+), 106 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index a20aff073b865..4f80f672f3184 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -101,6 +101,12 @@ + /* statistic update interval (mSec) */ + #define STAT_UPDATE_TIMER (1 * 1000) + ++/* time to wait for MAC or FCT to stop (jiffies) */ ++#define HW_DISABLE_TIMEOUT (HZ / 10) ++ ++/* time to wait between polling MAC or FCT state (ms) */ ++#define HW_DISABLE_DELAY_MS 1 ++ + /* defines interrupts from interrupt EP */ + #define MAX_INT_EP (32) + #define INT_EP_INTEP (31) +@@ -490,6 +496,26 @@ static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data) + return ret; + } + ++static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask, ++ u32 data) ++{ ++ int ret; ++ u32 buf; ++ ++ ret = lan78xx_read_reg(dev, reg, &buf); ++ if (ret < 0) ++ return ret; ++ ++ buf &= ~mask; ++ buf |= (mask & data); ++ ++ ret = lan78xx_write_reg(dev, reg, buf); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static int lan78xx_read_stats(struct lan78xx_net *dev, + struct lan78xx_statstage *data) + { +@@ -2480,6 +2506,156 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev) + lan78xx_write_reg(dev, LTM_INACTIVE1, regs[5]); + } + ++static int lan78xx_start_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enable) ++{ ++ return lan78xx_update_reg(dev, reg, hw_enable, hw_enable); ++} ++ ++static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled, ++ u32 hw_disabled) ++{ ++ unsigned long timeout; ++ bool stopped = true; ++ int ret; ++ u32 buf; ++ ++ /* Stop the h/w block (if not already stopped) */ ++ ++ ret = lan78xx_read_reg(dev, reg, &buf); ++ if (ret < 0) ++ return ret; ++ ++ if (buf & hw_enabled) { ++ buf &= ~hw_enabled; ++ ++ ret = lan78xx_write_reg(dev, reg, buf); ++ if (ret < 0) ++ return ret; ++ ++ stopped = false; ++ timeout = jiffies + HW_DISABLE_TIMEOUT; ++ do { ++ ret = lan78xx_read_reg(dev, reg, &buf); ++ if (ret < 0) ++ return ret; ++ ++ if (buf & hw_disabled) ++ stopped = true; ++ else ++ msleep(HW_DISABLE_DELAY_MS); ++ } while (!stopped && !time_after(jiffies, timeout)); ++ } ++ ++ ret = stopped ? 0 : -ETIME; ++ ++ return ret; ++} ++ ++static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 fifo_flush) ++{ ++ return lan78xx_update_reg(dev, reg, fifo_flush, fifo_flush); ++} ++ ++static int lan78xx_start_tx_path(struct lan78xx_net *dev) ++{ ++ int ret; ++ ++ netif_dbg(dev, drv, dev->net, "start tx path"); ++ ++ /* Start the MAC transmitter */ ++ ++ ret = lan78xx_start_hw(dev, MAC_TX, MAC_TX_TXEN_); ++ if (ret < 0) ++ return ret; ++ ++ /* Start the Tx FIFO */ ++ ++ ret = lan78xx_start_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int lan78xx_stop_tx_path(struct lan78xx_net *dev) ++{ ++ int ret; ++ ++ netif_dbg(dev, drv, dev->net, "stop tx path"); ++ ++ /* Stop the Tx FIFO */ ++ ++ ret = lan78xx_stop_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_, FCT_TX_CTL_DIS_); ++ if (ret < 0) ++ return ret; ++ ++ /* Stop the MAC transmitter */ ++ ++ ret = lan78xx_stop_hw(dev, MAC_TX, MAC_TX_TXEN_, MAC_TX_TXD_); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/* The caller must ensure the Tx path is stopped before calling ++ * lan78xx_flush_tx_fifo(). ++ */ ++static int lan78xx_flush_tx_fifo(struct lan78xx_net *dev) ++{ ++ return lan78xx_flush_fifo(dev, FCT_TX_CTL, FCT_TX_CTL_RST_); ++} ++ ++static int lan78xx_start_rx_path(struct lan78xx_net *dev) ++{ ++ int ret; ++ ++ netif_dbg(dev, drv, dev->net, "start rx path"); ++ ++ /* Start the Rx FIFO */ ++ ++ ret = lan78xx_start_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_); ++ if (ret < 0) ++ return ret; ++ ++ /* Start the MAC receiver*/ ++ ++ ret = lan78xx_start_hw(dev, MAC_RX, MAC_RX_RXEN_); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int lan78xx_stop_rx_path(struct lan78xx_net *dev) ++{ ++ int ret; ++ ++ netif_dbg(dev, drv, dev->net, "stop rx path"); ++ ++ /* Stop the MAC receiver */ ++ ++ ret = lan78xx_stop_hw(dev, MAC_RX, MAC_RX_RXEN_, MAC_RX_RXD_); ++ if (ret < 0) ++ return ret; ++ ++ /* Stop the Rx FIFO */ ++ ++ ret = lan78xx_stop_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_, FCT_RX_CTL_DIS_); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++/* The caller must ensure the Rx path is stopped before calling ++ * lan78xx_flush_rx_fifo(). ++ */ ++static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev) ++{ ++ return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_); ++} ++ + static int lan78xx_reset(struct lan78xx_net *dev) + { + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); +@@ -2671,23 +2847,7 @@ static int lan78xx_reset(struct lan78xx_net *dev) + if (ret < 0) + return ret; + +- ret = lan78xx_read_reg(dev, MAC_TX, &buf); +- if (ret < 0) +- return ret; +- +- buf |= MAC_TX_TXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_TX, buf); +- if (ret < 0) +- return ret; +- +- ret = lan78xx_read_reg(dev, FCT_TX_CTL, &buf); +- if (ret < 0) +- return ret; +- +- buf |= FCT_TX_CTL_EN_; +- +- ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf); ++ ret = lan78xx_start_tx_path(dev); + if (ret < 0) + return ret; + +@@ -2696,27 +2856,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) + if (ret < 0) + return ret; + +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); +- if (ret < 0) +- return ret; +- +- buf |= MAC_RX_RXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_RX, buf); +- if (ret < 0) +- return ret; ++ ret = lan78xx_start_rx_path(dev); + +- ret = lan78xx_read_reg(dev, FCT_RX_CTL, &buf); +- if (ret < 0) +- return ret; +- +- buf |= FCT_RX_CTL_EN_; +- +- ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf); +- if (ret < 0) +- return ret; +- +- return 0; ++ return ret; + } + + static void lan78xx_init_stats(struct lan78xx_net *dev) +@@ -3960,23 +4102,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + u16 crc; + int ret; + +- ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ ret = lan78xx_stop_tx_path(dev); + if (ret < 0) + return ret; +- +- buf &= ~MAC_TX_TXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_TX, buf); +- if (ret < 0) +- return ret; +- +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); +- if (ret < 0) +- return ret; +- +- buf &= ~MAC_RX_RXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ ret = lan78xx_stop_rx_path(dev); + if (ret < 0) + return ret; + +@@ -4153,17 +4282,9 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + if (ret < 0) + return ret; + +- lan78xx_read_reg(dev, MAC_RX, &buf); +- if (ret < 0) +- return ret; ++ ret = lan78xx_start_rx_path(dev); + +- buf |= MAC_RX_RXEN_; +- +- lan78xx_write_reg(dev, MAC_RX, buf); +- if (ret < 0) +- return ret; +- +- return 0; ++ return ret; + } + + static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) +@@ -4189,24 +4310,17 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + spin_unlock_irq(&dev->txq.lock); + } + +- /* stop TX & RX */ +- ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ /* stop RX */ ++ ret = lan78xx_stop_rx_path(dev); + if (ret < 0) + return ret; + +- buf &= ~MAC_TX_TXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_TX, buf); ++ ret = lan78xx_flush_rx_fifo(dev); + if (ret < 0) + return ret; + +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); +- if (ret < 0) +- return ret; +- +- buf &= ~MAC_RX_RXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ /* stop Tx */ ++ ret = lan78xx_stop_tx_path(dev); + if (ret < 0) + return ret; + +@@ -4224,23 +4338,11 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + + if (PMSG_IS_AUTO(message)) { + /* auto suspend (selective suspend) */ +- ret = lan78xx_read_reg(dev, MAC_TX, &buf); +- if (ret < 0) +- return ret; +- +- buf &= ~MAC_TX_TXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_TX, buf); +- if (ret < 0) +- return ret; +- +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ ret = lan78xx_stop_tx_path(dev); + if (ret < 0) + return ret; + +- buf &= ~MAC_RX_RXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ ret = lan78xx_stop_rx_path(dev); + if (ret < 0) + return ret; + +@@ -4292,13 +4394,7 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + if (ret < 0) + return ret; + +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); +- if (ret < 0) +- return ret; +- +- buf |= MAC_RX_RXEN_; +- +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ ret = lan78xx_start_rx_path(dev); + if (ret < 0) + return ret; + } else { +@@ -4323,7 +4419,6 @@ static int lan78xx_resume(struct usb_interface *intf) + struct sk_buff *skb; + struct urb *res; + int ret; +- u32 buf; + + if (!timer_pending(&dev->stat_monitor)) { + dev->delta = 1; +@@ -4331,6 +4426,10 @@ static int lan78xx_resume(struct usb_interface *intf) + jiffies + STAT_UPDATE_TIMER); + } + ++ ret = lan78xx_flush_tx_fifo(dev); ++ if (ret < 0) ++ return ret; ++ + if (!--dev->suspend_count) { + /* resume interrupt URBs */ + if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) { +@@ -4390,17 +4489,9 @@ static int lan78xx_resume(struct usb_interface *intf) + if (ret < 0) + return ret; + +- ret = lan78xx_read_reg(dev, MAC_TX, &buf); +- if (ret < 0) +- return ret; +- +- buf |= MAC_TX_TXEN_; ++ ret = lan78xx_start_tx_path(dev); + +- ret = lan78xx_write_reg(dev, MAC_TX, buf); +- if (ret < 0) +- return ret; +- +- return 0; ++ return ret; + } + + static int lan78xx_reset_resume(struct usb_interface *intf) +-- +2.43.0 + diff --git a/queue-4.19/lan78xx-fix-race-conditions-in-suspend-resume-handli.patch b/queue-4.19/lan78xx-fix-race-conditions-in-suspend-resume-handli.patch new file mode 100644 index 00000000000..0210246a75f --- /dev/null +++ b/queue-4.19/lan78xx-fix-race-conditions-in-suspend-resume-handli.patch @@ -0,0 +1,749 @@ +From 435e268fd8ea20c3d087c8e076381ef4fdb22b0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Aug 2021 19:56:11 +0100 +Subject: lan78xx: Fix race conditions in suspend/resume handling + +From: John Efstathiades + +[ Upstream commit 5f4cc6e25148cc141f97afb41b4dfe9eb1cce613 ] + +If the interface is given an IP address while the device is +suspended (as a result of an auto-suspend event) there is a race +between lan78xx_resume() and lan78xx_open() that can result in an +exception or failure to handle incoming packets. The following +changes fix this problem. + +Introduce a mutex to serialise operations in the network interface +open and stop entry points with respect to the USB driver suspend +and resume entry points. + +Move Tx and Rx data path start/stop to lan78xx_start() and +lan78xx_stop() respectively and flush the packet FIFOs before +starting the Tx and Rx data paths. This prevents the MAC and FIFOs +getting out of step and delivery of malformed packets to the network +stack. + +Stop processing of received packets before disconnecting the +PHY from the MAC to prevent a kernel exception caused by handling +packets after the PHY device has been removed. + +Refactor device auto-suspend code to make it consistent with the +the system suspend code and make the suspend handler easier to read. + +Add new code to stop wake-on-lan packets or PHY events resuming the +host or device from suspend if the device has not been opened +(typically after an IP address is assigned). + +This patch is dependent on changes to lan78xx_suspend() and +lan78xx_resume() introduced in the previous patch of this patch set. + +Signed-off-by: John Efstathiades +Signed-off-by: David S. Miller +Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop") +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 419 ++++++++++++++++++++++++++------------ + 1 file changed, 284 insertions(+), 135 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 4f80f672f3184..52d1d922f6c5e 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -401,6 +401,7 @@ struct lan78xx_net { + struct urb *urb_intr; + struct usb_anchor deferred; + ++ struct mutex dev_mutex; /* serialise open/stop wrt suspend/resume */ + struct mutex phy_mutex; /* for phy access */ + unsigned int pipe_in, pipe_out, pipe_intr; + +@@ -2330,11 +2331,16 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu) + int ll_mtu = new_mtu + netdev->hard_header_len; + int old_hard_mtu = dev->hard_mtu; + int old_rx_urb_size = dev->rx_urb_size; ++ int ret; + + /* no second zero-length packet read wanted after mtu-sized packets */ + if ((ll_mtu % dev->maxpacket) == 0) + return -EDOM; + ++ ret = usb_autopm_get_interface(dev->intf); ++ if (ret < 0) ++ return ret; ++ + lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN); + + netdev->mtu = new_mtu; +@@ -2350,6 +2356,8 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu) + } + } + ++ usb_autopm_put_interface(dev->intf); ++ + return 0; + } + +@@ -2847,16 +2855,8 @@ static int lan78xx_reset(struct lan78xx_net *dev) + if (ret < 0) + return ret; + +- ret = lan78xx_start_tx_path(dev); +- if (ret < 0) +- return ret; +- + ret = lan78xx_set_rx_max_frame_length(dev, + dev->net->mtu + VLAN_ETH_HLEN); +- if (ret < 0) +- return ret; +- +- ret = lan78xx_start_rx_path(dev); + + return ret; + } +@@ -2892,10 +2892,14 @@ static int lan78xx_open(struct net_device *net) + struct lan78xx_net *dev = netdev_priv(net); + int ret; + ++ netif_dbg(dev, ifup, dev->net, "open device"); ++ + ret = usb_autopm_get_interface(dev->intf); + if (ret < 0) + return ret; + ++ mutex_lock(&dev->dev_mutex); ++ + phy_start(net->phydev); + + netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); +@@ -2910,6 +2914,20 @@ static int lan78xx_open(struct net_device *net) + } + } + ++ ret = lan78xx_flush_rx_fifo(dev); ++ if (ret < 0) ++ goto done; ++ ret = lan78xx_flush_tx_fifo(dev); ++ if (ret < 0) ++ goto done; ++ ++ ret = lan78xx_start_tx_path(dev); ++ if (ret < 0) ++ goto done; ++ ret = lan78xx_start_rx_path(dev); ++ if (ret < 0) ++ goto done; ++ + lan78xx_init_stats(dev); + + set_bit(EVENT_DEV_OPEN, &dev->flags); +@@ -2920,6 +2938,8 @@ static int lan78xx_open(struct net_device *net) + + lan78xx_defer_kevent(dev, EVENT_LINK_RESET); + done: ++ mutex_unlock(&dev->dev_mutex); ++ + usb_autopm_put_interface(dev->intf); + + return ret; +@@ -2938,38 +2958,56 @@ static void lan78xx_terminate_urbs(struct lan78xx_net *dev) + temp = unlink_urbs(dev, &dev->txq) + unlink_urbs(dev, &dev->rxq); + + /* maybe wait for deletions to finish. */ +- while (!skb_queue_empty(&dev->rxq) && +- !skb_queue_empty(&dev->txq) && +- !skb_queue_empty(&dev->done)) { ++ while (!skb_queue_empty(&dev->rxq) || ++ !skb_queue_empty(&dev->txq)) { + schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS)); + set_current_state(TASK_UNINTERRUPTIBLE); + netif_dbg(dev, ifdown, dev->net, +- "waited for %d urb completions\n", temp); ++ "waited for %d urb completions", temp); + } + set_current_state(TASK_RUNNING); + dev->wait = NULL; + remove_wait_queue(&unlink_wakeup, &wait); ++ ++ while (!skb_queue_empty(&dev->done)) { ++ struct skb_data *entry; ++ struct sk_buff *skb; ++ ++ skb = skb_dequeue(&dev->done); ++ entry = (struct skb_data *)(skb->cb); ++ usb_free_urb(entry->urb); ++ dev_kfree_skb(skb); ++ } + } + + static int lan78xx_stop(struct net_device *net) + { + struct lan78xx_net *dev = netdev_priv(net); + ++ netif_dbg(dev, ifup, dev->net, "stop device"); ++ ++ mutex_lock(&dev->dev_mutex); ++ + if (timer_pending(&dev->stat_monitor)) + del_timer_sync(&dev->stat_monitor); + +- if (net->phydev) +- phy_stop(net->phydev); +- + clear_bit(EVENT_DEV_OPEN, &dev->flags); + netif_stop_queue(net); ++ tasklet_kill(&dev->bh); ++ ++ lan78xx_terminate_urbs(dev); + + netif_info(dev, ifdown, dev->net, + "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n", + net->stats.rx_packets, net->stats.tx_packets, + net->stats.rx_errors, net->stats.tx_errors); + +- lan78xx_terminate_urbs(dev); ++ /* ignore errors that occur stopping the Tx and Rx data paths */ ++ lan78xx_stop_tx_path(dev); ++ lan78xx_stop_rx_path(dev); ++ ++ if (net->phydev) ++ phy_stop(net->phydev); + + usb_kill_urb(dev->urb_intr); + +@@ -2979,12 +3017,17 @@ static int lan78xx_stop(struct net_device *net) + * can't flush_scheduled_work() until we drop rtnl (later), + * else workers could deadlock; so make workers a NOP. + */ +- dev->flags = 0; ++ clear_bit(EVENT_TX_HALT, &dev->flags); ++ clear_bit(EVENT_RX_HALT, &dev->flags); ++ clear_bit(EVENT_LINK_RESET, &dev->flags); ++ clear_bit(EVENT_STAT_UPDATE, &dev->flags); ++ + cancel_delayed_work_sync(&dev->wq); +- tasklet_kill(&dev->bh); + + usb_autopm_put_interface(dev->intf); + ++ mutex_unlock(&dev->dev_mutex); ++ + return 0; + } + +@@ -3110,6 +3153,9 @@ lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net) + struct lan78xx_net *dev = netdev_priv(net); + struct sk_buff *skb2 = NULL; + ++ if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) ++ schedule_delayed_work(&dev->wq, 0); ++ + if (skb) { + skb_tx_timestamp(skb); + skb2 = lan78xx_tx_prep(dev, skb, GFP_ATOMIC); +@@ -3719,18 +3765,17 @@ static void lan78xx_delayedwork(struct work_struct *work) + + dev = container_of(work, struct lan78xx_net, wq.work); + ++ if (usb_autopm_get_interface(dev->intf) < 0) ++ return; ++ + if (test_bit(EVENT_TX_HALT, &dev->flags)) { + unlink_urbs(dev, &dev->txq); +- status = usb_autopm_get_interface(dev->intf); +- if (status < 0) +- goto fail_pipe; ++ + status = usb_clear_halt(dev->udev, dev->pipe_out); +- usb_autopm_put_interface(dev->intf); + if (status < 0 && + status != -EPIPE && + status != -ESHUTDOWN) { + if (netif_msg_tx_err(dev)) +-fail_pipe: + netdev_err(dev->net, + "can't clear tx halt, status %d\n", + status); +@@ -3740,18 +3785,14 @@ static void lan78xx_delayedwork(struct work_struct *work) + netif_wake_queue(dev->net); + } + } ++ + if (test_bit(EVENT_RX_HALT, &dev->flags)) { + unlink_urbs(dev, &dev->rxq); +- status = usb_autopm_get_interface(dev->intf); +- if (status < 0) +- goto fail_halt; + status = usb_clear_halt(dev->udev, dev->pipe_in); +- usb_autopm_put_interface(dev->intf); + if (status < 0 && + status != -EPIPE && + status != -ESHUTDOWN) { + if (netif_msg_rx_err(dev)) +-fail_halt: + netdev_err(dev->net, + "can't clear rx halt, status %d\n", + status); +@@ -3765,16 +3806,9 @@ static void lan78xx_delayedwork(struct work_struct *work) + int ret = 0; + + clear_bit(EVENT_LINK_RESET, &dev->flags); +- status = usb_autopm_get_interface(dev->intf); +- if (status < 0) +- goto skip_reset; + if (lan78xx_link_reset(dev) < 0) { +- usb_autopm_put_interface(dev->intf); +-skip_reset: + netdev_info(dev->net, "link reset failed (%d)\n", + ret); +- } else { +- usb_autopm_put_interface(dev->intf); + } + } + +@@ -3788,6 +3822,8 @@ static void lan78xx_delayedwork(struct work_struct *work) + + dev->delta = min((dev->delta * 2), 50); + } ++ ++ usb_autopm_put_interface(dev->intf); + } + + static void intr_complete(struct urb *urb) +@@ -3947,6 +3983,7 @@ static int lan78xx_probe(struct usb_interface *intf, + skb_queue_head_init(&dev->rxq_pause); + skb_queue_head_init(&dev->txq_pend); + mutex_init(&dev->phy_mutex); ++ mutex_init(&dev->dev_mutex); + + tasklet_init(&dev->bh, lan78xx_bh, (unsigned long)dev); + INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork); +@@ -4090,6 +4127,74 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len) + return crc; + } + ++static int lan78xx_set_auto_suspend(struct lan78xx_net *dev) ++{ ++ u32 buf; ++ int ret; ++ ++ ret = lan78xx_stop_tx_path(dev); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_stop_rx_path(dev); ++ if (ret < 0) ++ return ret; ++ ++ /* auto suspend (selective suspend) */ ++ ++ ret = lan78xx_write_reg(dev, WUCSR, 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WUCSR2, 0); ++ if (ret < 0) ++ return ret; ++ ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); ++ if (ret < 0) ++ return ret; ++ ++ /* set goodframe wakeup */ ++ ++ ret = lan78xx_read_reg(dev, WUCSR, &buf); ++ if (ret < 0) ++ return ret; ++ ++ buf |= WUCSR_RFE_WAKE_EN_; ++ buf |= WUCSR_STORE_WAKE_; ++ ++ ret = lan78xx_write_reg(dev, WUCSR, buf); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ ++ buf &= ~PMT_CTL_RES_CLR_WKP_EN_; ++ buf |= PMT_CTL_RES_CLR_WKP_STS_; ++ buf |= PMT_CTL_PHY_WAKE_EN_; ++ buf |= PMT_CTL_WOL_EN_; ++ buf &= ~PMT_CTL_SUS_MODE_MASK_; ++ buf |= PMT_CTL_SUS_MODE_3_; ++ ++ ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ return ret; ++ ++ buf |= PMT_CTL_WUPS_MASK_; ++ ++ ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ return ret; ++ ++ ret = lan78xx_start_rx_path(dev); ++ ++ return ret; ++} ++ + static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + { + const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E }; +@@ -4290,18 +4395,25 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + { + struct lan78xx_net *dev = usb_get_intfdata(intf); +- u32 buf; ++ bool dev_open; + int ret; + int event; + + event = message.event; + +- if (!dev->suspend_count++) { ++ mutex_lock(&dev->dev_mutex); ++ ++ netif_dbg(dev, ifdown, dev->net, ++ "suspending: pm event %#x", message.event); ++ ++ dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags); ++ ++ if (dev_open) { + spin_lock_irq(&dev->txq.lock); + /* don't autosuspend while transmitting */ + if ((skb_queue_len(&dev->txq) || + skb_queue_len(&dev->txq_pend)) && +- PMSG_IS_AUTO(message)) { ++ PMSG_IS_AUTO(message)) { + spin_unlock_irq(&dev->txq.lock); + ret = -EBUSY; + goto out; +@@ -4313,171 +4425,204 @@ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message) + /* stop RX */ + ret = lan78xx_stop_rx_path(dev); + if (ret < 0) +- return ret; ++ goto out; + + ret = lan78xx_flush_rx_fifo(dev); + if (ret < 0) +- return ret; ++ goto out; + + /* stop Tx */ + ret = lan78xx_stop_tx_path(dev); + if (ret < 0) +- return ret; ++ goto out; + +- /* empty out the rx and queues */ ++ /* empty out the Rx and Tx queues */ + netif_device_detach(dev->net); + lan78xx_terminate_urbs(dev); + usb_kill_urb(dev->urb_intr); + + /* reattach */ + netif_device_attach(dev->net); +- } + +- if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) { + del_timer(&dev->stat_monitor); + + if (PMSG_IS_AUTO(message)) { +- /* auto suspend (selective suspend) */ +- ret = lan78xx_stop_tx_path(dev); ++ ret = lan78xx_set_auto_suspend(dev); + if (ret < 0) +- return ret; ++ goto out; ++ } else { ++ struct lan78xx_priv *pdata; + +- ret = lan78xx_stop_rx_path(dev); ++ pdata = (struct lan78xx_priv *)(dev->data[0]); ++ netif_carrier_off(dev->net); ++ ret = lan78xx_set_suspend(dev, pdata->wol); + if (ret < 0) +- return ret; ++ goto out; ++ } ++ } else { ++ /* Interface is down; don't allow WOL and PHY ++ * events to wake up the host ++ */ ++ u32 buf; + +- ret = lan78xx_write_reg(dev, WUCSR, 0); +- if (ret < 0) +- return ret; +- ret = lan78xx_write_reg(dev, WUCSR2, 0); +- if (ret < 0) +- return ret; +- ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); +- if (ret < 0) +- return ret; ++ set_bit(EVENT_DEV_ASLEEP, &dev->flags); + +- /* set goodframe wakeup */ +- ret = lan78xx_read_reg(dev, WUCSR, &buf); +- if (ret < 0) +- return ret; ++ ret = lan78xx_write_reg(dev, WUCSR, 0); ++ if (ret < 0) ++ goto out; ++ ret = lan78xx_write_reg(dev, WUCSR2, 0); ++ if (ret < 0) ++ goto out; + +- buf |= WUCSR_RFE_WAKE_EN_; +- buf |= WUCSR_STORE_WAKE_; ++ ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ goto out; + +- ret = lan78xx_write_reg(dev, WUCSR, buf); +- if (ret < 0) +- return ret; ++ buf &= ~PMT_CTL_RES_CLR_WKP_EN_; ++ buf |= PMT_CTL_RES_CLR_WKP_STS_; ++ buf &= ~PMT_CTL_SUS_MODE_MASK_; ++ buf |= PMT_CTL_SUS_MODE_3_; + +- ret = lan78xx_read_reg(dev, PMT_CTL, &buf); +- if (ret < 0) +- return ret; ++ ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ goto out; + +- buf &= ~PMT_CTL_RES_CLR_WKP_EN_; +- buf |= PMT_CTL_RES_CLR_WKP_STS_; ++ ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ if (ret < 0) ++ goto out; + +- buf |= PMT_CTL_PHY_WAKE_EN_; +- buf |= PMT_CTL_WOL_EN_; +- buf &= ~PMT_CTL_SUS_MODE_MASK_; +- buf |= PMT_CTL_SUS_MODE_3_; ++ buf |= PMT_CTL_WUPS_MASK_; + +- ret = lan78xx_write_reg(dev, PMT_CTL, buf); +- if (ret < 0) +- return ret; ++ ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ if (ret < 0) ++ goto out; ++ } + +- ret = lan78xx_read_reg(dev, PMT_CTL, &buf); +- if (ret < 0) +- return ret; ++ ret = 0; ++out: ++ mutex_unlock(&dev->dev_mutex); + +- buf |= PMT_CTL_WUPS_MASK_; ++ return ret; ++} + +- ret = lan78xx_write_reg(dev, PMT_CTL, buf); +- if (ret < 0) +- return ret; ++static bool lan78xx_submit_deferred_urbs(struct lan78xx_net *dev) ++{ ++ bool pipe_halted = false; ++ struct urb *urb; + +- ret = lan78xx_start_rx_path(dev); +- if (ret < 0) +- return ret; +- } else { +- struct lan78xx_priv *pdata; ++ while ((urb = usb_get_from_anchor(&dev->deferred))) { ++ struct sk_buff *skb = urb->context; ++ int ret; + +- pdata = (struct lan78xx_priv *)(dev->data[0]); ++ if (!netif_device_present(dev->net) || ++ !netif_carrier_ok(dev->net) || ++ pipe_halted) { ++ usb_free_urb(urb); ++ dev_kfree_skb(skb); ++ continue; ++ } + +- ret = lan78xx_set_suspend(dev, pdata->wol); +- if (ret < 0) +- return ret; ++ ret = usb_submit_urb(urb, GFP_ATOMIC); ++ ++ if (ret == 0) { ++ netif_trans_update(dev->net); ++ lan78xx_queue_skb(&dev->txq, skb, tx_start); ++ } else { ++ usb_free_urb(urb); ++ dev_kfree_skb(skb); ++ ++ if (ret == -EPIPE) { ++ netif_stop_queue(dev->net); ++ pipe_halted = true; ++ } else if (ret == -ENODEV) { ++ netif_device_detach(dev->net); ++ } + } + } + +- ret = 0; +-out: +- return ret; ++ return pipe_halted; + } + + static int lan78xx_resume(struct usb_interface *intf) + { + struct lan78xx_net *dev = usb_get_intfdata(intf); +- struct sk_buff *skb; +- struct urb *res; ++ bool dev_open; + int ret; + +- if (!timer_pending(&dev->stat_monitor)) { +- dev->delta = 1; +- mod_timer(&dev->stat_monitor, +- jiffies + STAT_UPDATE_TIMER); +- } ++ mutex_lock(&dev->dev_mutex); + +- ret = lan78xx_flush_tx_fifo(dev); +- if (ret < 0) +- return ret; ++ netif_dbg(dev, ifup, dev->net, "resuming device"); + +- if (!--dev->suspend_count) { +- /* resume interrupt URBs */ +- if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) { +- ret = usb_submit_urb(dev->urb_intr, GFP_NOIO); +- if (ret < 0) +- return ret; +- } ++ dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags); ++ ++ if (dev_open) { ++ bool pipe_halted = false; ++ ++ ret = lan78xx_flush_tx_fifo(dev); ++ if (ret < 0) ++ goto out; ++ ++ if (dev->urb_intr) { ++ int ret = usb_submit_urb(dev->urb_intr, GFP_KERNEL); + +- spin_lock_irq(&dev->txq.lock); +- while ((res = usb_get_from_anchor(&dev->deferred))) { +- skb = (struct sk_buff *)res->context; +- ret = usb_submit_urb(res, GFP_ATOMIC); + if (ret < 0) { +- dev_kfree_skb_any(skb); +- usb_free_urb(res); +- usb_autopm_put_interface_async(dev->intf); +- } else { +- netif_trans_update(dev->net); +- lan78xx_queue_skb(&dev->txq, skb, tx_start); ++ if (ret == -ENODEV) ++ netif_device_detach(dev->net); ++ ++ netdev_warn(dev->net, "Failed to submit intr URB"); + } + } + ++ spin_lock_irq(&dev->txq.lock); ++ ++ if (netif_device_present(dev->net)) { ++ pipe_halted = lan78xx_submit_deferred_urbs(dev); ++ ++ if (pipe_halted) ++ lan78xx_defer_kevent(dev, EVENT_TX_HALT); ++ } ++ + clear_bit(EVENT_DEV_ASLEEP, &dev->flags); ++ + spin_unlock_irq(&dev->txq.lock); + +- if (test_bit(EVENT_DEV_OPEN, &dev->flags)) { +- if (!(skb_queue_len(&dev->txq) >= dev->tx_qlen)) +- netif_start_queue(dev->net); +- tasklet_schedule(&dev->bh); ++ if (!pipe_halted && ++ netif_device_present(dev->net) && ++ (skb_queue_len(&dev->txq) < dev->tx_qlen)) ++ netif_start_queue(dev->net); ++ ++ ret = lan78xx_start_tx_path(dev); ++ if (ret < 0) ++ goto out; ++ ++ tasklet_schedule(&dev->bh); ++ ++ if (!timer_pending(&dev->stat_monitor)) { ++ dev->delta = 1; ++ mod_timer(&dev->stat_monitor, ++ jiffies + STAT_UPDATE_TIMER); + } ++ ++ } else { ++ clear_bit(EVENT_DEV_ASLEEP, &dev->flags); + } + + ret = lan78xx_write_reg(dev, WUCSR2, 0); + if (ret < 0) +- return ret; ++ goto out; + ret = lan78xx_write_reg(dev, WUCSR, 0); + if (ret < 0) +- return ret; ++ goto out; + ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); + if (ret < 0) +- return ret; ++ goto out; + + ret = lan78xx_write_reg(dev, WUCSR2, WUCSR2_NS_RCD_ | + WUCSR2_ARP_RCD_ | + WUCSR2_IPV6_TCPSYN_RCD_ | + WUCSR2_IPV4_TCPSYN_RCD_); + if (ret < 0) +- return ret; ++ goto out; + + ret = lan78xx_write_reg(dev, WUCSR, WUCSR_EEE_TX_WAKE_ | + WUCSR_EEE_RX_WAKE_ | +@@ -4487,9 +4632,11 @@ static int lan78xx_resume(struct usb_interface *intf) + WUCSR_MPR_ | + WUCSR_BCST_FR_); + if (ret < 0) +- return ret; ++ goto out; + +- ret = lan78xx_start_tx_path(dev); ++ ret = 0; ++out: ++ mutex_unlock(&dev->dev_mutex); + + return ret; + } +@@ -4499,6 +4646,8 @@ static int lan78xx_reset_resume(struct usb_interface *intf) + struct lan78xx_net *dev = usb_get_intfdata(intf); + int ret; + ++ netif_dbg(dev, ifup, dev->net, "(reset) resuming device"); ++ + ret = lan78xx_reset(dev); + if (ret < 0) + return ret; +-- +2.43.0 + diff --git a/queue-4.19/lan78xx-fix-white-space-and-style-issues.patch b/queue-4.19/lan78xx-fix-white-space-and-style-issues.patch new file mode 100644 index 00000000000..1b73cf97380 --- /dev/null +++ b/queue-4.19/lan78xx-fix-white-space-and-style-issues.patch @@ -0,0 +1,255 @@ +From ef3c085c2f5cb66073c0b55407edd5b5233164f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Aug 2021 19:56:04 +0100 +Subject: lan78xx: Fix white space and style issues + +From: John Efstathiades + +[ Upstream commit 9ceec7d33adf9647293f24d2fd9a055b89c63864 ] + +Fix white space and code style issues identified by checkpatch. + +Signed-off-by: John Efstathiades +Signed-off-by: David S. Miller +Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop") +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 80 ++++++++++++++++++++------------------- + 1 file changed, 42 insertions(+), 38 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 4d94af63cf190..2f4f85e03df2c 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -396,7 +396,7 @@ struct lan78xx_net { + struct usb_anchor deferred; + + struct mutex phy_mutex; /* for phy access */ +- unsigned pipe_in, pipe_out, pipe_intr; ++ unsigned int pipe_in, pipe_out, pipe_intr; + + u32 hard_mtu; /* count any extra framing */ + size_t rx_urb_size; /* size for rx urbs */ +@@ -406,7 +406,7 @@ struct lan78xx_net { + wait_queue_head_t *wait; + unsigned char suspend_count; + +- unsigned maxpacket; ++ unsigned int maxpacket; + struct timer_list delay; + struct timer_list stat_monitor; + +@@ -515,7 +515,7 @@ static int lan78xx_read_stats(struct lan78xx_net *dev, + if (likely(ret >= 0)) { + src = (u32 *)stats; + dst = (u32 *)data; +- for (i = 0; i < sizeof(*stats)/sizeof(u32); i++) { ++ for (i = 0; i < sizeof(*stats) / sizeof(u32); i++) { + le32_to_cpus(&src[i]); + dst[i] = src[i]; + } +@@ -529,10 +529,11 @@ static int lan78xx_read_stats(struct lan78xx_net *dev, + return ret; + } + +-#define check_counter_rollover(struct1, dev_stats, member) { \ +- if (struct1->member < dev_stats.saved.member) \ +- dev_stats.rollover_count.member++; \ +- } ++#define check_counter_rollover(struct1, dev_stats, member) \ ++ do { \ ++ if ((struct1)->member < (dev_stats).saved.member) \ ++ (dev_stats).rollover_count.member++; \ ++ } while (0) + + static void lan78xx_check_stat_rollover(struct lan78xx_net *dev, + struct lan78xx_statstage *stats) +@@ -858,9 +859,9 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, + + for (i = 0; i < length; i++) { + lan78xx_write_reg(dev, OTP_ADDR1, +- ((offset + i) >> 8) & OTP_ADDR1_15_11); ++ ((offset + i) >> 8) & OTP_ADDR1_15_11); + lan78xx_write_reg(dev, OTP_ADDR2, +- ((offset + i) & OTP_ADDR2_10_3)); ++ ((offset + i) & OTP_ADDR2_10_3)); + + lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_); + lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_); +@@ -914,9 +915,9 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset, + + for (i = 0; i < length; i++) { + lan78xx_write_reg(dev, OTP_ADDR1, +- ((offset + i) >> 8) & OTP_ADDR1_15_11); ++ ((offset + i) >> 8) & OTP_ADDR1_15_11); + lan78xx_write_reg(dev, OTP_ADDR2, +- ((offset + i) & OTP_ADDR2_10_3)); ++ ((offset + i) & OTP_ADDR2_10_3)); + lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]); + lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_); + lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_); +@@ -973,7 +974,7 @@ static int lan78xx_dataport_wait_not_busy(struct lan78xx_net *dev) + usleep_range(40, 100); + } + +- netdev_warn(dev->net, "lan78xx_dataport_wait_not_busy timed out"); ++ netdev_warn(dev->net, "%s timed out", __func__); + + return -EIO; + } +@@ -986,7 +987,7 @@ static int lan78xx_dataport_write(struct lan78xx_net *dev, u32 ram_select, + int i, ret; + + if (usb_autopm_get_interface(dev->intf) < 0) +- return 0; ++ return 0; + + mutex_lock(&pdata->dataport_mutex); + +@@ -1059,9 +1060,9 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param) + for (i = 1; i < NUM_OF_MAF; i++) { + lan78xx_write_reg(dev, MAF_HI(i), 0); + lan78xx_write_reg(dev, MAF_LO(i), +- pdata->pfilter_table[i][1]); ++ pdata->pfilter_table[i][1]); + lan78xx_write_reg(dev, MAF_HI(i), +- pdata->pfilter_table[i][0]); ++ pdata->pfilter_table[i][0]); + } + + lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); +@@ -1080,11 +1081,12 @@ static void lan78xx_set_multicast(struct net_device *netdev) + RFE_CTL_DA_PERFECT_ | RFE_CTL_MCAST_HASH_); + + for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++) +- pdata->mchash_table[i] = 0; ++ pdata->mchash_table[i] = 0; ++ + /* pfilter_table[0] has own HW address */ + for (i = 1; i < NUM_OF_MAF; i++) { +- pdata->pfilter_table[i][0] = +- pdata->pfilter_table[i][1] = 0; ++ pdata->pfilter_table[i][0] = 0; ++ pdata->pfilter_table[i][1] = 0; + } + + pdata->rfe_ctl |= RFE_CTL_BCAST_EN_; +@@ -1279,9 +1281,10 @@ static void lan78xx_status(struct lan78xx_net *dev, struct urb *urb) + generic_handle_irq(dev->domain_data.phyirq); + local_irq_enable(); + } +- } else ++ } else { + netdev_warn(dev->net, + "unexpected interrupt: 0x%08x\n", intdata); ++ } + } + + static int lan78xx_ethtool_get_eeprom_len(struct net_device *netdev) +@@ -1370,7 +1373,7 @@ static void lan78xx_get_wol(struct net_device *netdev, + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + + if (usb_autopm_get_interface(dev->intf) < 0) +- return; ++ return; + + ret = lan78xx_read_reg(dev, USB_CFG0, &buf); + if (unlikely(ret < 0)) { +@@ -2027,7 +2030,7 @@ static int lan8835_fixup(struct phy_device *phydev) + + /* RGMII MAC TXC Delay Enable */ + lan78xx_write_reg(dev, MAC_RGMII_ID, +- MAC_RGMII_ID_TXC_DELAY_EN_); ++ MAC_RGMII_ID_TXC_DELAY_EN_); + + /* RGMII TX DLL Tune Adjust */ + lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); +@@ -3383,9 +3386,10 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev) + if (skb) + dev_kfree_skb_any(skb); + usb_free_urb(urb); +- } else ++ } else { + netif_dbg(dev, tx_queued, dev->net, + "> tx, len %d, type 0x%x\n", length, skb->protocol); ++ } + } + + static void lan78xx_rx_bh(struct lan78xx_net *dev) +@@ -3486,7 +3490,7 @@ static void lan78xx_delayedwork(struct work_struct *work) + unlink_urbs(dev, &dev->rxq); + status = usb_autopm_get_interface(dev->intf); + if (status < 0) +- goto fail_halt; ++ goto fail_halt; + status = usb_clear_halt(dev->udev, dev->pipe_in); + usb_autopm_put_interface(dev->intf); + if (status < 0 && +@@ -3659,8 +3663,8 @@ static int lan78xx_probe(struct usb_interface *intf, + struct net_device *netdev; + struct usb_device *udev; + int ret; +- unsigned maxp; +- unsigned period; ++ unsigned int maxp; ++ unsigned int period; + u8 *buf = NULL; + + udev = interface_to_usbdev(intf); +@@ -3892,10 +3896,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + /* set WUF_CFG & WUF_MASK for IPv4 Multicast */ + crc = lan78xx_wakeframe_crc16(ipv4_multicast, 3); + lan78xx_write_reg(dev, WUF_CFG(mask_index), +- WUF_CFGX_EN_ | +- WUF_CFGX_TYPE_MCAST_ | +- (0 << WUF_CFGX_OFFSET_SHIFT_) | +- (crc & WUF_CFGX_CRC16_MASK_)); ++ WUF_CFGX_EN_ | ++ WUF_CFGX_TYPE_MCAST_ | ++ (0 << WUF_CFGX_OFFSET_SHIFT_) | ++ (crc & WUF_CFGX_CRC16_MASK_)); + + lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7); + lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +@@ -3906,10 +3910,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + /* for IPv6 Multicast */ + crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2); + lan78xx_write_reg(dev, WUF_CFG(mask_index), +- WUF_CFGX_EN_ | +- WUF_CFGX_TYPE_MCAST_ | +- (0 << WUF_CFGX_OFFSET_SHIFT_) | +- (crc & WUF_CFGX_CRC16_MASK_)); ++ WUF_CFGX_EN_ | ++ WUF_CFGX_TYPE_MCAST_ | ++ (0 << WUF_CFGX_OFFSET_SHIFT_) | ++ (crc & WUF_CFGX_CRC16_MASK_)); + + lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3); + lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +@@ -3936,10 +3940,10 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + */ + crc = lan78xx_wakeframe_crc16(arp_type, 2); + lan78xx_write_reg(dev, WUF_CFG(mask_index), +- WUF_CFGX_EN_ | +- WUF_CFGX_TYPE_ALL_ | +- (0 << WUF_CFGX_OFFSET_SHIFT_) | +- (crc & WUF_CFGX_CRC16_MASK_)); ++ WUF_CFGX_EN_ | ++ WUF_CFGX_TYPE_ALL_ | ++ (0 << WUF_CFGX_OFFSET_SHIFT_) | ++ (crc & WUF_CFGX_CRC16_MASK_)); + + lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000); + lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +@@ -4087,7 +4091,7 @@ static int lan78xx_resume(struct usb_interface *intf) + if (!--dev->suspend_count) { + /* resume interrupt URBs */ + if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags)) +- usb_submit_urb(dev->urb_intr, GFP_NOIO); ++ usb_submit_urb(dev->urb_intr, GFP_NOIO); + + spin_lock_irq(&dev->txq.lock); + while ((res = usb_get_from_anchor(&dev->deferred))) { +-- +2.43.0 + diff --git a/queue-4.19/net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch b/queue-4.19/net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch new file mode 100644 index 00000000000..fdab5307149 --- /dev/null +++ b/queue-4.19/net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch @@ -0,0 +1,257 @@ +From 864edec8b5c8f7dafcad74fdbee14d31f7e7c78a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Mar 2024 14:48:00 +0000 +Subject: net/ipv6: avoid possible UAF in ip6_route_mpath_notify() + +From: Eric Dumazet + +[ Upstream commit 685f7d531264599b3f167f1e94bbd22f120e5fab ] + +syzbot found another use-after-free in ip6_route_mpath_notify() [1] + +Commit f7225172f25a ("net/ipv6: prevent use after free in +ip6_route_mpath_notify") was not able to fix the root cause. + +We need to defer the fib6_info_release() calls after +ip6_route_mpath_notify(), in the cleanup phase. + +[1] +BUG: KASAN: slab-use-after-free in rt6_fill_node+0x1460/0x1ac0 +Read of size 4 at addr ffff88809a07fc64 by task syz-executor.2/23037 + +CPU: 0 PID: 23037 Comm: syz-executor.2 Not tainted 6.8.0-rc4-syzkaller-01035-gea7f3cfaa588 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024 +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x1e7/0x2e0 lib/dump_stack.c:106 + print_address_description mm/kasan/report.c:377 [inline] + print_report+0x167/0x540 mm/kasan/report.c:488 + kasan_report+0x142/0x180 mm/kasan/report.c:601 + rt6_fill_node+0x1460/0x1ac0 + inet6_rt_notify+0x13b/0x290 net/ipv6/route.c:6184 + ip6_route_mpath_notify net/ipv6/route.c:5198 [inline] + ip6_route_multipath_add net/ipv6/route.c:5404 [inline] + inet6_rtm_newroute+0x1d0f/0x2300 net/ipv6/route.c:5517 + rtnetlink_rcv_msg+0x885/0x1040 net/core/rtnetlink.c:6597 + netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2543 + netlink_unicast_kernel net/netlink/af_netlink.c:1341 [inline] + netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1367 + netlink_sendmsg+0xa3b/0xd70 net/netlink/af_netlink.c:1908 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:745 + ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584 + ___sys_sendmsg net/socket.c:2638 [inline] + __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667 + do_syscall_64+0xf9/0x240 + entry_SYSCALL_64_after_hwframe+0x6f/0x77 +RIP: 0033:0x7f73dd87dda9 +Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 +RSP: 002b:00007f73de6550c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 00007f73dd9ac050 RCX: 00007f73dd87dda9 +RDX: 0000000000000000 RSI: 0000000020000140 RDI: 0000000000000005 +RBP: 00007f73dd8ca47a R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 +R13: 000000000000006e R14: 00007f73dd9ac050 R15: 00007ffdbdeb7858 + + +Allocated by task 23037: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + poison_kmalloc_redzone mm/kasan/common.c:372 [inline] + __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:389 + kasan_kmalloc include/linux/kasan.h:211 [inline] + __do_kmalloc_node mm/slub.c:3981 [inline] + __kmalloc+0x22e/0x490 mm/slub.c:3994 + kmalloc include/linux/slab.h:594 [inline] + kzalloc include/linux/slab.h:711 [inline] + fib6_info_alloc+0x2e/0xf0 net/ipv6/ip6_fib.c:155 + ip6_route_info_create+0x445/0x12b0 net/ipv6/route.c:3758 + ip6_route_multipath_add net/ipv6/route.c:5298 [inline] + inet6_rtm_newroute+0x744/0x2300 net/ipv6/route.c:5517 + rtnetlink_rcv_msg+0x885/0x1040 net/core/rtnetlink.c:6597 + netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2543 + netlink_unicast_kernel net/netlink/af_netlink.c:1341 [inline] + netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1367 + netlink_sendmsg+0xa3b/0xd70 net/netlink/af_netlink.c:1908 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:745 + ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584 + ___sys_sendmsg net/socket.c:2638 [inline] + __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667 + do_syscall_64+0xf9/0x240 + entry_SYSCALL_64_after_hwframe+0x6f/0x77 + +Freed by task 16: + kasan_save_stack mm/kasan/common.c:47 [inline] + kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 + kasan_save_free_info+0x4e/0x60 mm/kasan/generic.c:640 + poison_slab_object+0xa6/0xe0 mm/kasan/common.c:241 + __kasan_slab_free+0x34/0x70 mm/kasan/common.c:257 + kasan_slab_free include/linux/kasan.h:184 [inline] + slab_free_hook mm/slub.c:2121 [inline] + slab_free mm/slub.c:4299 [inline] + kfree+0x14a/0x380 mm/slub.c:4409 + rcu_do_batch kernel/rcu/tree.c:2190 [inline] + rcu_core+0xd76/0x1810 kernel/rcu/tree.c:2465 + __do_softirq+0x2bb/0x942 kernel/softirq.c:553 + +Last potentially related work creation: + kasan_save_stack+0x3f/0x60 mm/kasan/common.c:47 + __kasan_record_aux_stack+0xae/0x100 mm/kasan/generic.c:586 + __call_rcu_common kernel/rcu/tree.c:2715 [inline] + call_rcu+0x167/0xa80 kernel/rcu/tree.c:2829 + fib6_info_release include/net/ip6_fib.h:341 [inline] + ip6_route_multipath_add net/ipv6/route.c:5344 [inline] + inet6_rtm_newroute+0x114d/0x2300 net/ipv6/route.c:5517 + rtnetlink_rcv_msg+0x885/0x1040 net/core/rtnetlink.c:6597 + netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2543 + netlink_unicast_kernel net/netlink/af_netlink.c:1341 [inline] + netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1367 + netlink_sendmsg+0xa3b/0xd70 net/netlink/af_netlink.c:1908 + sock_sendmsg_nosec net/socket.c:730 [inline] + __sock_sendmsg+0x221/0x270 net/socket.c:745 + ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584 + ___sys_sendmsg net/socket.c:2638 [inline] + __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667 + do_syscall_64+0xf9/0x240 + entry_SYSCALL_64_after_hwframe+0x6f/0x77 + +The buggy address belongs to the object at ffff88809a07fc00 + which belongs to the cache kmalloc-512 of size 512 +The buggy address is located 100 bytes inside of + freed 512-byte region [ffff88809a07fc00, ffff88809a07fe00) + +The buggy address belongs to the physical page: +page:ffffea0002681f00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x9a07c +head:ffffea0002681f00 order:2 entire_mapcount:0 nr_pages_mapped:0 pincount:0 +flags: 0xfff00000000840(slab|head|node=0|zone=1|lastcpupid=0x7ff) +page_type: 0xffffffff() +raw: 00fff00000000840 ffff888014c41c80 dead000000000122 0000000000000000 +raw: 0000000000000000 0000000080100010 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected +page_owner tracks the page as allocated +page last allocated via order 2, migratetype Unmovable, gfp_mask 0x1d20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC|__GFP_HARDWALL), pid 23028, tgid 23027 (syz-executor.4), ts 2340253595219, free_ts 2339107097036 + set_page_owner include/linux/page_owner.h:31 [inline] + post_alloc_hook+0x1ea/0x210 mm/page_alloc.c:1533 + prep_new_page mm/page_alloc.c:1540 [inline] + get_page_from_freelist+0x33ea/0x3580 mm/page_alloc.c:3311 + __alloc_pages+0x255/0x680 mm/page_alloc.c:4567 + __alloc_pages_node include/linux/gfp.h:238 [inline] + alloc_pages_node include/linux/gfp.h:261 [inline] + alloc_slab_page+0x5f/0x160 mm/slub.c:2190 + allocate_slab mm/slub.c:2354 [inline] + new_slab+0x84/0x2f0 mm/slub.c:2407 + ___slab_alloc+0xd17/0x13e0 mm/slub.c:3540 + __slab_alloc mm/slub.c:3625 [inline] + __slab_alloc_node mm/slub.c:3678 [inline] + slab_alloc_node mm/slub.c:3850 [inline] + __do_kmalloc_node mm/slub.c:3980 [inline] + __kmalloc+0x2e0/0x490 mm/slub.c:3994 + kmalloc include/linux/slab.h:594 [inline] + kzalloc include/linux/slab.h:711 [inline] + new_dir fs/proc/proc_sysctl.c:956 [inline] + get_subdir fs/proc/proc_sysctl.c:1000 [inline] + sysctl_mkdir_p fs/proc/proc_sysctl.c:1295 [inline] + __register_sysctl_table+0xb30/0x1440 fs/proc/proc_sysctl.c:1376 + neigh_sysctl_register+0x416/0x500 net/core/neighbour.c:3859 + devinet_sysctl_register+0xaf/0x1f0 net/ipv4/devinet.c:2644 + inetdev_init+0x296/0x4d0 net/ipv4/devinet.c:286 + inetdev_event+0x338/0x15c0 net/ipv4/devinet.c:1555 + notifier_call_chain+0x18f/0x3b0 kernel/notifier.c:93 + call_netdevice_notifiers_extack net/core/dev.c:1987 [inline] + call_netdevice_notifiers net/core/dev.c:2001 [inline] + register_netdevice+0x15b2/0x1a20 net/core/dev.c:10340 + br_dev_newlink+0x27/0x100 net/bridge/br_netlink.c:1563 + rtnl_newlink_create net/core/rtnetlink.c:3497 [inline] + __rtnl_newlink net/core/rtnetlink.c:3717 [inline] + rtnl_newlink+0x158f/0x20a0 net/core/rtnetlink.c:3730 +page last free pid 11583 tgid 11583 stack trace: + reset_page_owner include/linux/page_owner.h:24 [inline] + free_pages_prepare mm/page_alloc.c:1140 [inline] + free_unref_page_prepare+0x968/0xa90 mm/page_alloc.c:2346 + free_unref_page+0x37/0x3f0 mm/page_alloc.c:2486 + kasan_depopulate_vmalloc_pte+0x74/0x90 mm/kasan/shadow.c:415 + apply_to_pte_range mm/memory.c:2619 [inline] + apply_to_pmd_range mm/memory.c:2663 [inline] + apply_to_pud_range mm/memory.c:2699 [inline] + apply_to_p4d_range mm/memory.c:2735 [inline] + __apply_to_page_range+0x8ec/0xe40 mm/memory.c:2769 + kasan_release_vmalloc+0x9a/0xb0 mm/kasan/shadow.c:532 + __purge_vmap_area_lazy+0x163f/0x1a10 mm/vmalloc.c:1770 + drain_vmap_area_work+0x40/0xd0 mm/vmalloc.c:1804 + process_one_work kernel/workqueue.c:2633 [inline] + process_scheduled_works+0x913/0x1420 kernel/workqueue.c:2706 + worker_thread+0xa5f/0x1000 kernel/workqueue.c:2787 + kthread+0x2ef/0x390 kernel/kthread.c:388 + ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1b/0x30 arch/x86/entry/entry_64.S:242 + +Memory state around the buggy address: + ffff88809a07fb00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff88809a07fb80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +>ffff88809a07fc00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff88809a07fc80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff88809a07fd00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + +Fixes: 3b1137fe7482 ("net: ipv6: Change notifications for multipath add to RTA_MULTIPATH") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20240303144801.702646-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 21 +++++++-------------- + 1 file changed, 7 insertions(+), 14 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 9dbc9c0cbc5a3..b4d9acb1bc101 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -4516,25 +4516,19 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, + err_nh = NULL; + list_for_each_entry(nh, &rt6_nh_list, next) { + err = __ip6_ins_rt(nh->fib6_info, info, extack); +- fib6_info_release(nh->fib6_info); +- +- if (!err) { +- /* save reference to last route successfully inserted */ +- rt_last = nh->fib6_info; +- +- /* save reference to first route for notification */ +- if (!rt_notif) +- rt_notif = nh->fib6_info; +- } + +- /* nh->fib6_info is used or freed at this point, reset to NULL*/ +- nh->fib6_info = NULL; + if (err) { + if (replace && nhn) + ip6_print_replace_route_err(&rt6_nh_list); + err_nh = nh; + goto add_errout; + } ++ /* save reference to last route successfully inserted */ ++ rt_last = nh->fib6_info; ++ ++ /* save reference to first route for notification */ ++ if (!rt_notif) ++ rt_notif = nh->fib6_info; + + /* Because each route is added like a single route we remove + * these flags after the first nexthop: if there is a collision, +@@ -4572,8 +4566,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, + + cleanup: + list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) { +- if (nh->fib6_info) +- fib6_info_release(nh->fib6_info); ++ fib6_info_release(nh->fib6_info); + list_del(&nh->next); + kfree(nh); + } +-- +2.43.0 + diff --git a/queue-4.19/net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch b/queue-4.19/net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch new file mode 100644 index 00000000000..8c4f0823fa1 --- /dev/null +++ b/queue-4.19/net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch @@ -0,0 +1,45 @@ +From 5a186077bc2a0c4b6cc8f02bdfed968dc0342acd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Feb 2024 13:45:17 +0100 +Subject: net: lan78xx: fix runtime PM count underflow on link stop + +From: Oleksij Rempel + +[ Upstream commit 1eecc7ab82c42133b748e1895275942a054a7f67 ] + +Current driver has some asymmetry in the runtime PM calls. On lan78xx_open() +it will call usb_autopm_get() and unconditionally usb_autopm_put(). And +on lan78xx_stop() it will call only usb_autopm_put(). So far, it was +working only because this driver do not activate autosuspend by default, +so it was visible only by warning "Runtime PM usage count underflow!". + +Since, with current driver, we can't use runtime PM with active link, +execute lan78xx_open()->usb_autopm_put() only in error case. Otherwise, +keep ref counting high as long as interface is open. + +Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver") +Signed-off-by: Oleksij Rempel +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index 52d1d922f6c5e..f56f45c924de0 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -2940,7 +2940,8 @@ static int lan78xx_open(struct net_device *net) + done: + mutex_unlock(&dev->dev_mutex); + +- usb_autopm_put_interface(dev->intf); ++ if (ret < 0) ++ usb_autopm_put_interface(dev->intf); + + return ret; + } +-- +2.43.0 + diff --git a/queue-4.19/net-move-definition-of-pcpu_lstats-to-header-file.patch b/queue-4.19/net-move-definition-of-pcpu_lstats-to-header-file.patch new file mode 100644 index 00000000000..6364dbc219d --- /dev/null +++ b/queue-4.19/net-move-definition-of-pcpu_lstats-to-header-file.patch @@ -0,0 +1,117 @@ +From 75ebf0a18315b800c6f73d8807e353e52ec4be05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Sep 2018 16:00:51 +0800 +Subject: net: move definition of pcpu_lstats to header file + +From: Li RongQing + +[ Upstream commit 52bb6677d530d37055092d86b4eab69dce6c166a ] + +pcpu_lstats is defined in several files, so unify them as one +and move to header file + +Signed-off-by: Zhang Yu +Signed-off-by: Li RongQing +Signed-off-by: David S. Miller +Stable-dep-of: 1ca1ba465e55 ("geneve: make sure to pull inner header in geneve_rx()") +Signed-off-by: Sasha Levin +--- + drivers/net/loopback.c | 6 ------ + drivers/net/nlmon.c | 6 ------ + drivers/net/vsockmon.c | 14 ++++---------- + include/linux/netdevice.h | 6 ++++++ + 4 files changed, 10 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c +index 7863918592db9..954935a38f186 100644 +--- a/drivers/net/loopback.c ++++ b/drivers/net/loopback.c +@@ -59,12 +59,6 @@ + #include + #include + +-struct pcpu_lstats { +- u64 packets; +- u64 bytes; +- struct u64_stats_sync syncp; +-}; +- + /* The higher levels take care of making this non-reentrant (it's + * called with bh's disabled). + */ +diff --git a/drivers/net/nlmon.c b/drivers/net/nlmon.c +index 4b22955de1918..dd0db7534cb32 100644 +--- a/drivers/net/nlmon.c ++++ b/drivers/net/nlmon.c +@@ -6,12 +6,6 @@ + #include + #include + +-struct pcpu_lstats { +- u64 packets; +- u64 bytes; +- struct u64_stats_sync syncp; +-}; +- + static netdev_tx_t nlmon_xmit(struct sk_buff *skb, struct net_device *dev) + { + int len = skb->len; +diff --git a/drivers/net/vsockmon.c b/drivers/net/vsockmon.c +index c28bdce14fd5e..7bad5c95551fd 100644 +--- a/drivers/net/vsockmon.c ++++ b/drivers/net/vsockmon.c +@@ -11,12 +11,6 @@ + #define DEFAULT_MTU (VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + \ + sizeof(struct af_vsockmon_hdr)) + +-struct pcpu_lstats { +- u64 rx_packets; +- u64 rx_bytes; +- struct u64_stats_sync syncp; +-}; +- + static int vsockmon_dev_init(struct net_device *dev) + { + dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats); +@@ -56,8 +50,8 @@ static netdev_tx_t vsockmon_xmit(struct sk_buff *skb, struct net_device *dev) + struct pcpu_lstats *stats = this_cpu_ptr(dev->lstats); + + u64_stats_update_begin(&stats->syncp); +- stats->rx_bytes += len; +- stats->rx_packets++; ++ stats->bytes += len; ++ stats->packets++; + u64_stats_update_end(&stats->syncp); + + dev_kfree_skb(skb); +@@ -80,8 +74,8 @@ vsockmon_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) + + do { + start = u64_stats_fetch_begin_irq(&vstats->syncp); +- tbytes = vstats->rx_bytes; +- tpackets = vstats->rx_packets; ++ tbytes = vstats->bytes; ++ tpackets = vstats->packets; + } while (u64_stats_fetch_retry_irq(&vstats->syncp, start)); + + packets += tpackets; +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index ac87fcc4d44b4..89155d171b567 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -2383,6 +2383,12 @@ struct pcpu_sw_netstats { + struct u64_stats_sync syncp; + }; + ++struct pcpu_lstats { ++ u64 packets; ++ u64 bytes; ++ struct u64_stats_sync syncp; ++}; ++ + #define __netdev_alloc_pcpu_stats(type, gfp) \ + ({ \ + typeof(type) __percpu *pcpu_stats = alloc_percpu_gfp(type, gfp);\ +-- +2.43.0 + diff --git a/queue-4.19/net-rds-fix-warning-in-rds_conn_connect_if_down.patch b/queue-4.19/net-rds-fix-warning-in-rds_conn_connect_if_down.patch new file mode 100644 index 00000000000..e4eb9f24bde --- /dev/null +++ b/queue-4.19/net-rds-fix-warning-in-rds_conn_connect_if_down.patch @@ -0,0 +1,57 @@ +From 0f13ae6fcac25828b7bcfebb90cd1f8cb44c4f94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 08:13:08 +0800 +Subject: net/rds: fix WARNING in rds_conn_connect_if_down + +From: Edward Adam Davis + +[ Upstream commit c055fc00c07be1f0df7375ab0036cebd1106ed38 ] + +If connection isn't established yet, get_mr() will fail, trigger connection after +get_mr(). + +Fixes: 584a8279a44a ("RDS: RDMA: return appropriate error on rdma map failures") +Reported-and-tested-by: syzbot+d4faee732755bba9838e@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/rds/rdma.c | 3 +++ + net/rds/send.c | 6 +----- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/net/rds/rdma.c b/net/rds/rdma.c +index 9882cebfcad60..2632f3f3aa284 100644 +--- a/net/rds/rdma.c ++++ b/net/rds/rdma.c +@@ -278,6 +278,9 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args, + put_page(sg_page(&sg[i])); + kfree(sg); + ret = PTR_ERR(trans_private); ++ /* Trigger connection so that its ready for the next retry */ ++ if (ret == -ENODEV) ++ rds_conn_connect_if_down(cp->cp_conn); + goto out; + } + +diff --git a/net/rds/send.c b/net/rds/send.c +index 26e2c2305f7aa..c856e6c963af9 100644 +--- a/net/rds/send.c ++++ b/net/rds/send.c +@@ -1300,12 +1300,8 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) + + /* Parse any control messages the user may have included. */ + ret = rds_cmsg_send(rs, rm, msg, &allocated_mr, &vct); +- if (ret) { +- /* Trigger connection so that its ready for the next retry */ +- if (ret == -EAGAIN) +- rds_conn_connect_if_down(conn); ++ if (ret) + goto out; +- } + + if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) { + printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n", +-- +2.43.0 + diff --git a/queue-4.19/net-usb-lan78xx-remove-lots-of-set-but-unused-ret-va.patch b/queue-4.19/net-usb-lan78xx-remove-lots-of-set-but-unused-ret-va.patch new file mode 100644 index 00000000000..f0b452f095e --- /dev/null +++ b/queue-4.19/net-usb-lan78xx-remove-lots-of-set-but-unused-ret-va.patch @@ -0,0 +1,540 @@ +From 185258f6f83f53caf34918be842ec90aef48fc44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 2 Nov 2020 11:45:06 +0000 +Subject: net: usb: lan78xx: Remove lots of set but unused 'ret' variables +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lee Jones + +[ Upstream commit 06cd7c46b3ab3f2252c61bf85b191236cf0254e1 ] + +Fixes the following W=1 kernel build warning(s): + + drivers/net/usb/lan78xx.c: In function ‘lan78xx_read_raw_otp’: + drivers/net/usb/lan78xx.c:825:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_write_raw_otp’: + drivers/net/usb/lan78xx.c:879:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_deferred_multicast_write’: + drivers/net/usb/lan78xx.c:1041:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_update_flowcontrol’: + drivers/net/usb/lan78xx.c:1127:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_init_mac_address’: + drivers/net/usb/lan78xx.c:1666:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_link_status_change’: + drivers/net/usb/lan78xx.c:1841:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_irq_bus_sync_unlock’: + drivers/net/usb/lan78xx.c:1920:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan8835_fixup’: + drivers/net/usb/lan78xx.c:1994:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_rx_max_frame_length’: + drivers/net/usb/lan78xx.c:2192:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_change_mtu’: + drivers/net/usb/lan78xx.c:2270:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_mac_addr’: + drivers/net/usb/lan78xx.c:2299:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_features’: + drivers/net/usb/lan78xx.c:2333:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + drivers/net/usb/lan78xx.c: In function ‘lan78xx_set_suspend’: + drivers/net/usb/lan78xx.c:3807:6: warning: variable ‘ret’ set but not used [-Wunused-but-set-variable] + +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20201102114512.1062724-25-lee.jones@linaro.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 1eecc7ab82c4 ("net: lan78xx: fix runtime PM count underflow on link stop") +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 168 ++++++++++++++++++-------------------- + 1 file changed, 78 insertions(+), 90 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index c0fff40a98bb8..4d94af63cf190 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -835,20 +835,19 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, + u32 length, u8 *data) + { + int i; +- int ret; + u32 buf; + unsigned long timeout; + +- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf); ++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf); + + if (buf & OTP_PWR_DN_PWRDN_N_) { + /* clear it and wait to be cleared */ +- ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0); ++ lan78xx_write_reg(dev, OTP_PWR_DN, 0); + + timeout = jiffies + HZ; + do { + usleep_range(1, 10); +- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf); ++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf); + if (time_after(jiffies, timeout)) { + netdev_warn(dev->net, + "timeout on OTP_PWR_DN"); +@@ -858,18 +857,18 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, + } + + for (i = 0; i < length; i++) { +- ret = lan78xx_write_reg(dev, OTP_ADDR1, ++ lan78xx_write_reg(dev, OTP_ADDR1, + ((offset + i) >> 8) & OTP_ADDR1_15_11); +- ret = lan78xx_write_reg(dev, OTP_ADDR2, ++ lan78xx_write_reg(dev, OTP_ADDR2, + ((offset + i) & OTP_ADDR2_10_3)); + +- ret = lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_); +- ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_); ++ lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_); ++ lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_); + + timeout = jiffies + HZ; + do { + udelay(1); +- ret = lan78xx_read_reg(dev, OTP_STATUS, &buf); ++ lan78xx_read_reg(dev, OTP_STATUS, &buf); + if (time_after(jiffies, timeout)) { + netdev_warn(dev->net, + "timeout on OTP_STATUS"); +@@ -877,7 +876,7 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset, + } + } while (buf & OTP_STATUS_BUSY_); + +- ret = lan78xx_read_reg(dev, OTP_RD_DATA, &buf); ++ lan78xx_read_reg(dev, OTP_RD_DATA, &buf); + + data[i] = (u8)(buf & 0xFF); + } +@@ -889,20 +888,19 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset, + u32 length, u8 *data) + { + int i; +- int ret; + u32 buf; + unsigned long timeout; + +- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf); ++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf); + + if (buf & OTP_PWR_DN_PWRDN_N_) { + /* clear it and wait to be cleared */ +- ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0); ++ lan78xx_write_reg(dev, OTP_PWR_DN, 0); + + timeout = jiffies + HZ; + do { + udelay(1); +- ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf); ++ lan78xx_read_reg(dev, OTP_PWR_DN, &buf); + if (time_after(jiffies, timeout)) { + netdev_warn(dev->net, + "timeout on OTP_PWR_DN completion"); +@@ -912,21 +910,21 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset, + } + + /* set to BYTE program mode */ +- ret = lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_); ++ lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_); + + for (i = 0; i < length; i++) { +- ret = lan78xx_write_reg(dev, OTP_ADDR1, ++ lan78xx_write_reg(dev, OTP_ADDR1, + ((offset + i) >> 8) & OTP_ADDR1_15_11); +- ret = lan78xx_write_reg(dev, OTP_ADDR2, ++ lan78xx_write_reg(dev, OTP_ADDR2, + ((offset + i) & OTP_ADDR2_10_3)); +- ret = lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]); +- ret = lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_); +- ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_); ++ lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]); ++ lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_); ++ lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_); + + timeout = jiffies + HZ; + do { + udelay(1); +- ret = lan78xx_read_reg(dev, OTP_STATUS, &buf); ++ lan78xx_read_reg(dev, OTP_STATUS, &buf); + if (time_after(jiffies, timeout)) { + netdev_warn(dev->net, + "Timeout on OTP_STATUS completion"); +@@ -1051,7 +1049,6 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param) + container_of(param, struct lan78xx_priv, set_multicast); + struct lan78xx_net *dev = pdata->dev; + int i; +- int ret; + + netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n", + pdata->rfe_ctl); +@@ -1060,14 +1057,14 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param) + DP_SEL_VHF_HASH_LEN, pdata->mchash_table); + + for (i = 1; i < NUM_OF_MAF; i++) { +- ret = lan78xx_write_reg(dev, MAF_HI(i), 0); +- ret = lan78xx_write_reg(dev, MAF_LO(i), ++ lan78xx_write_reg(dev, MAF_HI(i), 0); ++ lan78xx_write_reg(dev, MAF_LO(i), + pdata->pfilter_table[i][1]); +- ret = lan78xx_write_reg(dev, MAF_HI(i), ++ lan78xx_write_reg(dev, MAF_HI(i), + pdata->pfilter_table[i][0]); + } + +- ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); ++ lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); + } + + static void lan78xx_set_multicast(struct net_device *netdev) +@@ -1137,7 +1134,6 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, + u16 lcladv, u16 rmtadv) + { + u32 flow = 0, fct_flow = 0; +- int ret; + u8 cap; + + if (dev->fc_autoneg) +@@ -1160,10 +1156,10 @@ static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, + (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), + (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); + +- ret = lan78xx_write_reg(dev, FCT_FLOW, fct_flow); ++ lan78xx_write_reg(dev, FCT_FLOW, fct_flow); + + /* threshold value should be set before enabling flow */ +- ret = lan78xx_write_reg(dev, FLOW, flow); ++ lan78xx_write_reg(dev, FLOW, flow); + + return 0; + } +@@ -1694,11 +1690,10 @@ static int lan78xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + static void lan78xx_init_mac_address(struct lan78xx_net *dev) + { + u32 addr_lo, addr_hi; +- int ret; + u8 addr[6]; + +- ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo); +- ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi); ++ lan78xx_read_reg(dev, RX_ADDRL, &addr_lo); ++ lan78xx_read_reg(dev, RX_ADDRH, &addr_hi); + + addr[0] = addr_lo & 0xFF; + addr[1] = (addr_lo >> 8) & 0xFF; +@@ -1731,12 +1726,12 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev) + (addr[2] << 16) | (addr[3] << 24); + addr_hi = addr[4] | (addr[5] << 8); + +- ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo); +- ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi); ++ lan78xx_write_reg(dev, RX_ADDRL, addr_lo); ++ lan78xx_write_reg(dev, RX_ADDRH, addr_hi); + } + +- ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo); +- ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_); ++ lan78xx_write_reg(dev, MAF_LO(0), addr_lo); ++ lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_); + + ether_addr_copy(dev->net->dev_addr, addr); + } +@@ -1870,7 +1865,7 @@ static void lan78xx_remove_mdio(struct lan78xx_net *dev) + static void lan78xx_link_status_change(struct net_device *net) + { + struct phy_device *phydev = net->phydev; +- int ret, temp; ++ int temp; + + /* At forced 100 F/H mode, chip may fail to set mode correctly + * when cable is switched between long(~50+m) and short one. +@@ -1881,7 +1876,7 @@ static void lan78xx_link_status_change(struct net_device *net) + /* disable phy interrupt */ + temp = phy_read(phydev, LAN88XX_INT_MASK); + temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_; +- ret = phy_write(phydev, LAN88XX_INT_MASK, temp); ++ phy_write(phydev, LAN88XX_INT_MASK, temp); + + temp = phy_read(phydev, MII_BMCR); + temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000); +@@ -1895,7 +1890,7 @@ static void lan78xx_link_status_change(struct net_device *net) + /* enable phy interrupt back */ + temp = phy_read(phydev, LAN88XX_INT_MASK); + temp |= LAN88XX_INT_MASK_MDINTPIN_EN_; +- ret = phy_write(phydev, LAN88XX_INT_MASK, temp); ++ phy_write(phydev, LAN88XX_INT_MASK, temp); + } + } + +@@ -1949,14 +1944,13 @@ static void lan78xx_irq_bus_sync_unlock(struct irq_data *irqd) + struct lan78xx_net *dev = + container_of(data, struct lan78xx_net, domain_data); + u32 buf; +- int ret; + + /* call register access here because irq_bus_lock & irq_bus_sync_unlock + * are only two callbacks executed in non-atomic contex. + */ +- ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf); ++ lan78xx_read_reg(dev, INT_EP_CTL, &buf); + if (buf != data->irqenable) +- ret = lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable); ++ lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable); + + mutex_unlock(&data->irq_lock); + } +@@ -2023,7 +2017,6 @@ static void lan78xx_remove_irq_domain(struct lan78xx_net *dev) + static int lan8835_fixup(struct phy_device *phydev) + { + int buf; +- int ret; + struct lan78xx_net *dev = netdev_priv(phydev->attached_dev); + + /* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */ +@@ -2033,11 +2026,11 @@ static int lan8835_fixup(struct phy_device *phydev) + phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8010, buf); + + /* RGMII MAC TXC Delay Enable */ +- ret = lan78xx_write_reg(dev, MAC_RGMII_ID, ++ lan78xx_write_reg(dev, MAC_RGMII_ID, + MAC_RGMII_ID_TXC_DELAY_EN_); + + /* RGMII TX DLL Tune Adjust */ +- ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); ++ lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); + + dev->interface = PHY_INTERFACE_MODE_RGMII_TXID; + +@@ -2217,28 +2210,27 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) + + static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size) + { +- int ret = 0; + u32 buf; + bool rxenabled; + +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ lan78xx_read_reg(dev, MAC_RX, &buf); + + rxenabled = ((buf & MAC_RX_RXEN_) != 0); + + if (rxenabled) { + buf &= ~MAC_RX_RXEN_; +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ lan78xx_write_reg(dev, MAC_RX, buf); + } + + /* add 4 to size for FCS */ + buf &= ~MAC_RX_MAX_SIZE_MASK_; + buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT_) & MAC_RX_MAX_SIZE_MASK_); + +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ lan78xx_write_reg(dev, MAC_RX, buf); + + if (rxenabled) { + buf |= MAC_RX_RXEN_; +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ lan78xx_write_reg(dev, MAC_RX, buf); + } + + return 0; +@@ -2295,13 +2287,12 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu) + int ll_mtu = new_mtu + netdev->hard_header_len; + int old_hard_mtu = dev->hard_mtu; + int old_rx_urb_size = dev->rx_urb_size; +- int ret; + + /* no second zero-length packet read wanted after mtu-sized packets */ + if ((ll_mtu % dev->maxpacket) == 0) + return -EDOM; + +- ret = lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN); ++ lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN); + + netdev->mtu = new_mtu; + +@@ -2324,7 +2315,6 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p) + struct lan78xx_net *dev = netdev_priv(netdev); + struct sockaddr *addr = p; + u32 addr_lo, addr_hi; +- int ret; + + if (netif_running(netdev)) + return -EBUSY; +@@ -2341,12 +2331,12 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p) + addr_hi = netdev->dev_addr[4] | + netdev->dev_addr[5] << 8; + +- ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo); +- ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi); ++ lan78xx_write_reg(dev, RX_ADDRL, addr_lo); ++ lan78xx_write_reg(dev, RX_ADDRH, addr_hi); + + /* Added to support MAC address changes */ +- ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo); +- ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_); ++ lan78xx_write_reg(dev, MAF_LO(0), addr_lo); ++ lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_); + + return 0; + } +@@ -2358,7 +2348,6 @@ static int lan78xx_set_features(struct net_device *netdev, + struct lan78xx_net *dev = netdev_priv(netdev); + struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]); + unsigned long flags; +- int ret; + + spin_lock_irqsave(&pdata->rfe_ctl_lock, flags); + +@@ -2382,7 +2371,7 @@ static int lan78xx_set_features(struct net_device *netdev, + + spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags); + +- ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); ++ lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl); + + return 0; + } +@@ -3846,7 +3835,6 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int len) + static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + { + u32 buf; +- int ret; + int mask_index; + u16 crc; + u32 temp_wucsr; +@@ -3855,26 +3843,26 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + const u8 ipv6_multicast[3] = { 0x33, 0x33 }; + const u8 arp_type[2] = { 0x08, 0x06 }; + +- ret = lan78xx_read_reg(dev, MAC_TX, &buf); ++ lan78xx_read_reg(dev, MAC_TX, &buf); + buf &= ~MAC_TX_TXEN_; +- ret = lan78xx_write_reg(dev, MAC_TX, buf); +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ lan78xx_write_reg(dev, MAC_TX, buf); ++ lan78xx_read_reg(dev, MAC_RX, &buf); + buf &= ~MAC_RX_RXEN_; +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ lan78xx_write_reg(dev, MAC_RX, buf); + +- ret = lan78xx_write_reg(dev, WUCSR, 0); +- ret = lan78xx_write_reg(dev, WUCSR2, 0); +- ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); ++ lan78xx_write_reg(dev, WUCSR, 0); ++ lan78xx_write_reg(dev, WUCSR2, 0); ++ lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL); + + temp_wucsr = 0; + + temp_pmt_ctl = 0; +- ret = lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl); ++ lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl); + temp_pmt_ctl &= ~PMT_CTL_RES_CLR_WKP_EN_; + temp_pmt_ctl |= PMT_CTL_RES_CLR_WKP_STS_; + + for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++) +- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_CFG(mask_index), 0); + + mask_index = 0; + if (wol & WAKE_PHY) { +@@ -3903,30 +3891,30 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + + /* set WUF_CFG & WUF_MASK for IPv4 Multicast */ + crc = lan78xx_wakeframe_crc16(ipv4_multicast, 3); +- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), ++ lan78xx_write_reg(dev, WUF_CFG(mask_index), + WUF_CFGX_EN_ | + WUF_CFGX_TYPE_MCAST_ | + (0 << WUF_CFGX_OFFSET_SHIFT_) | + (crc & WUF_CFGX_CRC16_MASK_)); + +- ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7); +- ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +- ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); +- ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7); ++ lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); + mask_index++; + + /* for IPv6 Multicast */ + crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2); +- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), ++ lan78xx_write_reg(dev, WUF_CFG(mask_index), + WUF_CFGX_EN_ | + WUF_CFGX_TYPE_MCAST_ | + (0 << WUF_CFGX_OFFSET_SHIFT_) | + (crc & WUF_CFGX_CRC16_MASK_)); + +- ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3); +- ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +- ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); +- ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3); ++ lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); + mask_index++; + + temp_pmt_ctl |= PMT_CTL_WOL_EN_; +@@ -3947,16 +3935,16 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + * for packettype (offset 12,13) = ARP (0x0806) + */ + crc = lan78xx_wakeframe_crc16(arp_type, 2); +- ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), ++ lan78xx_write_reg(dev, WUF_CFG(mask_index), + WUF_CFGX_EN_ | + WUF_CFGX_TYPE_ALL_ | + (0 << WUF_CFGX_OFFSET_SHIFT_) | + (crc & WUF_CFGX_CRC16_MASK_)); + +- ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000); +- ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); +- ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); +- ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000); ++ lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0); ++ lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0); + mask_index++; + + temp_pmt_ctl |= PMT_CTL_WOL_EN_; +@@ -3964,7 +3952,7 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_; + } + +- ret = lan78xx_write_reg(dev, WUCSR, temp_wucsr); ++ lan78xx_write_reg(dev, WUCSR, temp_wucsr); + + /* when multiple WOL bits are set */ + if (hweight_long((unsigned long)wol) > 1) { +@@ -3972,16 +3960,16 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol) + temp_pmt_ctl &= ~PMT_CTL_SUS_MODE_MASK_; + temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_; + } +- ret = lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl); ++ lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl); + + /* clear WUPS */ +- ret = lan78xx_read_reg(dev, PMT_CTL, &buf); ++ lan78xx_read_reg(dev, PMT_CTL, &buf); + buf |= PMT_CTL_WUPS_MASK_; +- ret = lan78xx_write_reg(dev, PMT_CTL, buf); ++ lan78xx_write_reg(dev, PMT_CTL, buf); + +- ret = lan78xx_read_reg(dev, MAC_RX, &buf); ++ lan78xx_read_reg(dev, MAC_RX, &buf); + buf |= MAC_RX_RXEN_; +- ret = lan78xx_write_reg(dev, MAC_RX, buf); ++ lan78xx_write_reg(dev, MAC_RX, buf); + + return 0; + } +-- +2.43.0 + diff --git a/queue-4.19/netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch b/queue-4.19/netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch new file mode 100644 index 00000000000..cf5d37918d2 --- /dev/null +++ b/queue-4.19/netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch @@ -0,0 +1,71 @@ +From 65c0b33d6b1b3122636d0365525a982ccfd2d9d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 11:38:55 +0000 +Subject: netfilter: nf_conntrack_h323: Add protection for bmp length out of + range + +From: Lena Wang + +[ Upstream commit 767146637efc528b5e3d31297df115e85a2fd362 ] + +UBSAN load reports an exception of BRK#5515 SHIFT_ISSUE:Bitwise shifts +that are out of bounds for their data type. + +vmlinux get_bitmap(b=75) + 712 + +vmlinux decode_seq(bs=0xFFFFFFD008037000, f=0xFFFFFFD008037018, level=134443100) + 1956 + +vmlinux decode_choice(base=0xFFFFFFD0080370F0, level=23843636) + 1216 + +vmlinux decode_seq(f=0xFFFFFFD0080371A8, level=134443500) + 812 + +vmlinux decode_choice(base=0xFFFFFFD008037280, level=0) + 1216 + +vmlinux DecodeRasMessage() + 304 + +vmlinux ras_help() + 684 + +vmlinux nf_confirm() + 188 + + +Due to abnormal data in skb->data, the extension bitmap length +exceeds 32 when decoding ras message then uses the length to make +a shift operation. It will change into negative after several loop. +UBSAN load could detect a negative shift as an undefined behaviour +and reports exception. +So we add the protection to avoid the length exceeding 32. Or else +it will return out of range error and stop decoding. + +Fixes: 5e35941d9901 ("[NETFILTER]: Add H.323 conntrack/NAT helper") +Signed-off-by: Lena Wang +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_h323_asn1.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c +index 4c2ef42e189cb..82dae553a5fc7 100644 +--- a/net/netfilter/nf_conntrack_h323_asn1.c ++++ b/net/netfilter/nf_conntrack_h323_asn1.c +@@ -536,6 +536,8 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, + /* Get fields bitmap */ + if (nf_h323_error_boundary(bs, 0, f->sz)) + return H323_ERROR_BOUND; ++ if (f->sz > 32) ++ return H323_ERROR_RANGE; + bmp = get_bitmap(bs, f->sz); + if (base) + *(unsigned int *)base = bmp; +@@ -592,6 +594,8 @@ static int decode_seq(struct bitstr *bs, const struct field_t *f, + bmp2_len = get_bits(bs, 7) + 1; + if (nf_h323_error_boundary(bs, 0, bmp2_len)) + return H323_ERROR_BOUND; ++ if (bmp2_len > 32) ++ return H323_ERROR_RANGE; + bmp2 = get_bitmap(bs, bmp2_len); + bmp |= bmp2 >> f->sz; + if (base) +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_default_.patch b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_default_.patch new file mode 100644 index 00000000000..410bf859d8f --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_default_.patch @@ -0,0 +1,36 @@ +From a623b79ddbbda55c083ac3bd192893f027a271a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:35 +0800 +Subject: netrom: Fix a data-race around sysctl_netrom_default_path_quality + +From: Jason Xing + +[ Upstream commit 958d6145a6d9ba9e075c921aead8753fb91c9101 ] + +We need to protect the reader reading sysctl_netrom_default_path_quality +because the value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c +index 53ced34a1fdd2..e3ce3531608c4 100644 +--- a/net/netrom/nr_route.c ++++ b/net/netrom/nr_route.c +@@ -156,7 +156,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic, + nr_neigh->digipeat = NULL; + nr_neigh->ax25 = NULL; + nr_neigh->dev = dev; +- nr_neigh->quality = sysctl_netrom_default_path_quality; ++ nr_neigh->quality = READ_ONCE(sysctl_netrom_default_path_quality); + nr_neigh->locked = 0; + nr_neigh->count = 0; + nr_neigh->number = nr_neigh_no++; +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch new file mode 100644 index 00000000000..1f0d3ba9a92 --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch @@ -0,0 +1,36 @@ +From bff887068984aa774be5dab360a4038823c41360 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:45 +0800 +Subject: netrom: Fix a data-race around sysctl_netrom_link_fails_count + +From: Jason Xing + +[ Upstream commit bc76645ebdd01be9b9994dac39685a3d0f6f7985 ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c +index eb285b12977b7..744c19a7a469c 100644 +--- a/net/netrom/nr_route.c ++++ b/net/netrom/nr_route.c +@@ -728,7 +728,7 @@ void nr_link_failed(ax25_cb *ax25, int reason) + nr_neigh->ax25 = NULL; + ax25_cb_put(ax25); + +- if (++nr_neigh->failed < sysctl_netrom_link_fails_count) { ++ if (++nr_neigh->failed < READ_ONCE(sysctl_netrom_link_fails_count)) { + nr_neigh_put(nr_neigh); + return; + } +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch new file mode 100644 index 00000000000..8e0d91b1a33 --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch @@ -0,0 +1,37 @@ +From 081bd6e5bdcd4171e2c1d150e0ced24f76db78cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:36 +0800 +Subject: netrom: Fix a data-race around + sysctl_netrom_obsolescence_count_initialiser + +From: Jason Xing + +[ Upstream commit cfd9f4a740f772298308b2e6070d2c744fb5cf79 ] + +We need to protect the reader reading the sysctl value +because the value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c +index e3ce3531608c4..929446e246b36 100644 +--- a/net/netrom/nr_route.c ++++ b/net/netrom/nr_route.c +@@ -766,7 +766,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) + if (ax25 != NULL) { + ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat, + ax25->ax25_dev->dev, 0, +- sysctl_netrom_obsolescence_count_initialiser); ++ READ_ONCE(sysctl_netrom_obsolescence_count_initialiser)); + if (ret) + return ret; + } +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch new file mode 100644 index 00000000000..daf18655193 --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch @@ -0,0 +1,36 @@ +From a7708c7c94bd98cd9ec11ecd23edf0d1974f92f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:44 +0800 +Subject: netrom: Fix a data-race around sysctl_netrom_routing_control + +From: Jason Xing + +[ Upstream commit b5dffcb8f71bdd02a4e5799985b51b12f4eeaf76 ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_route.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c +index 929446e246b36..eb285b12977b7 100644 +--- a/net/netrom/nr_route.c ++++ b/net/netrom/nr_route.c +@@ -780,7 +780,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) + return ret; + } + +- if (!sysctl_netrom_routing_control && ax25 != NULL) ++ if (!READ_ONCE(sysctl_netrom_routing_control) && ax25 != NULL) + return 0; + + /* Its Time-To-Live has expired */ +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch new file mode 100644 index 00000000000..ea68adb70e4 --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch @@ -0,0 +1,36 @@ +From c0acd88aa8483351f3e5bd01c4d9810cdd5b7086 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:38 +0800 +Subject: netrom: Fix a data-race around sysctl_netrom_transport_timeout + +From: Jason Xing + +[ Upstream commit 60a7a152abd494ed4f69098cf0f322e6bb140612 ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 146550ce0ac6f..a07652c91f2da 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -456,7 +456,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol, + nr_init_timers(sk); + + nr->t1 = +- msecs_to_jiffies(sysctl_netrom_transport_timeout); ++ msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_timeout)); + nr->t2 = + msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay); + nr->n2 = +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-23382 b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-23382 new file mode 100644 index 00000000000..905e2b145ac --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-23382 @@ -0,0 +1,36 @@ +From b38c239e207db54b1f98c2b5f90c5fb578cf20a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:41 +0800 +Subject: netrom: Fix a data-race around sysctl_netrom_transport_busy_delay + +From: Jason Xing + +[ Upstream commit 43547d8699439a67b78d6bb39015113f7aa360fd ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 05235768566a3..5769fe9c111ed 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -462,7 +462,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol, + nr->n2 = + msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries)); + nr->t4 = +- msecs_to_jiffies(sysctl_netrom_transport_busy_delay); ++ msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay)); + nr->idle = + msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout); + nr->window = sysctl_netrom_transport_requested_window_size; +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-28060 b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-28060 new file mode 100644 index 00000000000..6e2a95f2f49 --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-28060 @@ -0,0 +1,37 @@ +From dac517245bf2e85e26ecefcf837acc640e6c473b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:40 +0800 +Subject: netrom: Fix a data-race around + sysctl_netrom_transport_acknowledge_delay + +From: Jason Xing + +[ Upstream commit 806f462ba9029d41aadf8ec93f2f99c5305deada ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 9d4a1d56badc8..05235768566a3 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -458,7 +458,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol, + nr->t1 = + msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_timeout)); + nr->t2 = +- msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay); ++ msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_acknowledge_delay)); + nr->n2 = + msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries)); + nr->t4 = +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-4591 b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-4591 new file mode 100644 index 00000000000..0bf875a82c1 --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-4591 @@ -0,0 +1,36 @@ +From 6a0e97ca9897c166d66fd604540ab36ff58f631d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:39 +0800 +Subject: netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries + +From: Jason Xing + +[ Upstream commit e799299aafed417cc1f32adccb2a0e5268b3f6d5 ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index a07652c91f2da..9d4a1d56badc8 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -460,7 +460,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol, + nr->t2 = + msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay); + nr->n2 = +- msecs_to_jiffies(sysctl_netrom_transport_maximum_tries); ++ msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries)); + nr->t4 = + msecs_to_jiffies(sysctl_netrom_transport_busy_delay); + nr->idle = +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-5373 b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-5373 new file mode 100644 index 00000000000..b1ac56f6cdd --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-5373 @@ -0,0 +1,37 @@ +From b547c43818854bf4fcc50a719f8b62ed54237ed8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:42 +0800 +Subject: netrom: Fix a data-race around + sysctl_netrom_transport_requested_window_size + +From: Jason Xing + +[ Upstream commit a2e706841488f474c06e9b33f71afc947fb3bf56 ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 5769fe9c111ed..1d4b4d228ca0b 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -465,7 +465,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol, + msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay)); + nr->idle = + msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout); +- nr->window = sysctl_netrom_transport_requested_window_size; ++ nr->window = READ_ONCE(sysctl_netrom_transport_requested_window_size); + + nr->bpqext = 1; + nr->state = NR_STATE_0; +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9711 b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9711 new file mode 100644 index 00000000000..d50e6c1833d --- /dev/null +++ b/queue-4.19/netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9711 @@ -0,0 +1,37 @@ +From c73de21a9afd89df4f563c3e91d48c01919d868f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:43 +0800 +Subject: netrom: Fix a data-race around + sysctl_netrom_transport_no_activity_timeout + +From: Jason Xing + +[ Upstream commit f99b494b40431f0ca416859f2345746199398e2b ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 1d4b4d228ca0b..3277f9a7ed02b 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -464,7 +464,7 @@ static int nr_create(struct net *net, struct socket *sock, int protocol, + nr->t4 = + msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay)); + nr->idle = +- msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout); ++ msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_no_activity_timeout)); + nr->window = READ_ONCE(sysctl_netrom_transport_requested_window_size); + + nr->bpqext = 1; +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-data-races-around-sysctl_net_busy_read.patch b/queue-4.19/netrom-fix-data-races-around-sysctl_net_busy_read.patch new file mode 100644 index 00000000000..3c41d9054ce --- /dev/null +++ b/queue-4.19/netrom-fix-data-races-around-sysctl_net_busy_read.patch @@ -0,0 +1,68 @@ +From edc05925f9c6effed87933fcdad931bcda6a77bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:46 +0800 +Subject: netrom: Fix data-races around sysctl_net_busy_read + +From: Jason Xing + +[ Upstream commit d380ce70058a4ccddc3e5f5c2063165dc07672c6 ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/af_netrom.c | 2 +- + net/netrom/nr_in.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 3277f9a7ed02b..9e48ce56f085c 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -957,7 +957,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) + * G8PZT's Xrouter which is sending packets with command type 7 + * as an extension of the protocol. + */ +- if (sysctl_netrom_reset_circuit && ++ if (READ_ONCE(sysctl_netrom_reset_circuit) && + (frametype != NR_RESET || flags != 0)) + nr_transmit_reset(skb, 1); + +diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c +index fbfdae452ff9a..01ccd00d1c005 100644 +--- a/net/netrom/nr_in.c ++++ b/net/netrom/nr_in.c +@@ -100,7 +100,7 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff *skb, + break; + + case NR_RESET: +- if (sysctl_netrom_reset_circuit) ++ if (READ_ONCE(sysctl_netrom_reset_circuit)) + nr_disconnect(sk, ECONNRESET); + break; + +@@ -131,7 +131,7 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, + break; + + case NR_RESET: +- if (sysctl_netrom_reset_circuit) ++ if (READ_ONCE(sysctl_netrom_reset_circuit)) + nr_disconnect(sk, ECONNRESET); + break; + +@@ -266,7 +266,7 @@ static int nr_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype + break; + + case NR_RESET: +- if (sysctl_netrom_reset_circuit) ++ if (READ_ONCE(sysctl_netrom_reset_circuit)) + nr_disconnect(sk, ECONNRESET); + break; + +-- +2.43.0 + diff --git a/queue-4.19/netrom-fix-data-races-around-sysctl_netrom_network_t.patch b/queue-4.19/netrom-fix-data-races-around-sysctl_netrom_network_t.patch new file mode 100644 index 00000000000..fa0fc92bfbf --- /dev/null +++ b/queue-4.19/netrom-fix-data-races-around-sysctl_netrom_network_t.patch @@ -0,0 +1,74 @@ +From 7604ce14d56e6222c3f4db176274419df7bf6535 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 16:20:37 +0800 +Subject: netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser + +From: Jason Xing + +[ Upstream commit 119cae5ea3f9e35cdada8e572cc067f072fa825a ] + +We need to protect the reader reading the sysctl value because the +value can be changed concurrently. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Jason Xing +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/netrom/nr_dev.c | 2 +- + net/netrom/nr_out.c | 2 +- + net/netrom/nr_subr.c | 5 +++-- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c +index 988f542481a83..fa845edad7bf6 100644 +--- a/net/netrom/nr_dev.c ++++ b/net/netrom/nr_dev.c +@@ -84,7 +84,7 @@ static int nr_header(struct sk_buff *skb, struct net_device *dev, + buff[6] |= AX25_SSSID_SPARE; + buff += AX25_ADDR_LEN; + +- *buff++ = sysctl_netrom_network_ttl_initialiser; ++ *buff++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser); + + *buff++ = NR_PROTO_IP; + *buff++ = NR_PROTO_IP; +diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c +index 00fbf1419ec6b..213bddab6e74f 100644 +--- a/net/netrom/nr_out.c ++++ b/net/netrom/nr_out.c +@@ -207,7 +207,7 @@ void nr_transmit_buffer(struct sock *sk, struct sk_buff *skb) + dptr[6] |= AX25_SSSID_SPARE; + dptr += AX25_ADDR_LEN; + +- *dptr++ = sysctl_netrom_network_ttl_initialiser; ++ *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser); + + if (!nr_route_frame(skb, NULL)) { + kfree_skb(skb); +diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c +index a7d3a265befb9..b5cee72b8c985 100644 +--- a/net/netrom/nr_subr.c ++++ b/net/netrom/nr_subr.c +@@ -185,7 +185,8 @@ void nr_write_internal(struct sock *sk, int frametype) + *dptr++ = nr->my_id; + *dptr++ = frametype; + *dptr++ = nr->window; +- if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser; ++ if (nr->bpqext) ++ *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser); + break; + + case NR_DISCREQ: +@@ -239,7 +240,7 @@ void __nr_transmit_reply(struct sk_buff *skb, int mine, unsigned char cmdflags) + dptr[6] |= AX25_SSSID_SPARE; + dptr += AX25_ADDR_LEN; + +- *dptr++ = sysctl_netrom_network_ttl_initialiser; ++ *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser); + + if (mine) { + *dptr++ = 0; +-- +2.43.0 + diff --git a/queue-4.19/series b/queue-4.19/series new file mode 100644 index 00000000000..782d1d517fe --- /dev/null +++ b/queue-4.19/series @@ -0,0 +1,23 @@ +net-usb-lan78xx-remove-lots-of-set-but-unused-ret-va.patch +lan78xx-fix-white-space-and-style-issues.patch +lan78xx-add-missing-return-code-checks.patch +lan78xx-fix-partial-packet-errors-on-suspend-resume.patch +lan78xx-fix-race-conditions-in-suspend-resume-handli.patch +net-lan78xx-fix-runtime-pm-count-underflow-on-link-s.patch +net-move-definition-of-pcpu_lstats-to-header-file.patch +geneve-make-sure-to-pull-inner-header-in-geneve_rx.patch +net-ipv6-avoid-possible-uaf-in-ip6_route_mpath_notif.patch +net-rds-fix-warning-in-rds_conn_connect_if_down.patch +netfilter-nf_conntrack_h323-add-protection-for-bmp-l.patch +netrom-fix-a-data-race-around-sysctl_netrom_default_.patch +netrom-fix-a-data-race-around-sysctl_netrom_obsolesc.patch +netrom-fix-data-races-around-sysctl_netrom_network_t.patch +netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch +netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-4591 +netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-28060 +netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-23382 +netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-5373 +netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-9711 +netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch +netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch +netrom-fix-data-races-around-sysctl_net_busy_read.patch