63 lines
2.1 KiB
Diff
63 lines
2.1 KiB
Diff
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);
|