wireless extensions: fix kernel heap content leak
[linux-2.6.git] / net / wireless / wext-core.c
index dbde22b..8f5116f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
+#include <linux/slab.h>
 #include <linux/wireless.h>
 #include <linux/uaccess.h>
 #include <net/cfg80211.h>
@@ -261,44 +262,44 @@ static const unsigned standard_ioctl_num = ARRAY_SIZE(standard_ioctl);
  * we know about.
  */
 static const struct iw_ioctl_description standard_event[] = {
-       [IWEVTXDROP     - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVTXDROP)] = {
                .header_type    = IW_HEADER_TYPE_ADDR,
        },
-       [IWEVQUAL       - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVQUAL)] = {
                .header_type    = IW_HEADER_TYPE_QUAL,
        },
-       [IWEVCUSTOM     - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVCUSTOM)] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = IW_CUSTOM_MAX,
        },
-       [IWEVREGISTERED - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVREGISTERED)] = {
                .header_type    = IW_HEADER_TYPE_ADDR,
        },
-       [IWEVEXPIRED    - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVEXPIRED)] = {
                .header_type    = IW_HEADER_TYPE_ADDR,
        },
-       [IWEVGENIE      - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVGENIE)] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = IW_GENERIC_IE_MAX,
        },
-       [IWEVMICHAELMICFAILURE  - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVMICHAELMICFAILURE)] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = sizeof(struct iw_michaelmicfailure),
        },
-       [IWEVASSOCREQIE - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVASSOCREQIE)] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = IW_GENERIC_IE_MAX,
        },
-       [IWEVASSOCRESPIE        - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVASSOCRESPIE)] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = IW_GENERIC_IE_MAX,
        },
-       [IWEVPMKIDCAND  - IWEVFIRST] = {
+       [IW_EVENT_IDX(IWEVPMKIDCAND)] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
                .max_tokens     = sizeof(struct iw_pmkid_cand),
@@ -453,7 +454,7 @@ void wireless_send_event(struct net_device *        dev,
                if (cmd_index < standard_ioctl_num)
                        descr = &(standard_ioctl[cmd_index]);
        } else {
-               cmd_index = cmd - IWEVFIRST;
+               cmd_index = IW_EVENT_IDX(cmd);
                if (cmd_index < standard_event_num)
                        descr = &(standard_event[cmd_index]);
        }
@@ -781,6 +782,22 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
                }
        }
 
+       if (IW_IS_GET(cmd) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) {
+               /*
+                * If this is a GET, but not NOMAX, it means that the extra
+                * data is not bounded by userspace, but by max_tokens. Thus
+                * set the length to max_tokens. This matches the extra data
+                * allocation.
+                * The driver should fill it with the number of tokens it
+                * provided, and it may check iwp->length rather than having
+                * knowledge of max_tokens. If the driver doesn't change the
+                * iwp->length, this ioctl just copies back max_token tokens
+                * filled with zeroes. Hopefully the driver isn't claiming
+                * them to be valid data.
+                */
+               iwp->length = descr->max_tokens;
+       }
+
        err = handler(dev, info, (union iwreq_data *) iwp, extra);
 
        iwp->length += essid_compat;