nl80211: Do not return incomplete hw capability info
If a memory allocation fails while parsing driver capabilities, drop all mode/channel/rate information instead of returning possibly partial information. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
89a79ca2b9
commit
747ba1067d
1 changed files with 23 additions and 8 deletions
|
@ -966,6 +966,7 @@ struct phy_info_arg {
|
||||||
u16 *num_modes;
|
u16 *num_modes;
|
||||||
struct hostapd_hw_modes *modes;
|
struct hostapd_hw_modes *modes;
|
||||||
int last_mode, last_chan_idx;
|
int last_mode, last_chan_idx;
|
||||||
|
int failed;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
|
static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa,
|
||||||
|
@ -1083,7 +1084,7 @@ static int phy_info_freqs(struct phy_info_arg *phy_info,
|
||||||
mode->num_channels + new_channels,
|
mode->num_channels + new_channels,
|
||||||
sizeof(struct hostapd_channel_data));
|
sizeof(struct hostapd_channel_data));
|
||||||
if (!channel)
|
if (!channel)
|
||||||
return NL_SKIP;
|
return NL_STOP;
|
||||||
|
|
||||||
mode->channels = channel;
|
mode->channels = channel;
|
||||||
mode->num_channels += new_channels;
|
mode->num_channels += new_channels;
|
||||||
|
@ -1129,7 +1130,7 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb)
|
||||||
|
|
||||||
mode->rates = os_calloc(mode->num_rates, sizeof(int));
|
mode->rates = os_calloc(mode->num_rates, sizeof(int));
|
||||||
if (!mode->rates)
|
if (!mode->rates)
|
||||||
return NL_SKIP;
|
return NL_STOP;
|
||||||
|
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
||||||
|
@ -1158,8 +1159,10 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
|
||||||
mode = os_realloc_array(phy_info->modes,
|
mode = os_realloc_array(phy_info->modes,
|
||||||
*phy_info->num_modes + 1,
|
*phy_info->num_modes + 1,
|
||||||
sizeof(*mode));
|
sizeof(*mode));
|
||||||
if (!mode)
|
if (!mode) {
|
||||||
return NL_SKIP;
|
phy_info->failed = 1;
|
||||||
|
return NL_STOP;
|
||||||
|
}
|
||||||
phy_info->modes = mode;
|
phy_info->modes = mode;
|
||||||
|
|
||||||
mode = &phy_info->modes[*(phy_info->num_modes)];
|
mode = &phy_info->modes[*(phy_info->num_modes)];
|
||||||
|
@ -1195,11 +1198,12 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
|
||||||
phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
|
phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
|
||||||
tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
|
tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
|
||||||
ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
|
ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]);
|
||||||
if (ret != NL_OK)
|
if (ret == NL_OK)
|
||||||
return ret;
|
|
||||||
ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
|
ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]);
|
||||||
if (ret != NL_OK)
|
if (ret != NL_OK) {
|
||||||
|
phy_info->failed = 1;
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return NL_OK;
|
return NL_OK;
|
||||||
}
|
}
|
||||||
|
@ -1599,6 +1603,7 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
|
||||||
.num_modes = num_modes,
|
.num_modes = num_modes,
|
||||||
.modes = NULL,
|
.modes = NULL,
|
||||||
.last_mode = -1,
|
.last_mode = -1,
|
||||||
|
.failed = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
*num_modes = 0;
|
*num_modes = 0;
|
||||||
|
@ -1615,6 +1620,16 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags)
|
||||||
|
|
||||||
if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
|
if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) {
|
||||||
nl80211_set_regulatory_flags(drv, &result);
|
nl80211_set_regulatory_flags(drv, &result);
|
||||||
|
if (result.failed) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; result.modes && i < *num_modes; i++) {
|
||||||
|
os_free(result.modes[i].channels);
|
||||||
|
os_free(result.modes[i].rates);
|
||||||
|
}
|
||||||
|
os_free(result.modes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return wpa_driver_nl80211_postprocess_modes(result.modes,
|
return wpa_driver_nl80211_postprocess_modes(result.modes,
|
||||||
num_modes);
|
num_modes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue