From: Takashi Iwai <tiwai@suse.de>
Subject: kABI workaround for cfg80211 changes
Patch-mainline: Never, kABI workaround
References: CVE-2020-24586 bsc#1185859
Some ugly kABI workaround for the recently introduced wireless core
stack changes:
- The modified ieee80211_data_to_8023_exthdr() with an additional
argument is provided as __ieee80211_data_to_8023_exthdr().
A compat wrapper is defined.
- The ieee80211_fragment_cache field in struct sta_info is factored
out into struct __sta_info. sta_info is embedded there.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
include/net/cfg80211.h | 8 ++++++++
net/mac80211/rx.c | 2 +-
net/mac80211/sta_info.c | 14 +++++++++-----
net/mac80211/sta_info.h | 11 +++++++++--
net/wireless/util.c | 12 +++++++++++-
5 files changed, 38 insertions(+), 9 deletions(-)
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5089,9 +5089,17 @@ unsigned int ieee80211_get_mesh_hdrlen(s
* @data_offset: offset of payload after the 802.11 header
* Return: 0 on success. Non-zero on error.
*/
+#ifdef __GENKSYMS__
int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
const u8 *addr, enum nl80211_iftype iftype,
+ u8 data_offset);
+#else
+/* new version */
+int __ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype,
u8 data_offset, bool is_amsdu);
+#define ieee80211_data_to_8023_exthdr __ieee80211_data_to_8023_exthdr
+#endif
/**
* ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2205,7 +2205,7 @@ ieee80211_rx_h_defragment(struct ieee802
}
if (rx->sta)
- cache = &rx->sta->frags;
+ cache = &sta_frags(rx->sta);
if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
goto out;
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -243,6 +243,8 @@ struct sta_info *sta_info_get_by_idx(str
*/
void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
{
+ struct __sta_info *__sta = container_of(sta, struct __sta_info, sta);
+
/*
* If we had used sta_info_pre_move_state() then we might not
* have gone through the state transitions down again, so do
@@ -273,7 +275,7 @@ void sta_info_free(struct ieee80211_loca
kfree(sta->mesh);
#endif
free_percpu(sta->pcpu_rx_stats);
- kfree(sta);
+ kfree(__sta);
}
/* Caller must hold local->sta_mtx */
@@ -324,11 +326,13 @@ struct sta_info *sta_info_alloc(struct i
struct ieee80211_local *local = sdata->local;
struct ieee80211_hw *hw = &local->hw;
struct sta_info *sta;
+ struct __sta_info *__sta;
int i;
- sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
- if (!sta)
+ __sta = kzalloc(sizeof(*__sta) + hw->sta_data_size, gfp);
+ if (!__sta)
return NULL;
+ sta = &__sta->sta;
if (ieee80211_hw_check(hw, USES_RSS)) {
sta->pcpu_rx_stats =
@@ -377,7 +381,7 @@ struct sta_info *sta_info_alloc(struct i
u64_stats_init(&sta->rx_stats.syncp);
- ieee80211_init_frag_cache(&sta->frags);
+ ieee80211_init_frag_cache(&__sta->frags);
sta->sta_state = IEEE80211_STA_NONE;
@@ -1087,7 +1091,7 @@ static void __sta_info_destroy_part2(str
rate_control_remove_sta_debugfs(sta);
ieee80211_sta_debugfs_remove(sta);
- ieee80211_destroy_frag_cache(&sta->frags);
+ ieee80211_destroy_frag_cache(&sta_frags(sta));
cleanup_single_sta(sta);
}
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -651,12 +651,19 @@ struct sta_info {
struct cfg80211_chan_def tdls_chandef;
- struct ieee80211_fragment_cache frags;
-
/* keep last! */
struct ieee80211_sta sta;
};
+/* XXX frags is factoroed out for SLE kABI compatibility */
+struct __sta_info {
+ struct ieee80211_fragment_cache frags;
+ void *reserved;
+ struct sta_info sta;
+};
+
+#define sta_frags(s) container_of(s, struct __sta_info, sta)->frags
+
static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta)
{
#ifdef CONFIG_MAC80211_MESH
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -438,7 +438,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s
}
EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+int __ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
const u8 *addr, enum nl80211_iftype iftype,
u8 data_offset, bool is_amsdu)
{
@@ -546,6 +546,16 @@ int ieee80211_data_to_8023_exthdr(struct
return 0;
}
+EXPORT_SYMBOL(__ieee80211_data_to_8023_exthdr);
+
+// XXX for SLE kABI compatibility
+#undef ieee80211_data_to_8023_exthdr
+int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype,
+ u8 data_offset)
+{
+ return __ieee80211_data_to_8023_exthdr(skb, ehdr, addr, iftype, data_offset, false);
+}
EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr);
static void