summaryrefslogtreecommitdiffstats
path: root/freed-ora/current/f24/wext-fix-message-delay-ordering.patch
diff options
context:
space:
mode:
Diffstat (limited to 'freed-ora/current/f24/wext-fix-message-delay-ordering.patch')
-rw-r--r--freed-ora/current/f24/wext-fix-message-delay-ordering.patch122
1 files changed, 122 insertions, 0 deletions
diff --git a/freed-ora/current/f24/wext-fix-message-delay-ordering.patch b/freed-ora/current/f24/wext-fix-message-delay-ordering.patch
new file mode 100644
index 000000000..109b68da3
--- /dev/null
+++ b/freed-ora/current/f24/wext-fix-message-delay-ordering.patch
@@ -0,0 +1,122 @@
+From 8bf862739a7786ae72409220914df960a0aa80d8 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Wed, 27 Jan 2016 12:37:52 +0100
+Subject: wext: fix message delay/ordering
+
+Beniamino reported that he was getting an RTM_NEWLINK message for a
+given interface, after the RTM_DELLINK for it. It turns out that the
+message is a wireless extensions message, which was sent because the
+interface had been connected and disconnection while it was deleted
+caused a wext message.
+
+For its netlink messages, wext uses RTM_NEWLINK, but the message is
+without all the regular rtnetlink attributes, so "ip monitor link"
+prints just rudimentary information:
+
+5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN group default
+ link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff
+Deleted 5: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default
+ link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff
+5: wlan1: <BROADCAST,MULTICAST,UP>
+ link/ether
+(from my hwsim reproduction)
+
+This can cause userspace to get confused since it doesn't expect an
+RTM_NEWLINK message after RTM_DELLINK.
+
+The reason for this is that wext schedules a worker to send out the
+messages, and the scheduling delay can cause the messages to get out
+to userspace in different order.
+
+To fix this, have wext register a netdevice notifier and flush out
+any pending messages when netdevice state changes. This fixes any
+ordering whenever the original message wasn't sent by a notifier
+itself.
+
+Cc: stable@vger.kernel.org
+Reported-by: Beniamino Galvani <bgalvani@redhat.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+ net/wireless/wext-core.c | 51 +++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 40 insertions(+), 11 deletions(-)
+
+diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
+index c8717c1..87dd619 100644
+--- a/net/wireless/wext-core.c
++++ b/net/wireless/wext-core.c
+@@ -342,6 +342,39 @@ static const int compat_event_type_size[] = {
+
+ /* IW event code */
+
++static void wireless_nlevent_flush(void)
++{
++ struct sk_buff *skb;
++ struct net *net;
++
++ ASSERT_RTNL();
++
++ for_each_net(net) {
++ while ((skb = skb_dequeue(&net->wext_nlevents)))
++ rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
++ GFP_KERNEL);
++ }
++}
++
++static int wext_netdev_notifier_call(struct notifier_block *nb,
++ unsigned long state, void *ptr)
++{
++ /*
++ * When a netdev changes state in any way, flush all pending messages
++ * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
++ * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
++ * or similar - all of which could otherwise happen due to delays from
++ * schedule_work().
++ */
++ wireless_nlevent_flush();
++
++ return NOTIFY_OK;
++}
++
++static struct notifier_block wext_netdev_notifier = {
++ .notifier_call = wext_netdev_notifier_call,
++};
++
+ static int __net_init wext_pernet_init(struct net *net)
+ {
+ skb_queue_head_init(&net->wext_nlevents);
+@@ -360,7 +393,12 @@ static struct pernet_operations wext_pernet_ops = {
+
+ static int __init wireless_nlevent_init(void)
+ {
+- return register_pernet_subsys(&wext_pernet_ops);
++ int err = register_pernet_subsys(&wext_pernet_ops);
++
++ if (err)
++ return err;
++
++ return register_netdevice_notifier(&wext_netdev_notifier);
+ }
+
+ subsys_initcall(wireless_nlevent_init);
+@@ -368,17 +406,8 @@ subsys_initcall(wireless_nlevent_init);
+ /* Process events generated by the wireless layer or the driver. */
+ static void wireless_nlevent_process(struct work_struct *work)
+ {
+- struct sk_buff *skb;
+- struct net *net;
+-
+ rtnl_lock();
+-
+- for_each_net(net) {
+- while ((skb = skb_dequeue(&net->wext_nlevents)))
+- rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
+- GFP_KERNEL);
+- }
+-
++ wireless_nlevent_flush();
+ rtnl_unlock();
+ }
+
+--
+cgit v0.12
+
OpenPOWER on IntegriCloud