From 747ba1067d3161d1bdbf23e90e6d1551b861bd2e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 17 Nov 2015 19:01:15 +0200 Subject: [PATCH] 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 --- src/drivers/driver_nl80211_capa.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 59a8efb32..25fed11ed 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -966,6 +966,7 @@ struct phy_info_arg { u16 *num_modes; struct hostapd_hw_modes *modes; int last_mode, last_chan_idx; + int failed; }; 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, sizeof(struct hostapd_channel_data)); if (!channel) - return NL_SKIP; + return NL_STOP; mode->channels = channel; 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)); if (!mode->rates) - return NL_SKIP; + return NL_STOP; 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, *phy_info->num_modes + 1, sizeof(*mode)); - if (!mode) - return NL_SKIP; + if (!mode) { + phy_info->failed = 1; + return NL_STOP; + } phy_info->modes = mode; 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], tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]); ret = phy_info_freqs(phy_info, mode, tb_band[NL80211_BAND_ATTR_FREQS]); - if (ret != NL_OK) - return ret; - ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]); - if (ret != NL_OK) + if (ret == NL_OK) + ret = phy_info_rates(mode, tb_band[NL80211_BAND_ATTR_RATES]); + if (ret != NL_OK) { + phy_info->failed = 1; return ret; + } return NL_OK; } @@ -1599,6 +1603,7 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) .num_modes = num_modes, .modes = NULL, .last_mode = -1, + .failed = 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) { 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, num_modes); }