From: Greg Kroah-Hartman Date: Sat, 5 Mar 2022 12:28:52 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.9.305~74 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a7afcafa67571c13d4241d24d8eb7d00d39bc27;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: batman-adv-don-t-expect-inter-netns-unique-iflink-indices.patch batman-adv-request-iflink-once-in-batadv-on-batadv-check.patch batman-adv-request-iflink-once-in-batadv_get_real_netdevice.patch net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-cause-by-server.patch net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-generated-by-client.patch --- diff --git a/queue-4.14/batman-adv-don-t-expect-inter-netns-unique-iflink-indices.patch b/queue-4.14/batman-adv-don-t-expect-inter-netns-unique-iflink-indices.patch new file mode 100644 index 00000000000..c5f29defd40 --- /dev/null +++ b/queue-4.14/batman-adv-don-t-expect-inter-netns-unique-iflink-indices.patch @@ -0,0 +1,95 @@ +From 6c1f41afc1dbe59d9d3c8bb0d80b749c119aa334 Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Sun, 27 Feb 2022 23:23:49 +0100 +Subject: batman-adv: Don't expect inter-netns unique iflink indices + +From: Sven Eckelmann + +commit 6c1f41afc1dbe59d9d3c8bb0d80b749c119aa334 upstream. + +The ifindex doesn't have to be unique for multiple network namespaces on +the same machine. + + $ ip netns add test1 + $ ip -net test1 link add dummy1 type dummy + $ ip netns add test2 + $ ip -net test2 link add dummy2 type dummy + + $ ip -net test1 link show dev dummy1 + 6: dummy1: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 + link/ether 96:81:55:1e:dd:85 brd ff:ff:ff:ff:ff:ff + $ ip -net test2 link show dev dummy2 + 6: dummy2: mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 + link/ether 5a:3c:af:35:07:c3 brd ff:ff:ff:ff:ff:ff + +But the batman-adv code to walk through the various layers of virtual +interfaces uses this assumption because dev_get_iflink handles it +internally and doesn't return the actual netns of the iflink. And +dev_get_iflink only documents the situation where ifindex == iflink for +physical devices. + +But only checking for dev->netdev_ops->ndo_get_iflink is also not an option +because ipoib_get_iflink implements it even when it sometimes returns an +iflink != ifindex and sometimes iflink == ifindex. The caller must +therefore make sure itself to check both netns and iflink + ifindex for +equality. Only when they are equal, a "physical" interface was detected +which should stop the traversal. On the other hand, vxcan_get_iflink can +also return 0 in case there was currently no valid peer. In this case, it +is still necessary to stop. + +Fixes: b7eddd0b3950 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface") +Fixes: 5ed4a460a1d3 ("batman-adv: additional checks for virtual interfaces on top of WiFi") +Reported-by: Sabrina Dubroca +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/hard-interface.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -163,13 +163,15 @@ static bool batadv_is_on_batman_iface(co + return true; + + iflink = dev_get_iflink(net_dev); +- +- /* no more parents..stop recursion */ +- if (iflink == 0 || iflink == net_dev->ifindex) ++ if (iflink == 0) + return false; + + parent_net = batadv_getlink_net(net_dev, net); + ++ /* iflink to itself, most likely physical device */ ++ if (net == parent_net && iflink == net_dev->ifindex) ++ return false; ++ + /* recurse over the parent device */ + parent_dev = __dev_get_by_index((struct net *)parent_net, iflink); + /* if we got a NULL parent_dev there is something broken.. */ +@@ -229,8 +231,7 @@ static struct net_device *batadv_get_rea + return NULL; + + iflink = dev_get_iflink(netdev); +- +- if (netdev->ifindex == iflink) { ++ if (iflink == 0) { + dev_hold(netdev); + return netdev; + } +@@ -241,6 +242,14 @@ static struct net_device *batadv_get_rea + + net = dev_net(hard_iface->soft_iface); + real_net = batadv_getlink_net(netdev, net); ++ ++ /* iflink to itself, most likely physical device */ ++ if (net == real_net && netdev->ifindex == iflink) { ++ real_netdev = netdev; ++ dev_hold(real_netdev); ++ goto out; ++ } ++ + real_netdev = dev_get_by_index(real_net, iflink); + + out: diff --git a/queue-4.14/batman-adv-request-iflink-once-in-batadv-on-batadv-check.patch b/queue-4.14/batman-adv-request-iflink-once-in-batadv-on-batadv-check.patch new file mode 100644 index 00000000000..1a293edaddc --- /dev/null +++ b/queue-4.14/batman-adv-request-iflink-once-in-batadv-on-batadv-check.patch @@ -0,0 +1,53 @@ +From 690bb6fb64f5dc7437317153902573ecad67593d Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Mon, 28 Feb 2022 00:01:24 +0100 +Subject: batman-adv: Request iflink once in batadv-on-batadv check + +From: Sven Eckelmann + +commit 690bb6fb64f5dc7437317153902573ecad67593d upstream. + +There is no need to call dev_get_iflink multiple times for the same +net_device in batadv_is_on_batman_iface. And since some of the +.ndo_get_iflink callbacks are dynamic (for example via RCUs like in +vxcan_get_iflink), it could easily happen that the returned values are not +stable. The pre-checks before __dev_get_by_index are then of course bogus. + +Fixes: b7eddd0b3950 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface") +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/hard-interface.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -155,22 +155,23 @@ static bool batadv_is_on_batman_iface(co + struct net *net = dev_net(net_dev); + struct net_device *parent_dev; + struct net *parent_net; ++ int iflink; + bool ret; + + /* check if this is a batman-adv mesh interface */ + if (batadv_softif_is_valid(net_dev)) + return true; + ++ iflink = dev_get_iflink(net_dev); ++ + /* no more parents..stop recursion */ +- if (dev_get_iflink(net_dev) == 0 || +- dev_get_iflink(net_dev) == net_dev->ifindex) ++ if (iflink == 0 || iflink == net_dev->ifindex) + return false; + + parent_net = batadv_getlink_net(net_dev, net); + + /* recurse over the parent device */ +- parent_dev = __dev_get_by_index((struct net *)parent_net, +- dev_get_iflink(net_dev)); ++ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink); + /* if we got a NULL parent_dev there is something broken.. */ + if (!parent_dev) { + pr_err("Cannot find parent device\n"); diff --git a/queue-4.14/batman-adv-request-iflink-once-in-batadv_get_real_netdevice.patch b/queue-4.14/batman-adv-request-iflink-once-in-batadv_get_real_netdevice.patch new file mode 100644 index 00000000000..9dbbc6126d3 --- /dev/null +++ b/queue-4.14/batman-adv-request-iflink-once-in-batadv_get_real_netdevice.patch @@ -0,0 +1,55 @@ +From 6116ba09423f7d140f0460be6a1644dceaad00da Mon Sep 17 00:00:00 2001 +From: Sven Eckelmann +Date: Mon, 28 Feb 2022 00:01:24 +0100 +Subject: batman-adv: Request iflink once in batadv_get_real_netdevice + +From: Sven Eckelmann + +commit 6116ba09423f7d140f0460be6a1644dceaad00da upstream. + +There is no need to call dev_get_iflink multiple times for the same +net_device in batadv_get_real_netdevice. And since some of the +ndo_get_iflink callbacks are dynamic (for example via RCUs like in +vxcan_get_iflink), it could easily happen that the returned values are not +stable. The pre-checks before __dev_get_by_index are then of course bogus. + +Fixes: 5ed4a460a1d3 ("batman-adv: additional checks for virtual interfaces on top of WiFi") +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/hard-interface.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/net/batman-adv/hard-interface.c ++++ b/net/batman-adv/hard-interface.c +@@ -221,14 +221,16 @@ static struct net_device *batadv_get_rea + struct net_device *real_netdev = NULL; + struct net *real_net; + struct net *net; +- int ifindex; ++ int iflink; + + ASSERT_RTNL(); + + if (!netdev) + return NULL; + +- if (netdev->ifindex == dev_get_iflink(netdev)) { ++ iflink = dev_get_iflink(netdev); ++ ++ if (netdev->ifindex == iflink) { + dev_hold(netdev); + return netdev; + } +@@ -238,9 +240,8 @@ static struct net_device *batadv_get_rea + goto out; + + net = dev_net(hard_iface->soft_iface); +- ifindex = dev_get_iflink(netdev); + real_net = batadv_getlink_net(netdev, net); +- real_netdev = dev_get_by_index(real_net, ifindex); ++ real_netdev = dev_get_by_index(real_net, iflink); + + out: + if (hard_iface) diff --git a/queue-4.14/net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch b/queue-4.14/net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch new file mode 100644 index 00000000000..5557c489703 --- /dev/null +++ b/queue-4.14/net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch @@ -0,0 +1,103 @@ +From 91b0383fef06f20b847fa9e4f0e3054ead0b1a1b Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean +Date: Thu, 24 Feb 2022 18:01:54 +0200 +Subject: net: dcb: flush lingering app table entries for unregistered devices + +From: Vladimir Oltean + +commit 91b0383fef06f20b847fa9e4f0e3054ead0b1a1b upstream. + +If I'm not mistaken (and I don't think I am), the way in which the +dcbnl_ops work is that drivers call dcb_ieee_setapp() and this populates +the application table with dynamically allocated struct dcb_app_type +entries that are kept in the module-global dcb_app_list. + +However, nobody keeps exact track of these entries, and although +dcb_ieee_delapp() is supposed to remove them, nobody does so when the +interface goes away (example: driver unbinds from device). So the +dcb_app_list will contain lingering entries with an ifindex that no +longer matches any device in dcb_app_lookup(). + +Reclaim the lost memory by listening for the NETDEV_UNREGISTER event and +flushing the app table entries of interfaces that are now gone. + +In fact something like this used to be done as part of the initial +commit (blamed below), but it was done in dcbnl_exit() -> dcb_flushapp(), +essentially at module_exit time. That became dead code after commit +7a6b6f515f77 ("DCB: fix kconfig option") which essentially merged +"tristate config DCB" and "bool config DCBNL" into a single "bool config +DCB", so net/dcb/dcbnl.c could not be built as a module anymore. + +Commit 36b9ad8084bd ("net/dcb: make dcbnl.c explicitly non-modular") +recognized this and deleted dcbnl_exit() and dcb_flushapp() altogether, +leaving us with the version we have today. + +Since flushing application table entries can and should be done as soon +as the netdevice disappears, fundamentally the commit that is to blame +is the one that introduced the design of this API. + +Fixes: 9ab933ab2cc8 ("dcbnl: add appliction tlv handlers") +Signed-off-by: Vladimir Oltean +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/dcb/dcbnl.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +--- a/net/dcb/dcbnl.c ++++ b/net/dcb/dcbnl.c +@@ -1939,10 +1939,54 @@ int dcb_ieee_delapp(struct net_device *d + } + EXPORT_SYMBOL(dcb_ieee_delapp); + ++static void dcbnl_flush_dev(struct net_device *dev) ++{ ++ struct dcb_app_type *itr, *tmp; ++ ++ spin_lock(&dcb_lock); ++ ++ list_for_each_entry_safe(itr, tmp, &dcb_app_list, list) { ++ if (itr->ifindex == dev->ifindex) { ++ list_del(&itr->list); ++ kfree(itr); ++ } ++ } ++ ++ spin_unlock(&dcb_lock); ++} ++ ++static int dcbnl_netdevice_event(struct notifier_block *nb, ++ unsigned long event, void *ptr) ++{ ++ struct net_device *dev = netdev_notifier_info_to_dev(ptr); ++ ++ switch (event) { ++ case NETDEV_UNREGISTER: ++ if (!dev->dcbnl_ops) ++ return NOTIFY_DONE; ++ ++ dcbnl_flush_dev(dev); ++ ++ return NOTIFY_OK; ++ default: ++ return NOTIFY_DONE; ++ } ++} ++ ++static struct notifier_block dcbnl_nb __read_mostly = { ++ .notifier_call = dcbnl_netdevice_event, ++}; ++ + static int __init dcbnl_init(void) + { ++ int err; ++ + INIT_LIST_HEAD(&dcb_app_list); + ++ err = register_netdevice_notifier(&dcbnl_nb); ++ if (err) ++ return err; ++ + rtnl_register(PF_UNSPEC, RTM_GETDCB, dcb_doit, NULL, 0); + rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, 0); + diff --git a/queue-4.14/net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-cause-by-server.patch b/queue-4.14/net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-cause-by-server.patch new file mode 100644 index 00000000000..1434ec82bae --- /dev/null +++ b/queue-4.14/net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-cause-by-server.patch @@ -0,0 +1,40 @@ +From 4940a1fdf31c39f0806ac831cde333134862030b Mon Sep 17 00:00:00 2001 +From: "D. Wythe" +Date: Wed, 2 Mar 2022 21:25:12 +0800 +Subject: net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error cause by server + +From: D. Wythe + +commit 4940a1fdf31c39f0806ac831cde333134862030b upstream. + +The problem of SMC_CLC_DECL_ERR_REGRMB on the server is very clear. +Based on the fact that whether a new SMC connection can be accepted or +not depends on not only the limit of conn nums, but also the available +entries of rtoken. Since the rtoken release is trigger by peer, while +the conn nums is decrease by local, tons of thing can happen in this +time difference. + +This only thing that needs to be mentioned is that now all connection +creations are completely protected by smc_server_lgr_pending lock, it's +enough to check only the available entries in rtokens_used_mask. + +Fixes: cd6851f30386 ("smc: remote memory buffers (RMBs)") +Signed-off-by: D. Wythe +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/smc/smc_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/smc/smc_core.c ++++ b/net/smc/smc_core.c +@@ -428,7 +428,8 @@ int smc_conn_create(struct smc_sock *smc + (lgr->role == role) && + (lgr->vlan_id == vlan_id) && + ((role == SMC_CLNT) || +- (lgr->conns_num < SMC_RMBS_PER_LGR_MAX))) { ++ (lgr->conns_num < SMC_RMBS_PER_LGR_MAX && ++ !bitmap_full(lgr->rtokens_used_mask, SMC_RMBS_PER_LGR_MAX)))) { + /* link group found */ + local_contact = SMC_REUSE_CONTACT; + conn->lgr = lgr; diff --git a/queue-4.14/net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-generated-by-client.patch b/queue-4.14/net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-generated-by-client.patch new file mode 100644 index 00000000000..dd9f715c2cb --- /dev/null +++ b/queue-4.14/net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-generated-by-client.patch @@ -0,0 +1,47 @@ +From 0537f0a2151375dcf90c1bbfda6a0aaf57164e89 Mon Sep 17 00:00:00 2001 +From: "D. Wythe" +Date: Wed, 2 Mar 2022 21:25:11 +0800 +Subject: net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error generated by client + +From: D. Wythe + +commit 0537f0a2151375dcf90c1bbfda6a0aaf57164e89 upstream. + +The main reason for this unexpected SMC_CLC_DECL_ERR_REGRMB in client +dues to following execution sequence: + +Server Conn A: Server Conn B: Client Conn B: + +smc_lgr_unregister_conn + smc_lgr_register_conn + smc_clc_send_accept -> + smc_rtoken_add +smcr_buf_unuse + -> Client Conn A: + smc_rtoken_delete + +smc_lgr_unregister_conn() makes current link available to assigned to new +incoming connection, while smcr_buf_unuse() has not executed yet, which +means that smc_rtoken_add may fail because of insufficient rtoken_entry, +reversing their execution order will avoid this problem. + +Fixes: 3e034725c0d8 ("net/smc: common functions for RMBs and send buffers") +Signed-off-by: D. Wythe +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/smc/smc_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/smc/smc_core.c ++++ b/net/smc/smc_core.c +@@ -239,8 +239,8 @@ void smc_conn_free(struct smc_connection + if (!lgr) + return; + smc_cdc_tx_dismiss_slots(conn); +- smc_lgr_unregister_conn(conn); + smc_buf_unuse(conn); ++ smc_lgr_unregister_conn(conn); + } + + static void smc_link_clear(struct smc_link *lnk) diff --git a/queue-4.14/series b/queue-4.14/series index c21080ee6d4..e8115f935fa 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -17,3 +17,9 @@ netfilter-fix-use-after-free-in-__nf_register_net_hook.patch xfrm-enforce-validity-of-offload-input-flags.patch netfilter-nf_queue-don-t-assume-sk-is-full-socket.patch netfilter-nf_queue-fix-possible-use-after-free.patch +batman-adv-request-iflink-once-in-batadv-on-batadv-check.patch +batman-adv-request-iflink-once-in-batadv_get_real_netdevice.patch +batman-adv-don-t-expect-inter-netns-unique-iflink-indices.patch +net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch +net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-generated-by-client.patch +net-smc-fix-unexpected-smc_clc_decl_err_regrmb-error-cause-by-server.patch