cfg80211: prevent speculation on cfg80211_classify8021d() return
It's possible that the caller of cfg80211_classify8021d() uses the value to index an array, like mac80211 in ieee80211_downgrade_queue(). Prevent speculation on the return value. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
ff1bab1ba1
commit
1fc9b72533
|
@ -5,7 +5,7 @@
|
|||
* Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||
* Copyright 2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*/
|
||||
#include <linux/export.h>
|
||||
#include <linux/bitops.h>
|
||||
|
@ -19,6 +19,7 @@
|
|||
#include <linux/mpls.h>
|
||||
#include <linux/gcd.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/nospec.h>
|
||||
#include "core.h"
|
||||
#include "rdev-ops.h"
|
||||
|
||||
|
@ -715,20 +716,25 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
|
|||
{
|
||||
unsigned int dscp;
|
||||
unsigned char vlan_priority;
|
||||
unsigned int ret;
|
||||
|
||||
/* skb->priority values from 256->263 are magic values to
|
||||
* directly indicate a specific 802.1d priority. This is used
|
||||
* to allow 802.1d priority to be passed directly in from VLAN
|
||||
* tags, etc.
|
||||
*/
|
||||
if (skb->priority >= 256 && skb->priority <= 263)
|
||||
return skb->priority - 256;
|
||||
if (skb->priority >= 256 && skb->priority <= 263) {
|
||||
ret = skb->priority - 256;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK)
|
||||
>> VLAN_PRIO_SHIFT;
|
||||
if (vlan_priority > 0)
|
||||
return vlan_priority;
|
||||
if (vlan_priority > 0) {
|
||||
ret = vlan_priority;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
switch (skb->protocol) {
|
||||
|
@ -747,8 +753,9 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
|
|||
if (!mpls)
|
||||
return 0;
|
||||
|
||||
return (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
|
||||
ret = (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
|
||||
>> MPLS_LS_TC_SHIFT;
|
||||
goto out;
|
||||
}
|
||||
case htons(ETH_P_80221):
|
||||
/* 802.21 is always network control traffic */
|
||||
|
@ -761,18 +768,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
|
|||
unsigned int i, tmp_dscp = dscp >> 2;
|
||||
|
||||
for (i = 0; i < qos_map->num_des; i++) {
|
||||
if (tmp_dscp == qos_map->dscp_exception[i].dscp)
|
||||
return qos_map->dscp_exception[i].up;
|
||||
if (tmp_dscp == qos_map->dscp_exception[i].dscp) {
|
||||
ret = qos_map->dscp_exception[i].up;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (tmp_dscp >= qos_map->up[i].low &&
|
||||
tmp_dscp <= qos_map->up[i].high)
|
||||
return i;
|
||||
tmp_dscp <= qos_map->up[i].high) {
|
||||
ret = i;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dscp >> 5;
|
||||
ret = dscp >> 5;
|
||||
out:
|
||||
return array_index_nospec(ret, IEEE80211_NUM_TIDS);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_classify8021d);
|
||||
|
||||
|
|
Loading…
Reference in New Issue