From 5079392954c80573234952772dc39dbb5d3179ca Mon Sep 17 00:00:00 2001 From: Pontus Fuchs Date: Mon, 14 Oct 2013 20:49:26 +0300 Subject: [PATCH] Increase buffer size and prevent write beyond buffer end wpa_config_write_key_mgmt has a buffer size of 50. This is not enough to fit the longest case. I used a network with "WPA-PSK WPA-EAP WPA-NONE" and CONFIG_IEEE80211R=y + CONFIG_IEEE80211W=y to produce a string longer than 50 chars. Increase the buffer size to 100 to prevent truncated output. Truncated output is not the only problem. If the buffer end is reached when adding certain key mgmt types the function does not return immediately. This leaves pos > end. When a second os_sprintf is called the calculation of end - pos yields a large positive number for buffer size. End result is a write beyond the buffer end. Fix this by bailing out if buffer end is reached. Signed-hostap: Pontus Fuchs --- wpa_supplicant/config.c | 64 ++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index f8ebc0dee..2b173650e 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -546,10 +546,10 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, char *buf, *pos, *end; int ret; - pos = buf = os_zalloc(50); + pos = buf = os_zalloc(100); if (buf == NULL) return NULL; - end = buf + 50; + end = buf + 100; if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { ret = os_snprintf(pos, end - pos, "%sWPA-PSK", @@ -602,29 +602,59 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, } #ifdef CONFIG_IEEE80211R - if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) - pos += os_snprintf(pos, end - pos, "%sFT-PSK", - pos == buf ? "" : " "); + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) { + ret = os_snprintf(pos, end - pos, "%sFT-PSK", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } - if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) - pos += os_snprintf(pos, end - pos, "%sFT-EAP", - pos == buf ? "" : " "); + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { + ret = os_snprintf(pos, end - pos, "%sFT-EAP", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W - if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) - pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", - pos == buf ? "" : " "); + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) - pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", - pos == buf ? "" : " "); + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS - if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) - pos += os_snprintf(pos, end - pos, "%sWPS", - pos == buf ? "" : " "); + if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { + ret = os_snprintf(pos, end - pos, "%sWPS", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } #endif /* CONFIG_WPS */ return buf;