]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 5 Mar 2022 12:28:36 +0000 (13:28 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 5 Mar 2022 12:28:36 +0000 (13:28 +0100)
added patches:
net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch

queue-4.9/net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch b/queue-4.9/net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch
new file mode 100644 (file)
index 0000000..d57e5f3
--- /dev/null
@@ -0,0 +1,103 @@
+From 91b0383fef06f20b847fa9e4f0e3054ead0b1a1b Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+Date: Thu, 24 Feb 2022 18:01:54 +0200
+Subject: net: dcb: flush lingering app table entries for unregistered devices
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+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 <vladimir.oltean@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/dcb/dcbnl.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+--- a/net/dcb/dcbnl.c
++++ b/net/dcb/dcbnl.c
+@@ -1938,10 +1938,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, NULL);
+       rtnl_register(PF_UNSPEC, RTM_SETDCB, dcb_doit, NULL, NULL);
index ec1d1f4783278419ce95b48cbde9293a5fb3bcaf..044d17b20aef3319d068efc60a001b9c0aaae003 100644 (file)
@@ -13,3 +13,4 @@ asoc-ops-shift-tested-values-in-snd_soc_put_volsw-by-min.patch
 xfrm-fix-mtu-regression.patch
 netfilter-nf_queue-don-t-assume-sk-is-full-socket.patch
 netfilter-nf_queue-fix-possible-use-after-free.patch
+net-dcb-flush-lingering-app-table-entries-for-unregistered-devices.patch