nl80211: check nla_parse() return values
authorJohannes Berg <johannes.berg@intel.com>
Fri, 24 Jan 2014 09:17:47 +0000 (10:17 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 4 Feb 2014 20:57:56 +0000 (21:57 +0100)
If there's a policy, then nla_parse() return values must be
checked, otherwise the policy is useless and there's nothing
that ensures the attributes are actually what we expect them
to be.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/nl80211.c

index 55abbe5b34f6623a238bc516a17be220f9ab35ff..9ed6ef6fd2c5413250dd9d11e6566cd5723c6546 100644 (file)
@@ -2055,10 +2055,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                nla_for_each_nested(nl_txq_params,
                                    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
                                    rem_txq_params) {
-                       nla_parse(tb, NL80211_TXQ_ATTR_MAX,
-                                 nla_data(nl_txq_params),
-                                 nla_len(nl_txq_params),
-                                 txq_params_policy);
+                       result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
+                                          nla_data(nl_txq_params),
+                                          nla_len(nl_txq_params),
+                                          txq_params_policy);
+                       if (result)
+                               return result;
                        result = parse_txq_params(tb, &txq_params);
                        if (result)
                                return result;
@@ -5198,9 +5200,11 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
 
        nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
                            rem_reg_rules) {
-               nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
-                         nla_data(nl_reg_rule), nla_len(nl_reg_rule),
-                         reg_rule_policy);
+               r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
+                             nla_data(nl_reg_rule), nla_len(nl_reg_rule),
+                             reg_rule_policy);
+               if (r)
+                       goto bad_reg;
                r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
                if (r)
                        goto bad_reg;
@@ -5622,9 +5626,11 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
                                    tmp) {
                        struct nlattr *ssid, *rssi;
 
-                       nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
-                                 nla_data(attr), nla_len(attr),
-                                 nl80211_match_policy);
+                       err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+                                       nla_data(attr), nla_len(attr),
+                                       nl80211_match_policy);
+                       if (err)
+                               goto out_free;
                        ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
                        if (ssid) {
                                if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
@@ -7499,16 +7505,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
         * directly to the enum ieee80211_band values used in cfg80211.
         */
        BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
-       nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
-       {
+       nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
                enum ieee80211_band band = nla_type(tx_rates);
+               int err;
+
                if (band < 0 || band >= IEEE80211_NUM_BANDS)
                        return -EINVAL;
                sband = rdev->wiphy.bands[band];
                if (sband == NULL)
                        return -EINVAL;
-               nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
-                         nla_len(tx_rates), nl80211_txattr_policy);
+               err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
+                               nla_len(tx_rates), nl80211_txattr_policy);
+               if (err)
+                       return err;
                if (tb[NL80211_TXRATE_LEGACY]) {
                        mask.control[band].legacy = rateset_to_mask(
                                sband,