compat-wireless: add struct padding to fix wext issue
authorJohannes Berg <johannes.berg@intel.com>
Thu, 6 Oct 2011 20:05:39 +0000 (22:05 +0200)
committerLuis R. Rodriguez <mcgrof@qca.qualcomm.com>
Thu, 6 Oct 2011 20:44:24 +0000 (13:44 -0700)
See description in the patch :-)

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
patches/09-cfg80211-wext-padding.patch [new file with mode: 0644]

diff --git a/patches/09-cfg80211-wext-padding.patch b/patches/09-cfg80211-wext-padding.patch
new file mode 100644 (file)
index 0000000..d7b1d88
--- /dev/null
@@ -0,0 +1,62 @@
+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   2011-10-04 10:49:07.000000000 +0200
++++ b/include/net/cfg80211.h   2011-10-06 21:50:47.000000000 +0200
+@@ -1904,6 +1904,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      2011-09-23 10:34:28.000000000 +0200
++++ b/net/wireless/core.c      2011-10-06 21:52:02.000000000 +0200
+@@ -330,6 +330,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);