Skip to content

Commit

Permalink
nl80211: validate some input better
Browse files Browse the repository at this point in the history
This patch changes nl80211 to:
 * validate that any IE input is a valid IE (stream)
 * move some validation code before locking
 * require that a reason code is given for both deauth/disassoc

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Apr 22, 2009
1 parent b0741a1 commit f4a11bb
Showing 1 changed file with 77 additions and 37 deletions.
114 changes: 77 additions & 37 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,36 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
};

/* IE validation */
static bool is_valid_ie_attr(const struct nlattr *attr)
{
const u8 *pos;
int len;

if (!attr)
return true;

pos = nla_data(attr);
len = nla_len(attr);

while (len) {
u8 elemlen;

if (len < 2)
return false;
len -= 2;

elemlen = pos[1];
if (elemlen > len)
return false;

len -= elemlen;
pos += 2 + elemlen;
}

return true;
}

/* message building helper */
static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq,
int flags, u8 cmd)
Expand Down Expand Up @@ -1069,6 +1099,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
struct beacon_parameters params;
int haveinfo = 0;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]))
return -EINVAL;

rtnl_lock();

err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
Expand Down Expand Up @@ -2442,6 +2475,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
enum ieee80211_band band;
size_t ie_len;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;

rtnl_lock();

err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
Expand Down Expand Up @@ -2710,6 +2746,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
struct wiphy *wiphy;
int err;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;

if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;

rtnl_lock();

err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
Expand All @@ -2731,11 +2773,6 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
goto out;
}

if (!info->attrs[NL80211_ATTR_MAC]) {
err = -EINVAL;
goto out;
}

wiphy = &drv->wiphy;
memset(&req, 0, sizeof(req));

Expand Down Expand Up @@ -2788,6 +2825,13 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
struct wiphy *wiphy;
int err;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;

if (!info->attrs[NL80211_ATTR_MAC] ||
!info->attrs[NL80211_ATTR_SSID])
return -EINVAL;

rtnl_lock();

err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
Expand All @@ -2809,12 +2853,6 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
goto out;
}

if (!info->attrs[NL80211_ATTR_MAC] ||
!info->attrs[NL80211_ATTR_SSID]) {
err = -EINVAL;
goto out;
}

wiphy = &drv->wiphy;
memset(&req, 0, sizeof(req));

Expand Down Expand Up @@ -2856,6 +2894,15 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
struct wiphy *wiphy;
int err;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;

if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;

if (!info->attrs[NL80211_ATTR_REASON_CODE])
return -EINVAL;

rtnl_lock();

err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
Expand All @@ -2877,24 +2924,16 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
goto out;
}

if (!info->attrs[NL80211_ATTR_MAC]) {
err = -EINVAL;
goto out;
}

wiphy = &drv->wiphy;
memset(&req, 0, sizeof(req));

req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

if (info->attrs[NL80211_ATTR_REASON_CODE]) {
req.reason_code =
nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
if (req.reason_code == 0) {
/* Reason Code 0 is reserved */
err = -EINVAL;
goto out;
}
req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
if (req.reason_code == 0) {
/* Reason Code 0 is reserved */
err = -EINVAL;
goto out;
}

if (info->attrs[NL80211_ATTR_IE]) {
Expand All @@ -2920,6 +2959,15 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
struct wiphy *wiphy;
int err;

if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
return -EINVAL;

if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;

if (!info->attrs[NL80211_ATTR_REASON_CODE])
return -EINVAL;

rtnl_lock();

err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
Expand All @@ -2941,24 +2989,16 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
goto out;
}

if (!info->attrs[NL80211_ATTR_MAC]) {
err = -EINVAL;
goto out;
}

wiphy = &drv->wiphy;
memset(&req, 0, sizeof(req));

req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

if (info->attrs[NL80211_ATTR_REASON_CODE]) {
req.reason_code =
nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
if (req.reason_code == 0) {
/* Reason Code 0 is reserved */
err = -EINVAL;
goto out;
}
req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
if (req.reason_code == 0) {
/* Reason Code 0 is reserved */
err = -EINVAL;
goto out;
}

if (info->attrs[NL80211_ATTR_IE]) {
Expand Down

0 comments on commit f4a11bb

Please sign in to comment.