diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 22761531e1be..10698923b38b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -199,8 +199,6 @@ #define IS_DFS_MODE_VALID(mode) ((mode >= DFS_MODE_NONE && \ mode <= DFS_MODE_DEPRIORITIZE)) -#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \ - || (channel >= 36 && channel <= 184)) #define MAX_TXPOWER_SCALE 4 #define CDS_MAX_FEATURE_SET 8 diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 3bc3667dd5de..afd83352d2b8 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -108,6 +108,9 @@ static inline void wlan_hdd_clear_link_layer_stats(hdd_adapter_t *adapter) {} #define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS) #define MAX_SCAN_SSID 10 +#define IS_CHANNEL_VALID(channel) ((channel >= 0 && channel < 15) \ + || (channel >= 36 && channel <= 184)) + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) \ || defined(BACKPORTED_CHANNEL_SWITCH_PRESENT) #define CHANNEL_SWITCH_SUPPORTED diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index eb6e24a2eedd..7dc7b45b5033 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -12152,9 +12152,10 @@ static int __iw_set_pno(struct net_device *dev, struct wlan_objmgr_psoc *psoc; int ret = 0; int offset; - char *ptr; + char *ptr, *data; uint8_t i, j, params; QDF_STATUS status; + size_t len; /* request is a large struct, so we make it static to avoid * stack overflow. This API is only invoked via ioctl, so it @@ -12183,9 +12184,18 @@ static int __iw_set_pno(struct net_device *dev, hdd_debug("PNO data len %d data %s", wrqu->data.length, extra); - ptr = extra; + /* making sure argument string ends with '\0' */ + len = (wrqu->data.length + 1); + data = qdf_mem_malloc(len); + if (!data) { + hdd_err("fail to allocate memory %zu", len); + return -EINVAL; + } + qdf_mem_copy(data, extra, (len-1)); + data[len] = '\0'; + ptr = data; - if (1 != sscanf(ptr, "%hhu%n", &value, &offset)) { + if (1 != sscanf(ptr, " %hhu %n", &value, &offset)) { hdd_err("PNO enable input is not valid %s", ptr); ret = -EINVAL; goto exit; @@ -12210,7 +12220,7 @@ static int __iw_set_pno(struct net_device *dev, ptr += offset; - if (1 != sscanf(ptr, "%hhu %n", &value, &offset)) { + if (1 != sscanf(ptr, " %hhu %n", &value, &offset)) { hdd_err("PNO count input not valid %s", ptr); ret = -EINVAL; goto exit; @@ -12234,7 +12244,7 @@ static int __iw_set_pno(struct net_device *dev, req.networks_list[i].ssid.length = 0; - params = sscanf(ptr, "%hhu %n", + params = sscanf(ptr, " %hhu %n", &(req.networks_list[i].ssid.length), &offset); @@ -12259,7 +12269,7 @@ static int __iw_set_pno(struct net_device *dev, req.networks_list[i].ssid.length); ptr += req.networks_list[i].ssid.length; - params = sscanf(ptr, "%u %u %hhu %n", + params = sscanf(ptr, " %u %u %hhu %n", &(req.networks_list[i].authentication), &(req.networks_list[i].encryption), &(req.networks_list[i].channel_cnt), @@ -12292,13 +12302,18 @@ static int __iw_set_pno(struct net_device *dev, if (0 != req.networks_list[i].channel_cnt) { for (j = 0; j < req.networks_list[i].channel_cnt; j++) { - if (1 != sscanf(ptr, "%hhu %n", &value, + if (1 != sscanf(ptr, " %hhu %n", &value, &offset)) { hdd_err("PNO network channel is not valid %s", ptr); ret = -EINVAL; goto exit; } + if (!IS_CHANNEL_VALID(value)) { + hdd_err("invalid channel: %hhu", value); + ret = -EINVAL; + goto exit; + } req.networks_list[i].channels[j] = cds_chan_to_freq(value); /* Advance to next channel number */ @@ -12306,7 +12321,7 @@ static int __iw_set_pno(struct net_device *dev, } } - if (1 != sscanf(ptr, "%u %n", + if (1 != sscanf(ptr, " %u %n", &(req.networks_list[i].bc_new_type), &offset)) { hdd_err("PNO broadcast network type is not valid %s", @@ -12314,13 +12329,19 @@ static int __iw_set_pno(struct net_device *dev, ret = -EINVAL; goto exit; } + if (req.networks_list[i].bc_new_type > 2) { + hdd_err("invalid bcast nw type: %u", + req.networks_list[i].bc_new_type); + ret = -EINVAL; + goto exit; + } hdd_debug("PNO bcastNetwType %d offset %d", req.networks_list[i].bc_new_type, offset); /* Advance to rssi Threshold */ ptr += offset; - if (1 != sscanf(ptr, "%d %n", + if (1 != sscanf(ptr, " %d %n", &(req.networks_list[i].rssi_thresh), &offset)) { hdd_err("PNO rssi threshold input is not valid %s", @@ -12335,13 +12356,19 @@ static int __iw_set_pno(struct net_device *dev, } /* For ucNetworkCount */ req.fast_scan_period = 0; - if (sscanf(ptr, "%u %n", &(req.fast_scan_period), &offset) > 0) { + if (sscanf(ptr, " %u %n", &(req.fast_scan_period), &offset) > 0) { req.fast_scan_period *= MSEC_PER_SEC; ptr += offset; } + if (req.fast_scan_period == 0) { + hdd_err("invalid fast scan period %u", + req.fast_scan_period); + ret = -EINVAL; + goto exit; + } req.fast_scan_max_cycles = 0; - if (sscanf(ptr, "%hhu %n", &value, + if (sscanf(ptr, " %hhu %n", &value, &offset) > 0) ptr += offset; req.fast_scan_max_cycles = value; @@ -12362,6 +12389,7 @@ static int __iw_set_pno(struct net_device *dev, exit: wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); + qdf_mem_free(data); return ret; }