On 2019-04-26 15:07, Johannes Berg wrote:
@@ -13354,6 +13367,42 @@ static int parse_tid_conf(struct
cfg80211_registered_device *rdev,
nla_get_u8(attrs[NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL]);
}
+ if (attrs[NL80211_ATTR_TID_CONFIG_TX_RATES_TYPE]) {
+ int idx;
+ enum nl80211_attrs attr;
+
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_TID_TX_BITRATE_MASK))
+ return -EOPNOTSUPP;
+
+ if (peer &&
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_PER_STA_TX_BITRATE_MASK))
+ return -EOPNOTSUPP;
+
+ idx = NL80211_ATTR_TID_CONFIG_TX_RATES_TYPE;
+ tid_conf->txrate_type = nla_get_u8(attrs[idx]);
+
+ tid_conf->tid_conf_mask |= IEEE80211_TID_CONF_TX_BITRATE;
+ if (tid_conf->txrate_type != NL80211_TX_RATE_AUTOMATIC) {
+ tid_conf->mask =
+ kzalloc(sizeof(struct cfg80211_bitrate_mask),
+ GFP_KERNEL);
You leak this
+ if (!tid_conf->mask)
+ return -ENOMEM;
+
+ attr = NL80211_ATTR_TID_CONFIG_TX_RATES;
+ ret = nl80211_parse_tx_bitrate_mask(attrs, rdev, attr,
+ tid_conf->mask);
+ if (ret) {
+ kfree(tid_conf->mask);
+ return ret;
+ }
+ } else {
+ tid_conf->mask = NULL;
+ }
+ }
+
return 0;
}
@@ -13407,7 +13456,7 @@ static int nl80211_set_tid_config(struct
sk_buff *skb,
}
ret = parse_tid_conf(rdev, attrs, &tid_conf->tid_conf[conf_idx],
- tid_conf->peer);
+ info, tid_conf->peer);
if (ret)
goto bad_tid_conf;
Practically everywhere, but particularly in the bad case in the next
loop iteration etc?
Yeah. I will fix this in next version.