diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 89152a4dc7af..7233eefb0cc6 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -8061,6 +8061,38 @@ static int iw_set_keepalive_params(struct net_device *dev, } #ifdef WLAN_FEATURE_PACKET_FILTERING +/** + * validate_packet_filter_params_size() - Validate the size of the params rcvd + * @priv_data: Pointer to the priv data from user space + * @request: Pointer to the struct containing the copied data from user space + * + * Return: False on invalid length, true otherwise + */ +static bool validate_packet_filter_params_size(struct pkt_filter_cfg *request, + uint16_t length) +{ + int max_params_size, rcvd_params_size; + + max_params_size = HDD_MAX_CMP_PER_PACKET_FILTER * + sizeof(struct pkt_filter_param_cfg); + + if (length < sizeof(struct pkt_filter_cfg) - max_params_size) { + hdd_err("Less than minimum number of arguments needed"); + return false; + } + + rcvd_params_size = request->num_params * + sizeof(struct pkt_filter_param_cfg); + + if (length != sizeof(struct pkt_filter_cfg) - + max_params_size + rcvd_params_size) { + hdd_err("Arguments do not match the number of params provided"); + return false; + } + + return true; +} + /** * __iw_set_packet_filter_params() - set packet filter parameters in target * @dev: Pointer to netdev @@ -8101,8 +8133,7 @@ static int __iw_set_packet_filter_params(struct net_device *dev, return -EINVAL; } - if ((NULL == priv_data.pointer) || (0 == priv_data.length) || - priv_data.length < sizeof(struct pkt_filter_cfg)) { + if ((NULL == priv_data.pointer) || (0 == priv_data.length)) { hdd_err("invalid priv data %pK or invalid priv data length %d", priv_data.pointer, priv_data.length); return -EINVAL; @@ -8122,11 +8153,18 @@ static int __iw_set_packet_filter_params(struct net_device *dev, /* copy data using copy_from_user */ request = mem_alloc_copy_from_user_helper(priv_data.pointer, priv_data.length); + if (NULL == request) { hdd_err("mem_alloc_copy_from_user_helper fail"); return -ENOMEM; } + if (!validate_packet_filter_params_size(request, priv_data.length)) { + hdd_err("Invalid priv data length %d", priv_data.length); + qdf_mem_free(request); + return -EINVAL; + } + if (request->filter_action == HDD_RCV_FILTER_SET) hdd_ctx->user_configured_pkt_filter_rules |= 1 << request->filter_id;