]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Oct 2017 08:58:35 +0000 (10:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Oct 2017 08:58:35 +0000 (10:58 +0200)
added patches:
genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch
mac80211-fix-vlan-handling-with-txqs.patch
mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch
mac80211_hwsim-use-proper-tx-power.patch

queue-4.9/genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch [new file with mode: 0644]
queue-4.9/mac80211-fix-vlan-handling-with-txqs.patch [new file with mode: 0644]
queue-4.9/mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch [new file with mode: 0644]
queue-4.9/mac80211_hwsim-use-proper-tx-power.patch [new file with mode: 0644]

diff --git a/queue-4.9/genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch b/queue-4.9/genirq-make-sparse_irq_lock-protect-what-it-should-protect.patch
new file mode 100644 (file)
index 0000000..58a6ca6
--- /dev/null
@@ -0,0 +1,119 @@
+From 12ac1d0f6c3e95732d144ffa65c8b20fbd9aa462 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 5 Sep 2017 10:12:20 +0200
+Subject: genirq: Make sparse_irq_lock protect what it should protect
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 12ac1d0f6c3e95732d144ffa65c8b20fbd9aa462 upstream.
+
+for_each_active_irq() iterates the sparse irq allocation bitmap. The caller
+must hold sparse_irq_lock. Several code pathes expect that an active bit in
+the sparse bitmap also has a valid interrupt descriptor.
+
+Unfortunately that's not true. The (de)allocation is a two step process,
+which holds the sparse_irq_lock only across the queue/remove from the radix
+tree and the set/clear in the allocation bitmap.
+
+If a iteration locks sparse_irq_lock between the two steps, then it might
+see an active bit but the corresponding irq descriptor is NULL. If that is
+dereferenced unconditionally, then the kernel oopses. Of course, all
+iterator sites could be audited and fixed, but....
+
+There is no reason why the sparse_irq_lock needs to be dropped between the
+two steps, in fact the code becomes simpler when the mutex is held across
+both and the semantics become more straight forward, so future problems of
+missing NULL pointer checks in the iteration are avoided and all existing
+sites are fixed in one go.
+
+Expand the lock held sections so both operations are covered and the bitmap
+and the radixtree are in sync.
+
+Fixes: a05a900a51c7 ("genirq: Make sparse_lock a mutex")
+Reported-and-tested-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/irq/irqdesc.c |   24 +++++++-----------------
+ 1 file changed, 7 insertions(+), 17 deletions(-)
+
+--- a/kernel/irq/irqdesc.c
++++ b/kernel/irq/irqdesc.c
+@@ -405,10 +405,8 @@ static void free_desc(unsigned int irq)
+        * The sysfs entry must be serialized against a concurrent
+        * irq_sysfs_init() as well.
+        */
+-      mutex_lock(&sparse_irq_lock);
+       kobject_del(&desc->kobj);
+       delete_irq_desc(irq);
+-      mutex_unlock(&sparse_irq_lock);
+       /*
+        * We free the descriptor, masks and stat fields via RCU. That
+@@ -446,20 +444,15 @@ static int alloc_descs(unsigned int star
+               desc = alloc_desc(start + i, node, flags, mask, owner);
+               if (!desc)
+                       goto err;
+-              mutex_lock(&sparse_irq_lock);
+               irq_insert_desc(start + i, desc);
+               irq_sysfs_add(start + i, desc);
+-              mutex_unlock(&sparse_irq_lock);
+       }
++      bitmap_set(allocated_irqs, start, cnt);
+       return start;
+ err:
+       for (i--; i >= 0; i--)
+               free_desc(start + i);
+-
+-      mutex_lock(&sparse_irq_lock);
+-      bitmap_clear(allocated_irqs, start, cnt);
+-      mutex_unlock(&sparse_irq_lock);
+       return -ENOMEM;
+ }
+@@ -558,6 +551,7 @@ static inline int alloc_descs(unsigned i
+               desc->owner = owner;
+       }
++      bitmap_set(allocated_irqs, start, cnt);
+       return start;
+ }
+@@ -653,10 +647,10 @@ void irq_free_descs(unsigned int from, u
+       if (from >= nr_irqs || (from + cnt) > nr_irqs)
+               return;
++      mutex_lock(&sparse_irq_lock);
+       for (i = 0; i < cnt; i++)
+               free_desc(from + i);
+-      mutex_lock(&sparse_irq_lock);
+       bitmap_clear(allocated_irqs, from, cnt);
+       mutex_unlock(&sparse_irq_lock);
+ }
+@@ -703,19 +697,15 @@ __irq_alloc_descs(int irq, unsigned int
+                                          from, cnt, 0);
+       ret = -EEXIST;
+       if (irq >=0 && start != irq)
+-              goto err;
++              goto unlock;
+       if (start + cnt > nr_irqs) {
+               ret = irq_expand_nr_irqs(start + cnt);
+               if (ret)
+-                      goto err;
++                      goto unlock;
+       }
+-
+-      bitmap_set(allocated_irqs, start, cnt);
+-      mutex_unlock(&sparse_irq_lock);
+-      return alloc_descs(start, cnt, node, affinity, owner);
+-
+-err:
++      ret = alloc_descs(start, cnt, node, affinity, owner);
++unlock:
+       mutex_unlock(&sparse_irq_lock);
+       return ret;
+ }
diff --git a/queue-4.9/mac80211-fix-vlan-handling-with-txqs.patch b/queue-4.9/mac80211-fix-vlan-handling-with-txqs.patch
new file mode 100644 (file)
index 0000000..f58794e
--- /dev/null
@@ -0,0 +1,167 @@
+From 53168215909281a09d3afc6fb51a9d4f81f74d39 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 22 Jun 2017 12:20:30 +0200
+Subject: mac80211: fix VLAN handling with TXQs
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 53168215909281a09d3afc6fb51a9d4f81f74d39 upstream.
+
+With TXQs, the AP_VLAN interfaces are resolved to their owner AP
+interface when enqueuing the frame, which makes sense since the
+frame really goes out on that as far as the driver is concerned.
+
+However, this introduces a problem: frames to be encrypted with
+a VLAN-specific GTK will now be encrypted with the AP GTK, since
+the information about which virtual interface to use to select
+the key is taken from the TXQ.
+
+Fix this by preserving info->control.vif and using that in the
+dequeue function. This now requires doing the driver-mapping
+in the dequeue as well.
+
+Since there's no way to filter the frames that are sitting on a
+TXQ, drop all frames, which may affect other interfaces, when an
+AP_VLAN is removed.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/mac80211.h |   15 ++-------------
+ net/mac80211/iface.c   |   17 +++++++++++++++--
+ net/mac80211/tx.c      |   36 +++++++++++++++++++++++++++++-------
+ 3 files changed, 46 insertions(+), 22 deletions(-)
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -902,21 +902,10 @@ struct ieee80211_tx_info {
+                               unsigned long jiffies;
+                       };
+                       /* NB: vif can be NULL for injected frames */
+-                      union {
+-                              /* NB: vif can be NULL for injected frames */
+-                              struct ieee80211_vif *vif;
+-
+-                              /* When packets are enqueued on txq it's easy
+-                               * to re-construct the vif pointer. There's no
+-                               * more space in tx_info so it can be used to
+-                               * store the necessary enqueue time for packet
+-                               * sojourn time computation.
+-                               */
+-                              codel_time_t enqueue_time;
+-                      };
++                      struct ieee80211_vif *vif;
+                       struct ieee80211_key_conf *hw_key;
+                       u32 flags;
+-                      /* 4 bytes free */
++                      codel_time_t enqueue_time;
+               } control;
+               struct {
+                       u64 cookie;
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -791,6 +791,7 @@ static int ieee80211_open(struct net_dev
+ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
+                             bool going_down)
+ {
++      struct ieee80211_sub_if_data *txq_sdata = sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct fq *fq = &local->fq;
+       unsigned long flags;
+@@ -931,6 +932,9 @@ static void ieee80211_do_stop(struct iee
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_AP_VLAN:
++              txq_sdata = container_of(sdata->bss,
++                                       struct ieee80211_sub_if_data, u.ap);
++
+               mutex_lock(&local->mtx);
+               list_del(&sdata->u.vlan.list);
+               mutex_unlock(&local->mtx);
+@@ -1001,8 +1005,17 @@ static void ieee80211_do_stop(struct iee
+       }
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+-      if (sdata->vif.txq) {
+-              struct txq_info *txqi = to_txq_info(sdata->vif.txq);
++      if (txq_sdata->vif.txq) {
++              struct txq_info *txqi = to_txq_info(txq_sdata->vif.txq);
++
++              /*
++               * FIXME FIXME
++               *
++               * We really shouldn't purge the *entire* txqi since that
++               * contains frames for the other AP_VLANs (and possibly
++               * the AP itself) as well, but there's no API in FQ now
++               * to be able to filter.
++               */
+               spin_lock_bh(&fq->lock);
+               ieee80211_txq_purge(local, txqi);
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1277,11 +1277,6 @@ static void ieee80211_set_skb_enqueue_ti
+       IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
+ }
+-static void ieee80211_set_skb_vif(struct sk_buff *skb, struct txq_info *txqi)
+-{
+-      IEEE80211_SKB_CB(skb)->control.vif = txqi->txq.vif;
+-}
+-
+ static u32 codel_skb_len_func(const struct sk_buff *skb)
+ {
+       return skb->len;
+@@ -3388,6 +3383,7 @@ struct sk_buff *ieee80211_tx_dequeue(str
+       struct ieee80211_tx_info *info;
+       struct ieee80211_tx_data tx;
+       ieee80211_tx_result r;
++      struct ieee80211_vif *vif;
+       spin_lock_bh(&fq->lock);
+@@ -3404,8 +3400,6 @@ begin:
+       if (!skb)
+               goto out;
+-      ieee80211_set_skb_vif(skb, txqi);
+-
+       hdr = (struct ieee80211_hdr *)skb->data;
+       info = IEEE80211_SKB_CB(skb);
+@@ -3462,6 +3456,34 @@ begin:
+               }
+       }
++      switch (tx.sdata->vif.type) {
++      case NL80211_IFTYPE_MONITOR:
++              if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
++                      vif = &tx.sdata->vif;
++                      break;
++              }
++              tx.sdata = rcu_dereference(local->monitor_sdata);
++              if (tx.sdata) {
++                      vif = &tx.sdata->vif;
++                      info->hw_queue =
++                              vif->hw_queue[skb_get_queue_mapping(skb)];
++              } else if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
++                      ieee80211_free_txskb(&local->hw, skb);
++                      goto begin;
++              } else {
++                      vif = NULL;
++              }
++              break;
++      case NL80211_IFTYPE_AP_VLAN:
++              tx.sdata = container_of(tx.sdata->bss,
++                                      struct ieee80211_sub_if_data, u.ap);
++              /* fall through */
++      default:
++              vif = &tx.sdata->vif;
++              break;
++      }
++
++      IEEE80211_SKB_CB(skb)->control.vif = vif;
+ out:
+       spin_unlock_bh(&fq->lock);
diff --git a/queue-4.9/mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch b/queue-4.9/mac80211-flush-hw_roc_start-work-before-cancelling-the-roc.patch
new file mode 100644 (file)
index 0000000..1f0ce3c
--- /dev/null
@@ -0,0 +1,46 @@
+From 6e46d8ce894374fc135c96a8d1057c6af1fef237 Mon Sep 17 00:00:00 2001
+From: Avraham Stern <avraham.stern@intel.com>
+Date: Fri, 18 Aug 2017 15:33:57 +0300
+Subject: mac80211: flush hw_roc_start work before cancelling the ROC
+
+From: Avraham Stern <avraham.stern@intel.com>
+
+commit 6e46d8ce894374fc135c96a8d1057c6af1fef237 upstream.
+
+When HW ROC is supported it is possible that after the HW notified
+that the ROC has started, the ROC was cancelled and another ROC was
+added while the hw_roc_start worker is waiting on the mutex (since
+cancelling the ROC and adding another one also holds the same mutex).
+As a result, the hw_roc_start worker will continue to run after the
+new ROC is added but before it is actually started by the HW.
+This may result in notifying userspace that the ROC has started before
+it actually does, or in case of management tx ROC, in an attempt to
+tx while not on the right channel.
+
+In addition, when the driver will notify mac80211 that the second ROC
+has started, mac80211 will warn that this ROC has already been
+notified.
+
+Fix this by flushing the hw_roc_start work before cancelling an ROC.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Avraham Stern <avraham.stern@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/mac80211/offchannel.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -707,6 +707,8 @@ static int ieee80211_cancel_roc(struct i
+       if (!cookie)
+               return -ENOENT;
++      flush_work(&local->hw_roc_start);
++
+       mutex_lock(&local->mtx);
+       list_for_each_entry_safe(roc, tmp, &local->roc_list, list) {
+               if (!mgmt_tx && roc->cookie != cookie)
diff --git a/queue-4.9/mac80211_hwsim-use-proper-tx-power.patch b/queue-4.9/mac80211_hwsim-use-proper-tx-power.patch
new file mode 100644 (file)
index 0000000..83fed46
--- /dev/null
@@ -0,0 +1,39 @@
+From 9de981f507474f326e42117858dc9a9321331ae5 Mon Sep 17 00:00:00 2001
+From: Beni Lev <beni.lev@intel.com>
+Date: Tue, 25 Jul 2017 11:25:25 +0300
+Subject: mac80211_hwsim: Use proper TX power
+
+From: Beni Lev <beni.lev@intel.com>
+
+commit 9de981f507474f326e42117858dc9a9321331ae5 upstream.
+
+In struct ieee80211_tx_info, control.vif pointer and rate_driver_data[0]
+falls on the same place, depending on the union usage.
+During the whole TX process, the union is referred to as a control struct,
+which holds the vif that is later used in the tx flow, especially in order
+to derive the used tx power.
+Referring direcly to rate_driver_data[0] and assigning a value to it,
+overwrites the vif pointer, hence making all later references irrelevant.
+Moreover, rate_driver_data[0] isn't used later in the flow in order to
+retrieve the channel that it is pointing to.
+
+Signed-off-by: Beni Lev <beni.lev@intel.com>
+Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/mac80211_hwsim.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/wireless/mac80211_hwsim.c
++++ b/drivers/net/wireless/mac80211_hwsim.c
+@@ -1357,8 +1357,6 @@ static void mac80211_hwsim_tx(struct iee
+                                      txi->control.rates,
+                                      ARRAY_SIZE(txi->control.rates));
+-      txi->rate_driver_data[0] = channel;
+-
+       if (skb->len >= 24 + 8 &&
+           ieee80211_is_probe_resp(hdr->frame_control)) {
+               /* fake header transmission time */