M7350/external/compat-wireless/patches/09-cfg80211-wext-padding.patch

63 lines
2.1 KiB
Diff
Raw Normal View History

2024-09-09 08:57:42 +00:00
This is a tricky one.
Consider a kernel that has this code in net/wireless/wext-core.c:
#ifdef CONFIG_CFG80211_WEXT
if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)
handlers = dev->ieee80211_ptr->wiphy->wext;
#endif
#ifdef CONFIG_WIRELESS_EXT
if (dev->wireless_handlers)
handlers = dev->wireless_handlers;
#endif
If a kernel is compiled without CONFIG_WIRELESS_EXT then
compat-wireless can't do wireless extensions against it.
However, if the kernel is compiled with CONFIG_CFG80211_WEXT
then it will try to get the wext handlers from struct wiphy.
Now, struct wiphy in the base kernel and struct wiphy in
compat-wireless don't match, so the kernel crashes!!
To fix this, add lots of padding to compat-wireless's
struct wiphy so that the "wext" pointer is guaranteed
to be NULL.
Make sure the padding is larger than the struct so we
don't ever run into this again because the wext pointer
moved due to struct enlargements.
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1964,6 +1964,9 @@ struct wiphy_wowlan_support {
struct wiphy {
/* assign these fields before you register the wiphy */
+#define WIPHY_COMPAT_PAD_SIZE 2048
+ u8 padding[WIPHY_COMPAT_PAD_SIZE];
+
/* permanent MAC address(es) */
u8 perm_addr[ETH_ALEN];
u8 addr_mask[ETH_ALEN];
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -332,6 +332,17 @@ struct wiphy *wiphy_new(const struct cfg
struct cfg80211_registered_device *rdev;
int alloc_size;
+ /*
+ * Make sure the padding is >= the rest of the struct so that we
+ * always keep it large enough to pad out the entire original
+ * kernel's struct. We really only need to make sure it's larger
+ * than the kernel compat is compiled against, but since it'll
+ * only increase in size make sure it's larger than the current
+ * version of it. Subtract since it's included.
+ */
+ BUILD_BUG_ON(WIPHY_COMPAT_PAD_SIZE <
+ sizeof(struct wiphy) - WIPHY_COMPAT_PAD_SIZE);
+
WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key));
WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc));
WARN_ON(ops->connect && !ops->disconnect);