| From foo@baz Thu Feb 8 03:32:24 CET 2018 |
| From: Dan Williams <dan.j.williams@intel.com> |
| Date: Mon, 29 Jan 2018 17:03:15 -0800 |
| Subject: nl80211: Sanitize array index in parse_txq_params |
| |
| From: Dan Williams <dan.j.williams@intel.com> |
| |
| |
| (cherry picked from commit 259d8c1e984318497c84eef547bbb6b1d9f4eb05) |
| |
| Wireless drivers rely on parse_txq_params to validate that txq_params->ac |
| is less than NL80211_NUM_ACS by the time the low-level driver's ->conf_tx() |
| handler is called. Use a new helper, array_index_nospec(), to sanitize |
| txq_params->ac with respect to speculation. I.e. ensure that any |
| speculation into ->conf_tx() handlers is done with a value of |
| txq_params->ac that is within the bounds of [0, NL80211_NUM_ACS). |
| |
| Reported-by: Christian Lamparter <chunkeey@gmail.com> |
| Reported-by: Elena Reshetova <elena.reshetova@intel.com> |
| Signed-off-by: Dan Williams <dan.j.williams@intel.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Acked-by: Johannes Berg <johannes@sipsolutions.net> |
| Cc: linux-arch@vger.kernel.org |
| Cc: kernel-hardening@lists.openwall.com |
| Cc: gregkh@linuxfoundation.org |
| Cc: linux-wireless@vger.kernel.org |
| Cc: torvalds@linux-foundation.org |
| Cc: "David S. Miller" <davem@davemloft.net> |
| Cc: alan@linux.intel.com |
| Link: https://lkml.kernel.org/r/151727419584.33451.7700736761686184303.stgit@dwillia2-desk3.amr.corp.intel.com |
| Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/wireless/nl80211.c | 9 ++++++--- |
| 1 file changed, 6 insertions(+), 3 deletions(-) |
| |
| --- a/net/wireless/nl80211.c |
| +++ b/net/wireless/nl80211.c |
| @@ -16,6 +16,7 @@ |
| #include <linux/nl80211.h> |
| #include <linux/rtnetlink.h> |
| #include <linux/netlink.h> |
| +#include <linux/nospec.h> |
| #include <linux/etherdevice.h> |
| #include <net/net_namespace.h> |
| #include <net/genetlink.h> |
| @@ -2014,20 +2015,22 @@ static const struct nla_policy txq_param |
| static int parse_txq_params(struct nlattr *tb[], |
| struct ieee80211_txq_params *txq_params) |
| { |
| + u8 ac; |
| + |
| if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] || |
| !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || |
| !tb[NL80211_TXQ_ATTR_AIFS]) |
| return -EINVAL; |
| |
| - txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); |
| + ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); |
| txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); |
| txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); |
| txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); |
| txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); |
| |
| - if (txq_params->ac >= NL80211_NUM_ACS) |
| + if (ac >= NL80211_NUM_ACS) |
| return -EINVAL; |
| - |
| + txq_params->ac = array_index_nospec(ac, NL80211_NUM_ACS); |
| return 0; |
| } |
| |