From 87ab88827d71d652a2c40d638b7e5ad670593c32 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 10 Aug 2020 15:35:25 +0200 Subject: [PATCH] 4.4-stable patches added patches: ipv4-silence-suspicious-rcu-usage-warning.patch ipv6-fix-memory-leaks-on-ipv6_addrform-path.patch net-lan78xx-replace-bogus-endpoint-lookup.patch revert-vxlan-fix-tos-value-before-xmit.patch usb-hso-check-for-return-value-in-hso_serial_common_create.patch vxlan-ensure-fdb-dump-is-performed-under-rcu.patch --- ...silence-suspicious-rcu-usage-warning.patch | 80 ++++++++ ...x-memory-leaks-on-ipv6_addrform-path.patch | 115 +++++++++++ ...an78xx-replace-bogus-endpoint-lookup.patch | 190 ++++++++++++++++++ ...vert-vxlan-fix-tos-value-before-xmit.patch | 56 ++++++ queue-4.4/series | 6 + ...rn-value-in-hso_serial_common_create.patch | 48 +++++ ...sure-fdb-dump-is-performed-under-rcu.patch | 96 +++++++++ 7 files changed, 591 insertions(+) create mode 100644 queue-4.4/ipv4-silence-suspicious-rcu-usage-warning.patch create mode 100644 queue-4.4/ipv6-fix-memory-leaks-on-ipv6_addrform-path.patch create mode 100644 queue-4.4/net-lan78xx-replace-bogus-endpoint-lookup.patch create mode 100644 queue-4.4/revert-vxlan-fix-tos-value-before-xmit.patch create mode 100644 queue-4.4/usb-hso-check-for-return-value-in-hso_serial_common_create.patch create mode 100644 queue-4.4/vxlan-ensure-fdb-dump-is-performed-under-rcu.patch diff --git a/queue-4.4/ipv4-silence-suspicious-rcu-usage-warning.patch b/queue-4.4/ipv4-silence-suspicious-rcu-usage-warning.patch new file mode 100644 index 00000000000..e91129d5449 --- /dev/null +++ b/queue-4.4/ipv4-silence-suspicious-rcu-usage-warning.patch @@ -0,0 +1,80 @@ +From foo@baz Mon 10 Aug 2020 03:30:25 PM CEST +From: Ido Schimmel +Date: Wed, 29 Jul 2020 11:37:13 +0300 +Subject: ipv4: Silence suspicious RCU usage warning + +From: Ido Schimmel + +[ Upstream commit 83f3522860f702748143e022f1a546547314c715 ] + +fib_trie_unmerge() is called with RTNL held, but not from an RCU +read-side critical section. This leads to the following warning [1] when +the FIB alias list in a leaf is traversed with +hlist_for_each_entry_rcu(). + +Since the function is always called with RTNL held and since +modification of the list is protected by RTNL, simply use +hlist_for_each_entry() and silence the warning. + +[1] +WARNING: suspicious RCU usage +5.8.0-rc4-custom-01520-gc1f937f3f83b #30 Not tainted +----------------------------- +net/ipv4/fib_trie.c:1867 RCU-list traversed in non-reader section!! + +other info that might help us debug this: + +rcu_scheduler_active = 2, debug_locks = 1 +1 lock held by ip/164: + #0: ffffffff85a27850 (rtnl_mutex){+.+.}-{3:3}, at: rtnetlink_rcv_msg+0x49a/0xbd0 + +stack backtrace: +CPU: 0 PID: 164 Comm: ip Not tainted 5.8.0-rc4-custom-01520-gc1f937f3f83b #30 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-2.fc32 04/01/2014 +Call Trace: + dump_stack+0x100/0x184 + lockdep_rcu_suspicious+0x153/0x15d + fib_trie_unmerge+0x608/0xdb0 + fib_unmerge+0x44/0x360 + fib4_rule_configure+0xc8/0xad0 + fib_nl_newrule+0x37a/0x1dd0 + rtnetlink_rcv_msg+0x4f7/0xbd0 + netlink_rcv_skb+0x17a/0x480 + rtnetlink_rcv+0x22/0x30 + netlink_unicast+0x5ae/0x890 + netlink_sendmsg+0x98a/0xf40 + ____sys_sendmsg+0x879/0xa00 + ___sys_sendmsg+0x122/0x190 + __sys_sendmsg+0x103/0x1d0 + __x64_sys_sendmsg+0x7d/0xb0 + do_syscall_64+0x54/0xa0 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x7fc80a234e97 +Code: Bad RIP value. +RSP: 002b:00007ffef8b66798 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fc80a234e97 +RDX: 0000000000000000 RSI: 00007ffef8b66800 RDI: 0000000000000003 +RBP: 000000005f141b1c R08: 0000000000000001 R09: 0000000000000000 +R10: 00007fc80a2a8ac0 R11: 0000000000000246 R12: 0000000000000001 +R13: 0000000000000000 R14: 00007ffef8b67008 R15: 0000556fccb10020 + +Fixes: 0ddcf43d5d4a ("ipv4: FIB Local/MAIN table collapse") +Signed-off-by: Ido Schimmel +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/fib_trie.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -1696,7 +1696,7 @@ struct fib_table *fib_trie_unmerge(struc + while ((l = leaf_walk_rcu(&tp, key)) != NULL) { + struct key_vector *local_l = NULL, *local_tp; + +- hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) { ++ hlist_for_each_entry(fa, &l->leaf, fa_list) { + struct fib_alias *new_fa; + + if (local_tb->tb_id != fa->tb_id) diff --git a/queue-4.4/ipv6-fix-memory-leaks-on-ipv6_addrform-path.patch b/queue-4.4/ipv6-fix-memory-leaks-on-ipv6_addrform-path.patch new file mode 100644 index 00000000000..7e482185999 --- /dev/null +++ b/queue-4.4/ipv6-fix-memory-leaks-on-ipv6_addrform-path.patch @@ -0,0 +1,115 @@ +From foo@baz Mon 10 Aug 2020 03:30:25 PM CEST +From: Cong Wang +Date: Sat, 25 Jul 2020 15:40:53 -0700 +Subject: ipv6: fix memory leaks on IPV6_ADDRFORM path + +From: Cong Wang + +[ Upstream commit 8c0de6e96c9794cb523a516c465991a70245da1c ] + +IPV6_ADDRFORM causes resource leaks when converting an IPv6 socket +to IPv4, particularly struct ipv6_ac_socklist. Similar to +struct ipv6_mc_socklist, we should just close it on this path. + +This bug can be easily reproduced with the following C program: + + #include + #include + #include + #include + #include + + int main() + { + int s, value; + struct sockaddr_in6 addr; + struct ipv6_mreq m6; + + s = socket(AF_INET6, SOCK_DGRAM, 0); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(5000); + inet_pton(AF_INET6, "::ffff:192.168.122.194", &addr.sin6_addr); + connect(s, (struct sockaddr *)&addr, sizeof(addr)); + + inet_pton(AF_INET6, "fe80::AAAA", &m6.ipv6mr_multiaddr); + m6.ipv6mr_interface = 5; + setsockopt(s, SOL_IPV6, IPV6_JOIN_ANYCAST, &m6, sizeof(m6)); + + value = AF_INET; + setsockopt(s, SOL_IPV6, IPV6_ADDRFORM, &value, sizeof(value)); + + close(s); + return 0; + } + +Reported-by: ch3332xr@gmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/addrconf.h | 1 + + net/ipv6/anycast.c | 17 ++++++++++++----- + net/ipv6/ipv6_sockglue.c | 1 + + 3 files changed, 14 insertions(+), 5 deletions(-) + +--- a/include/net/addrconf.h ++++ b/include/net/addrconf.h +@@ -239,6 +239,7 @@ int ipv6_sock_ac_join(struct sock *sk, i + const struct in6_addr *addr); + int ipv6_sock_ac_drop(struct sock *sk, int ifindex, + const struct in6_addr *addr); ++void __ipv6_sock_ac_close(struct sock *sk); + void ipv6_sock_ac_close(struct sock *sk); + + int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr); +--- a/net/ipv6/anycast.c ++++ b/net/ipv6/anycast.c +@@ -170,7 +170,7 @@ int ipv6_sock_ac_drop(struct sock *sk, i + return 0; + } + +-void ipv6_sock_ac_close(struct sock *sk) ++void __ipv6_sock_ac_close(struct sock *sk) + { + struct ipv6_pinfo *np = inet6_sk(sk); + struct net_device *dev = NULL; +@@ -178,10 +178,7 @@ void ipv6_sock_ac_close(struct sock *sk) + struct net *net = sock_net(sk); + int prev_index; + +- if (!np->ipv6_ac_list) +- return; +- +- rtnl_lock(); ++ ASSERT_RTNL(); + pac = np->ipv6_ac_list; + np->ipv6_ac_list = NULL; + +@@ -198,6 +195,16 @@ void ipv6_sock_ac_close(struct sock *sk) + sock_kfree_s(sk, pac, sizeof(*pac)); + pac = next; + } ++} ++ ++void ipv6_sock_ac_close(struct sock *sk) ++{ ++ struct ipv6_pinfo *np = inet6_sk(sk); ++ ++ if (!np->ipv6_ac_list) ++ return; ++ rtnl_lock(); ++ __ipv6_sock_ac_close(sk); + rtnl_unlock(); + } + +--- a/net/ipv6/ipv6_sockglue.c ++++ b/net/ipv6/ipv6_sockglue.c +@@ -207,6 +207,7 @@ static int do_ipv6_setsockopt(struct soc + + fl6_free_socklist(sk); + __ipv6_sock_mc_close(sk); ++ __ipv6_sock_ac_close(sk); + + /* + * Sock is moving from IPv6 to IPv4 (sk_prot), so diff --git a/queue-4.4/net-lan78xx-replace-bogus-endpoint-lookup.patch b/queue-4.4/net-lan78xx-replace-bogus-endpoint-lookup.patch new file mode 100644 index 00000000000..c6a77fe9dc7 --- /dev/null +++ b/queue-4.4/net-lan78xx-replace-bogus-endpoint-lookup.patch @@ -0,0 +1,190 @@ +From foo@baz Mon 10 Aug 2020 03:30:25 PM CEST +From: Johan Hovold +Date: Tue, 28 Jul 2020 14:10:31 +0200 +Subject: net: lan78xx: replace bogus endpoint lookup + +From: Johan Hovold + +[ Upstream commit ea060b352654a8de1e070140d25fe1b7e4d50310 ] + +Drop the bogus endpoint-lookup helper which could end up accepting +interfaces based on endpoints belonging to unrelated altsettings. + +Note that the returned bulk pipes and interrupt endpoint descriptor +were never actually used. Instead the bulk-endpoint numbers are +hardcoded to 1 and 2 (matching the specification), while the interrupt- +endpoint descriptor was assumed to be the third descriptor created by +USB core. + +Try to bring some order to this by dropping the bogus lookup helper and +adding the missing endpoint sanity checks while keeping the interrupt- +descriptor assumption for now. + +Signed-off-by: Johan Hovold +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/lan78xx.c | 116 +++++++++++----------------------------------- + 1 file changed, 30 insertions(+), 86 deletions(-) + +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -251,10 +251,6 @@ struct lan78xx_net { + struct tasklet_struct bh; + struct delayed_work wq; + +- struct usb_host_endpoint *ep_blkin; +- struct usb_host_endpoint *ep_blkout; +- struct usb_host_endpoint *ep_intr; +- + int msg_enable; + + struct urb *urb_intr; +@@ -2180,77 +2176,12 @@ netdev_tx_t lan78xx_start_xmit(struct sk + return NETDEV_TX_OK; + } + +-int lan78xx_get_endpoints(struct lan78xx_net *dev, struct usb_interface *intf) +-{ +- int tmp; +- struct usb_host_interface *alt = NULL; +- struct usb_host_endpoint *in = NULL, *out = NULL; +- struct usb_host_endpoint *status = NULL; +- +- for (tmp = 0; tmp < intf->num_altsetting; tmp++) { +- unsigned ep; +- +- in = NULL; +- out = NULL; +- status = NULL; +- alt = intf->altsetting + tmp; +- +- for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { +- struct usb_host_endpoint *e; +- int intr = 0; +- +- e = alt->endpoint + ep; +- switch (e->desc.bmAttributes) { +- case USB_ENDPOINT_XFER_INT: +- if (!usb_endpoint_dir_in(&e->desc)) +- continue; +- intr = 1; +- /* FALLTHROUGH */ +- case USB_ENDPOINT_XFER_BULK: +- break; +- default: +- continue; +- } +- if (usb_endpoint_dir_in(&e->desc)) { +- if (!intr && !in) +- in = e; +- else if (intr && !status) +- status = e; +- } else { +- if (!out) +- out = e; +- } +- } +- if (in && out) +- break; +- } +- if (!alt || !in || !out) +- return -EINVAL; +- +- dev->pipe_in = usb_rcvbulkpipe(dev->udev, +- in->desc.bEndpointAddress & +- USB_ENDPOINT_NUMBER_MASK); +- dev->pipe_out = usb_sndbulkpipe(dev->udev, +- out->desc.bEndpointAddress & +- USB_ENDPOINT_NUMBER_MASK); +- dev->ep_intr = status; +- +- return 0; +-} +- + static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) + { + struct lan78xx_priv *pdata = NULL; + int ret; + int i; + +- ret = lan78xx_get_endpoints(dev, intf); +- if (ret) { +- netdev_warn(dev->net, "lan78xx_get_endpoints failed: %d\n", +- ret); +- return ret; +- } +- + dev->data[0] = (unsigned long)kzalloc(sizeof(*pdata), GFP_KERNEL); + + pdata = (struct lan78xx_priv *)(dev->data[0]); +@@ -2926,6 +2857,7 @@ static const struct net_device_ops lan78 + static int lan78xx_probe(struct usb_interface *intf, + const struct usb_device_id *id) + { ++ struct usb_host_endpoint *ep_blkin, *ep_blkout, *ep_intr; + struct lan78xx_net *dev; + struct net_device *netdev; + struct usb_device *udev; +@@ -2969,32 +2901,44 @@ static int lan78xx_probe(struct usb_inte + netdev->watchdog_timeo = TX_TIMEOUT_JIFFIES; + netdev->ethtool_ops = &lan78xx_ethtool_ops; + +- ret = lan78xx_bind(dev, intf); +- if (ret < 0) +- goto out2; +- strcpy(netdev->name, "eth%d"); +- +- if (netdev->mtu > (dev->hard_mtu - netdev->hard_header_len)) +- netdev->mtu = dev->hard_mtu - netdev->hard_header_len; +- netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER); +- + if (intf->cur_altsetting->desc.bNumEndpoints < 3) { + ret = -ENODEV; +- goto out3; ++ goto out2; + } + +- dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0; +- dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1; +- dev->ep_intr = (intf->cur_altsetting)->endpoint + 2; +- + dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE); ++ ep_blkin = usb_pipe_endpoint(udev, dev->pipe_in); ++ if (!ep_blkin || !usb_endpoint_is_bulk_in(&ep_blkin->desc)) { ++ ret = -ENODEV; ++ goto out2; ++ } ++ + dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE); ++ ep_blkout = usb_pipe_endpoint(udev, dev->pipe_out); ++ if (!ep_blkout || !usb_endpoint_is_bulk_out(&ep_blkout->desc)) { ++ ret = -ENODEV; ++ goto out2; ++ } ++ ++ ep_intr = &intf->cur_altsetting->endpoint[2]; ++ if (!usb_endpoint_is_int_in(&ep_intr->desc)) { ++ ret = -ENODEV; ++ goto out2; ++ } + + dev->pipe_intr = usb_rcvintpipe(dev->udev, +- dev->ep_intr->desc.bEndpointAddress & +- USB_ENDPOINT_NUMBER_MASK); +- period = dev->ep_intr->desc.bInterval; ++ usb_endpoint_num(&ep_intr->desc)); ++ ++ ret = lan78xx_bind(dev, intf); ++ if (ret < 0) ++ goto out2; ++ strcpy(netdev->name, "eth%d"); ++ ++ if (netdev->mtu > (dev->hard_mtu - netdev->hard_header_len)) ++ netdev->mtu = dev->hard_mtu - netdev->hard_header_len; ++ netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER); + ++ period = ep_intr->desc.bInterval; + maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0); + buf = kmalloc(maxp, GFP_KERNEL); + if (buf) { diff --git a/queue-4.4/revert-vxlan-fix-tos-value-before-xmit.patch b/queue-4.4/revert-vxlan-fix-tos-value-before-xmit.patch new file mode 100644 index 00000000000..af2bd98db1c --- /dev/null +++ b/queue-4.4/revert-vxlan-fix-tos-value-before-xmit.patch @@ -0,0 +1,56 @@ +From foo@baz Mon 10 Aug 2020 03:30:25 PM CEST +From: Hangbin Liu +Date: Wed, 5 Aug 2020 10:41:31 +0800 +Subject: Revert "vxlan: fix tos value before xmit" + +From: Hangbin Liu + +[ Upstream commit a0dced17ad9dc08b1b25e0065b54c97a318e6e8b ] + +This reverts commit 71130f29979c7c7956b040673e6b9d5643003176. + +In commit 71130f29979c ("vxlan: fix tos value before xmit") we want to +make sure the tos value are filtered by RT_TOS() based on RFC1349. + + 0 1 2 3 4 5 6 7 + +-----+-----+-----+-----+-----+-----+-----+-----+ + | PRECEDENCE | TOS | MBZ | + +-----+-----+-----+-----+-----+-----+-----+-----+ + +But RFC1349 has been obsoleted by RFC2474. The new DSCP field defined like + + 0 1 2 3 4 5 6 7 + +-----+-----+-----+-----+-----+-----+-----+-----+ + | DS FIELD, DSCP | ECN FIELD | + +-----+-----+-----+-----+-----+-----+-----+-----+ + +So with + +IPTOS_TOS_MASK 0x1E +RT_TOS(tos) ((tos)&IPTOS_TOS_MASK) + +the first 3 bits DSCP info will get lost. + +To take all the DSCP info in xmit, we should revert the patch and just push +all tos bits to ip_tunnel_ecn_encap(), which will handling ECN field later. + +Fixes: 71130f29979c ("vxlan: fix tos value before xmit") +Signed-off-by: Hangbin Liu +Acked-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -2070,7 +2070,7 @@ static void vxlan_xmit_one(struct sk_buf + return; + } + +- tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); ++ tos = ip_tunnel_ecn_encap(tos, old_iph, skb); + ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); + err = vxlan_xmit_skb(rt, sk, skb, fl4.saddr, + dst->sin.sin_addr.s_addr, tos, ttl, df, diff --git a/queue-4.4/series b/queue-4.4/series index d1484ae201f..59fc332c23d 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -44,3 +44,9 @@ igb-reinit_locked-should-be-called-with-rtnl_lock.patch atm-fix-atm_dev-refcnt-leaks-in-atmtcp_remove_persis.patch tools-lib-traceevent-fix-memory-leak-in-process_dyna.patch binder-prevent-context-manager-from-incrementing-ref-0.patch +ipv4-silence-suspicious-rcu-usage-warning.patch +ipv6-fix-memory-leaks-on-ipv6_addrform-path.patch +revert-vxlan-fix-tos-value-before-xmit.patch +net-lan78xx-replace-bogus-endpoint-lookup.patch +usb-hso-check-for-return-value-in-hso_serial_common_create.patch +vxlan-ensure-fdb-dump-is-performed-under-rcu.patch diff --git a/queue-4.4/usb-hso-check-for-return-value-in-hso_serial_common_create.patch b/queue-4.4/usb-hso-check-for-return-value-in-hso_serial_common_create.patch new file mode 100644 index 00000000000..fc6a846f1b3 --- /dev/null +++ b/queue-4.4/usb-hso-check-for-return-value-in-hso_serial_common_create.patch @@ -0,0 +1,48 @@ +From foo@baz Mon 10 Aug 2020 03:21:37 PM CEST +From: Rustam Kovhaev +Date: Mon, 27 Jul 2020 23:42:17 -0700 +Subject: usb: hso: check for return value in hso_serial_common_create() + +From: Rustam Kovhaev + +[ Upstream commit e911e99a0770f760377c263bc7bac1b1593c6147 ] + +in case of an error tty_register_device_attr() returns ERR_PTR(), +add IS_ERR() check + +Reported-and-tested-by: syzbot+67b2bd0e34f952d0321e@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?extid=67b2bd0e34f952d0321e +Signed-off-by: Rustam Kovhaev +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/hso.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -2280,12 +2280,14 @@ static int hso_serial_common_create(stru + + minor = get_free_serial_index(); + if (minor < 0) +- goto exit; ++ goto exit2; + + /* register our minor number */ + serial->parent->dev = tty_port_register_device_attr(&serial->port, + tty_drv, minor, &serial->parent->interface->dev, + serial->parent, hso_serial_dev_groups); ++ if (IS_ERR(serial->parent->dev)) ++ goto exit2; + dev = serial->parent->dev; + + /* fill in specific data for later use */ +@@ -2335,6 +2337,7 @@ static int hso_serial_common_create(stru + return 0; + exit: + hso_serial_tty_unregister(serial); ++exit2: + hso_serial_common_free(serial); + return -1; + } diff --git a/queue-4.4/vxlan-ensure-fdb-dump-is-performed-under-rcu.patch b/queue-4.4/vxlan-ensure-fdb-dump-is-performed-under-rcu.patch new file mode 100644 index 00000000000..06f7ada806c --- /dev/null +++ b/queue-4.4/vxlan-ensure-fdb-dump-is-performed-under-rcu.patch @@ -0,0 +1,96 @@ +From foo@baz Mon 10 Aug 2020 03:30:25 PM CEST +From: Ido Schimmel +Date: Wed, 29 Jul 2020 11:34:36 +0300 +Subject: vxlan: Ensure FDB dump is performed under RCU + +From: Ido Schimmel + +[ Upstream commit b5141915b5aec3b29a63db869229e3741ebce258 ] + +The commit cited below removed the RCU read-side critical section from +rtnl_fdb_dump() which means that the ndo_fdb_dump() callback is invoked +without RCU protection. + +This results in the following warning [1] in the VXLAN driver, which +relied on the callback being invoked from an RCU read-side critical +section. + +Fix this by calling rcu_read_lock() in the VXLAN driver, as already done +in the bridge driver. + +[1] +WARNING: suspicious RCU usage +5.8.0-rc4-custom-01521-g481007553ce6 #29 Not tainted +----------------------------- +drivers/net/vxlan.c:1379 RCU-list traversed in non-reader section!! + +other info that might help us debug this: + +rcu_scheduler_active = 2, debug_locks = 1 +1 lock held by bridge/166: + #0: ffffffff85a27850 (rtnl_mutex){+.+.}-{3:3}, at: netlink_dump+0xea/0x1090 + +stack backtrace: +CPU: 1 PID: 166 Comm: bridge Not tainted 5.8.0-rc4-custom-01521-g481007553ce6 #29 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-2.fc32 04/01/2014 +Call Trace: + dump_stack+0x100/0x184 + lockdep_rcu_suspicious+0x153/0x15d + vxlan_fdb_dump+0x51e/0x6d0 + rtnl_fdb_dump+0x4dc/0xad0 + netlink_dump+0x540/0x1090 + __netlink_dump_start+0x695/0x950 + rtnetlink_rcv_msg+0x802/0xbd0 + netlink_rcv_skb+0x17a/0x480 + rtnetlink_rcv+0x22/0x30 + netlink_unicast+0x5ae/0x890 + netlink_sendmsg+0x98a/0xf40 + __sys_sendto+0x279/0x3b0 + __x64_sys_sendto+0xe6/0x1a0 + do_syscall_64+0x54/0xa0 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x7fe14fa2ade0 +Code: Bad RIP value. +RSP: 002b:00007fff75bb5b88 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 00005614b1ba0020 RCX: 00007fe14fa2ade0 +RDX: 000000000000011c RSI: 00007fff75bb5b90 RDI: 0000000000000003 +RBP: 00007fff75bb5b90 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 00005614b1b89160 +R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 + +Fixes: 5e6d24358799 ("bridge: netlink dump interface at par with brctl") +Signed-off-by: Ido Schimmel +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -921,6 +921,7 @@ static int vxlan_fdb_dump(struct sk_buff + struct vxlan_fdb *f; + int err; + ++ rcu_read_lock(); + hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) { + struct vxlan_rdst *rd; + +@@ -933,12 +934,15 @@ static int vxlan_fdb_dump(struct sk_buff + cb->nlh->nlmsg_seq, + RTM_NEWNEIGH, + NLM_F_MULTI, rd); +- if (err < 0) ++ if (err < 0) { ++ rcu_read_unlock(); + goto out; ++ } + skip: + ++idx; + } + } ++ rcu_read_unlock(); + } + out: + return idx; -- 2.47.3