diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index 8bfd64b46ce8..f79fe9763778 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/core/hdd/src/wlan_hdd_ioctl.c @@ -118,9 +118,16 @@ typedef int (*hdd_drv_cmd_handler_t)(hdd_adapter_t *adapter, uint8_t cmd_name_len, struct hdd_priv_data *priv_data); +/** + * struct hdd_drv_cmd - Structure to store ioctl command handling info + * @cmd: Name of the command + * @handler: Command handler to be invoked + * @args: Set to true if command expects input parameters + */ struct hdd_drv_cmd { const char *cmd; hdd_drv_cmd_handler_t handler; + bool args; }; #ifdef WLAN_FEATURE_EXTWOW_SUPPORT @@ -130,6 +137,24 @@ struct hdd_drv_cmd { static uint16_t cesium_pid; +/** + * drv_cmd_validate() - Validates for space in hdd driver command + * @command: pointer to input data (its a NULL terminated string) + * @len: length of command name + * + * This function checks for space after command name and if no space + * is found returns error. + * + * Return: 0 for success non-zero for failure + */ +static int drv_cmd_validate(uint8_t *command, int len) +{ + if (command[len] != ' ') + return -EINVAL; + + return 0; +} + #ifdef FEATURE_WLAN_ESE struct tsm_priv { tAniTrafStrmMetrics tsm_metrics; @@ -895,6 +920,7 @@ static int hdd_parse_reassoc_v1(hdd_adapter_t *adapter, const char *command) * @adapter: Adapter upon which the command was received * @command: Command that was received, ASCII command * followed by binary data + * @total_len: Total length of the command received * * This function parses the v2 REASSOC command with the format * @@ -902,12 +928,18 @@ static int hdd_parse_reassoc_v1(hdd_adapter_t *adapter, const char *command) * * Return: 0 for success non-zero for failure */ -static int hdd_parse_reassoc_v2(hdd_adapter_t *adapter, const char *command) +static int hdd_parse_reassoc_v2(hdd_adapter_t *adapter, const char *command, + int total_len) { struct android_wifi_reassoc_params params; tSirMacAddr bssid; int ret; + if (total_len < sizeof(params) + 8) { + hdd_err("Invalid command length"); + return -EINVAL; + } + /* The params are located after "REASSOC " */ memcpy(¶ms, command + 8, sizeof(params)); @@ -924,6 +956,7 @@ static int hdd_parse_reassoc_v2(hdd_adapter_t *adapter, const char *command) * hdd_parse_reassoc() - parse the REASSOC command * @adapter: Adapter upon which the command was received * @command: Command that was received + * @total_len: Total length of the command received * * There are two different versions of the REASSOC command. Version 1 * of the command contains a parameter list that is ASCII characters @@ -934,7 +967,8 @@ static int hdd_parse_reassoc_v2(hdd_adapter_t *adapter, const char *command) * * Return: 0 for success non-zero for failure */ -static int hdd_parse_reassoc(hdd_adapter_t *adapter, const char *command) +static int hdd_parse_reassoc(hdd_adapter_t *adapter, const char *command, + int total_len) { int ret; @@ -951,10 +985,16 @@ static int hdd_parse_reassoc(hdd_adapter_t *adapter, const char *command) * 1111111111222222 * 01234567890123456789012345 */ + + if (total_len < 26) { + hdd_err("Invalid command, total_len = %d", total_len); + return -EINVAL; + } + if (command[25]) ret = hdd_parse_reassoc_v1(adapter, command); else - ret = hdd_parse_reassoc_v2(adapter, command); + ret = hdd_parse_reassoc_v2(adapter, command, total_len); return ret; } @@ -1168,13 +1208,20 @@ hdd_parse_sendactionframe_v2(hdd_adapter_t *adapter, struct android_wifi_af_params *params; tSirMacAddr bssid; int ret; + int len_wo_payload = 0; /* The params are located after "SENDACTIONFRAME " */ total_len -= 16; + len_wo_payload = sizeof(*params) - ANDROID_WIFI_ACTION_FRAME_SIZE; + if (total_len <= len_wo_payload) { + hdd_err("Invalid command len"); + return -EINVAL; + } + params = (struct android_wifi_af_params *)(command + 16); if (params->len <= 0 || params->len > ANDROID_WIFI_ACTION_FRAME_SIZE || - (params->len > total_len)) { + (params->len > (total_len - len_wo_payload))) { hdd_err("Invalid payload length: %d", params->len); return -EINVAL; } @@ -2201,6 +2248,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *adapter, uint8_t *command) sme_get_config_param(hHal, sme_config); if (strncmp(command, "SETDWELLTIME ACTIVE MAX", 23) == 0) { + if (drv_cmd_validate(command, 23)) + return -EINVAL; + value = value + 24; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || @@ -2213,6 +2263,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *adapter, uint8_t *command) sme_config->csrConfig.nActiveMaxChnTime = val; sme_update_config(hHal, sme_config); } else if (strncmp(command, "SETDWELLTIME ACTIVE MIN", 23) == 0) { + if (drv_cmd_validate(command, 23)) + return -EINVAL; + value = value + 24; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_ACTIVE_MIN_CHANNEL_TIME_MIN || @@ -2225,6 +2278,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *adapter, uint8_t *command) sme_config->csrConfig.nActiveMinChnTime = val; sme_update_config(hHal, sme_config); } else if (strncmp(command, "SETDWELLTIME PASSIVE MAX", 24) == 0) { + if (drv_cmd_validate(command, 24)) + return -EINVAL; + value = value + 25; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_PASSIVE_MAX_CHANNEL_TIME_MIN || @@ -2237,6 +2293,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *adapter, uint8_t *command) sme_config->csrConfig.nPassiveMaxChnTime = val; sme_update_config(hHal, sme_config); } else if (strncmp(command, "SETDWELLTIME PASSIVE MIN", 24) == 0) { + if (drv_cmd_validate(command, 24)) + return -EINVAL; + value = value + 25; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_PASSIVE_MIN_CHANNEL_TIME_MIN || @@ -2249,6 +2308,9 @@ static int hdd_set_dwell_time(hdd_adapter_t *adapter, uint8_t *command) sme_config->csrConfig.nPassiveMinChnTime = val; sme_update_config(hHal, sme_config); } else if (strncmp(command, "SETDWELLTIME", 12) == 0) { + if (drv_cmd_validate(command, 12)) + return -EINVAL; + value = value + 13; temp = kstrtou32(value, 10, &val); if (temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || @@ -3990,7 +4052,7 @@ static int drv_cmd_reassoc(hdd_adapter_t *adapter, uint8_t command_len, struct hdd_priv_data *priv_data) { - return hdd_parse_reassoc(adapter, command); + return hdd_parse_reassoc(adapter, command, priv_data->total_len); } static int drv_cmd_set_wes_mode(hdd_adapter_t *adapter, @@ -6705,105 +6767,112 @@ static int drv_cmd_set_channel_switch(hdd_adapter_t *adapter, * IOCTL driver commands and the handler for each of them. */ static const struct hdd_drv_cmd hdd_drv_cmds[] = { - {"P2P_DEV_ADDR", drv_cmd_p2p_dev_addr}, - {"P2P_SET_NOA", drv_cmd_p2p_set_noa}, - {"P2P_SET_PS", drv_cmd_p2p_set_ps}, - {"SETBAND", drv_cmd_set_band}, - {"SETWMMPS", drv_cmd_set_wmmps}, - {"COUNTRY", drv_cmd_country}, - {"SETSUSPENDMODE", drv_cmd_dummy}, - {"SET_AP_WPS_P2P_IE", drv_cmd_dummy}, - {"BTCOEXSCAN", drv_cmd_dummy}, - {"RXFILTER", drv_cmd_dummy}, - {"SETROAMTRIGGER", drv_cmd_set_roam_trigger}, - {"GETROAMTRIGGER", drv_cmd_get_roam_trigger}, - {"SETROAMSCANPERIOD", drv_cmd_set_roam_scan_period}, - {"GETROAMSCANPERIOD", drv_cmd_get_roam_scan_period}, - {"SETROAMSCANREFRESHPERIOD", drv_cmd_set_roam_scan_refresh_period}, - {"GETROAMSCANREFRESHPERIOD", drv_cmd_get_roam_scan_refresh_period}, - {"SETROAMMODE", drv_cmd_set_roam_mode}, - {"GETROAMMODE", drv_cmd_get_roam_mode}, - {"SETROAMDELTA", drv_cmd_set_roam_delta}, - {"GETROAMDELTA", drv_cmd_get_roam_delta}, - {"GETBAND", drv_cmd_get_band}, - {"SETROAMSCANCHANNELS", drv_cmd_set_roam_scan_channels}, - {"GETROAMSCANCHANNELS", drv_cmd_get_roam_scan_channels}, - {"GETCCXMODE", drv_cmd_get_ccx_mode}, - {"GETOKCMODE", drv_cmd_get_okc_mode}, - {"GETFASTROAM", drv_cmd_get_fast_roam}, - {"GETFASTTRANSITION", drv_cmd_get_fast_transition}, - {"SETROAMSCANCHANNELMINTIME", drv_cmd_set_roam_scan_channel_min_time}, - {"SENDACTIONFRAME", drv_cmd_send_action_frame}, - {"GETROAMSCANCHANNELMINTIME", drv_cmd_get_roam_scan_channel_min_time}, - {"SETSCANCHANNELTIME", drv_cmd_set_scan_channel_time}, - {"GETSCANCHANNELTIME", drv_cmd_get_scan_channel_time}, - {"SETSCANHOMETIME", drv_cmd_set_scan_home_time}, - {"GETSCANHOMETIME", drv_cmd_get_scan_home_time}, - {"SETROAMINTRABAND", drv_cmd_set_roam_intra_band}, - {"GETROAMINTRABAND", drv_cmd_get_roam_intra_band}, - {"SETSCANNPROBES", drv_cmd_set_scan_n_probes}, - {"GETSCANNPROBES", drv_cmd_get_scan_n_probes}, - {"SETSCANHOMEAWAYTIME", drv_cmd_set_scan_home_away_time}, - {"GETSCANHOMEAWAYTIME", drv_cmd_get_scan_home_away_time}, - {"REASSOC", drv_cmd_reassoc}, - {"SETWESMODE", drv_cmd_set_wes_mode}, - {"GETWESMODE", drv_cmd_get_wes_mode}, - {"SETOPPORTUNISTICRSSIDIFF", drv_cmd_set_opportunistic_rssi_diff}, - {"GETOPPORTUNISTICRSSIDIFF", drv_cmd_get_opportunistic_rssi_diff}, - {"SETROAMRESCANRSSIDIFF", drv_cmd_set_roam_rescan_rssi_diff}, - {"GETROAMRESCANRSSIDIFF", drv_cmd_get_roam_rescan_rssi_diff}, - {"SETFASTROAM", drv_cmd_set_fast_roam}, - {"SETFASTTRANSITION", drv_cmd_set_fast_transition}, - {"FASTREASSOC", drv_cmd_fast_reassoc}, - {"SETROAMSCANCONTROL", drv_cmd_set_roam_scan_control}, - {"SETOKCMODE", drv_cmd_set_okc_mode}, - {"GETROAMSCANCONTROL", drv_cmd_get_roam_scan_control}, - {"BTCOEXMODE", drv_cmd_bt_coex_mode}, - {"SCAN-ACTIVE", drv_cmd_scan_active}, - {"SCAN-PASSIVE", drv_cmd_scan_passive}, - {"GETDWELLTIME", drv_cmd_get_dwell_time}, - {"SETDWELLTIME", drv_cmd_set_dwell_time}, - {"MIRACAST", drv_cmd_miracast}, - {"SETIBSSBEACONOUIDATA", drv_cmd_set_ibss_beacon_oui_data}, - {"SETRMCENABLE", drv_cmd_set_rmc_enable}, - {"SETRMCACTIONPERIOD", drv_cmd_set_rmc_action_period}, - {"GETIBSSPEERINFOALL", drv_cmd_get_ibss_peer_info_all}, - {"GETIBSSPEERINFO", drv_cmd_get_ibss_peer_info}, - {"SETRMCTXRATE", drv_cmd_set_rmc_tx_rate}, - {"SETIBSSTXFAILEVENT", drv_cmd_set_ibss_tx_fail_event}, + {"P2P_DEV_ADDR", drv_cmd_p2p_dev_addr, false}, + {"P2P_SET_NOA", drv_cmd_p2p_set_noa, true}, + {"P2P_SET_PS", drv_cmd_p2p_set_ps, true}, + {"SETBAND", drv_cmd_set_band, true}, + {"SETWMMPS", drv_cmd_set_wmmps, true}, + {"COUNTRY", drv_cmd_country, true}, + {"SETSUSPENDMODE", drv_cmd_dummy, false}, + {"SET_AP_WPS_P2P_IE", drv_cmd_dummy, false}, + {"BTCOEXSCAN", drv_cmd_dummy, false}, + {"RXFILTER", drv_cmd_dummy, false}, + {"SETROAMTRIGGER", drv_cmd_set_roam_trigger, true}, + {"GETROAMTRIGGER", drv_cmd_get_roam_trigger, false}, + {"SETROAMSCANPERIOD", drv_cmd_set_roam_scan_period, true}, + {"GETROAMSCANPERIOD", drv_cmd_get_roam_scan_period, false}, + {"SETROAMSCANREFRESHPERIOD", drv_cmd_set_roam_scan_refresh_period, + true}, + {"GETROAMSCANREFRESHPERIOD", drv_cmd_get_roam_scan_refresh_period, + false}, + {"SETROAMMODE", drv_cmd_set_roam_mode, true}, + {"GETROAMMODE", drv_cmd_get_roam_mode, false}, + {"SETROAMDELTA", drv_cmd_set_roam_delta, true}, + {"GETROAMDELTA", drv_cmd_get_roam_delta, false}, + {"GETBAND", drv_cmd_get_band, false}, + {"SETROAMSCANCHANNELS", drv_cmd_set_roam_scan_channels, true}, + {"GETROAMSCANCHANNELS", drv_cmd_get_roam_scan_channels, false}, + {"GETCCXMODE", drv_cmd_get_ccx_mode, false}, + {"GETOKCMODE", drv_cmd_get_okc_mode, false}, + {"GETFASTROAM", drv_cmd_get_fast_roam, false}, + {"GETFASTTRANSITION", drv_cmd_get_fast_transition, false}, + {"SETROAMSCANCHANNELMINTIME", drv_cmd_set_roam_scan_channel_min_time, + true}, + {"SENDACTIONFRAME", drv_cmd_send_action_frame, true}, + {"GETROAMSCANCHANNELMINTIME", drv_cmd_get_roam_scan_channel_min_time, + false}, + {"SETSCANCHANNELTIME", drv_cmd_set_scan_channel_time, true}, + {"GETSCANCHANNELTIME", drv_cmd_get_scan_channel_time, false}, + {"SETSCANHOMETIME", drv_cmd_set_scan_home_time, true}, + {"GETSCANHOMETIME", drv_cmd_get_scan_home_time, false}, + {"SETROAMINTRABAND", drv_cmd_set_roam_intra_band, true}, + {"GETROAMINTRABAND", drv_cmd_get_roam_intra_band, false}, + {"SETSCANNPROBES", drv_cmd_set_scan_n_probes, true}, + {"GETSCANNPROBES", drv_cmd_get_scan_n_probes, false}, + {"SETSCANHOMEAWAYTIME", drv_cmd_set_scan_home_away_time, true}, + {"GETSCANHOMEAWAYTIME", drv_cmd_get_scan_home_away_time, false}, + {"REASSOC", drv_cmd_reassoc, true}, + {"SETWESMODE", drv_cmd_set_wes_mode, true}, + {"GETWESMODE", drv_cmd_get_wes_mode, false}, + {"SETOPPORTUNISTICRSSIDIFF", drv_cmd_set_opportunistic_rssi_diff, + true}, + {"GETOPPORTUNISTICRSSIDIFF", drv_cmd_get_opportunistic_rssi_diff, + false}, + {"SETROAMRESCANRSSIDIFF", drv_cmd_set_roam_rescan_rssi_diff, true}, + {"GETROAMRESCANRSSIDIFF", drv_cmd_get_roam_rescan_rssi_diff, false}, + {"SETFASTROAM", drv_cmd_set_fast_roam, true}, + {"SETFASTTRANSITION", drv_cmd_set_fast_transition, true}, + {"FASTREASSOC", drv_cmd_fast_reassoc, true}, + {"SETROAMSCANCONTROL", drv_cmd_set_roam_scan_control, true}, + {"SETOKCMODE", drv_cmd_set_okc_mode, true}, + {"GETROAMSCANCONTROL", drv_cmd_get_roam_scan_control, false}, + {"BTCOEXMODE", drv_cmd_bt_coex_mode, true}, + {"SCAN-ACTIVE", drv_cmd_scan_active, false}, + {"SCAN-PASSIVE", drv_cmd_scan_passive, false}, + {"GETDWELLTIME", drv_cmd_get_dwell_time, false}, + {"SETDWELLTIME", drv_cmd_set_dwell_time, true}, + {"MIRACAST", drv_cmd_miracast, true}, + {"SETIBSSBEACONOUIDATA", drv_cmd_set_ibss_beacon_oui_data, true}, + {"SETRMCENABLE", drv_cmd_set_rmc_enable, true}, + {"SETRMCACTIONPERIOD", drv_cmd_set_rmc_action_period, true}, + {"GETIBSSPEERINFOALL", drv_cmd_get_ibss_peer_info_all, false}, + {"GETIBSSPEERINFO", drv_cmd_get_ibss_peer_info, true}, + {"SETRMCTXRATE", drv_cmd_set_rmc_tx_rate, true}, + {"SETIBSSTXFAILEVENT", drv_cmd_set_ibss_tx_fail_event, true}, #ifdef FEATURE_WLAN_ESE - {"SETCCXROAMSCANCHANNELS", drv_cmd_set_ccx_roam_scan_channels}, - {"GETTSMSTATS", drv_cmd_get_tsm_stats}, - {"SETCCKMIE", drv_cmd_set_cckm_ie}, - {"CCXBEACONREQ", drv_cmd_ccx_beacon_req}, - {"CCXPLMREQ", drv_cmd_ccx_plm_req}, - {"SETCCXMODE", drv_cmd_set_ccx_mode}, + {"SETCCXROAMSCANCHANNELS", drv_cmd_set_ccx_roam_scan_channels, true}, + {"GETTSMSTATS", drv_cmd_get_tsm_stats, true}, + {"SETCCKMIE", drv_cmd_set_cckm_ie, true}, + {"CCXBEACONREQ", drv_cmd_ccx_beacon_req, true}, + {"CCXPLMREQ", drv_cmd_ccx_plm_req, true}, + {"SETCCXMODE", drv_cmd_set_ccx_mode, true}, #endif /* FEATURE_WLAN_ESE */ - {"SETMCRATE", drv_cmd_set_mc_rate}, - {"MAXTXPOWER", drv_cmd_max_tx_power}, - {"SETDFSSCANMODE", drv_cmd_set_dfs_scan_mode}, - {"GETDFSSCANMODE", drv_cmd_get_dfs_scan_mode}, - {"GETLINKSTATUS", drv_cmd_get_link_status}, + {"SETMCRATE", drv_cmd_set_mc_rate, true}, + {"MAXTXPOWER", drv_cmd_max_tx_power, true}, + {"SETDFSSCANMODE", drv_cmd_set_dfs_scan_mode, true}, + {"GETDFSSCANMODE", drv_cmd_get_dfs_scan_mode, false}, + {"GETLINKSTATUS", drv_cmd_get_link_status, false}, #ifdef WLAN_FEATURE_EXTWOW_SUPPORT - {"ENABLEEXTWOW", drv_cmd_enable_ext_wow}, - {"SETAPP1PARAMS", drv_cmd_set_app1_params}, - {"SETAPP2PARAMS", drv_cmd_set_app2_params}, + {"ENABLEEXTWOW", drv_cmd_enable_ext_wow, true}, + {"SETAPP1PARAMS", drv_cmd_set_app1_params, true}, + {"SETAPP2PARAMS", drv_cmd_set_app2_params, true}, #endif #ifdef FEATURE_WLAN_TDLS - {"TDLSSECONDARYCHANNELOFFSET", drv_cmd_tdls_secondary_channel_offset}, - {"TDLSOFFCHANNELMODE", drv_cmd_tdls_off_channel_mode}, - {"TDLSOFFCHANNEL", drv_cmd_tdls_off_channel}, - {"TDLSSCAN", drv_cmd_tdls_scan}, + {"TDLSSECONDARYCHANNELOFFSET", drv_cmd_tdls_secondary_channel_offset, + true}, + {"TDLSOFFCHANNELMODE", drv_cmd_tdls_off_channel_mode, true}, + {"TDLSOFFCHANNEL", drv_cmd_tdls_off_channel, true}, + {"TDLSSCAN", drv_cmd_tdls_scan, true}, #endif - {"RSSI", drv_cmd_get_rssi}, - {"LINKSPEED", drv_cmd_get_linkspeed}, - {"RXFILTER-REMOVE", drv_cmd_rx_filter_remove}, - {"RXFILTER-ADD", drv_cmd_rx_filter_add}, - {"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel}, - {"CHANNEL_SWITCH", drv_cmd_set_channel_switch}, - {"SETANTENNAMODE", drv_cmd_set_antenna_mode}, - {"GETANTENNAMODE", drv_cmd_get_antenna_mode}, - {"STOP", drv_cmd_dummy}, + {"RSSI", drv_cmd_get_rssi, false}, + {"LINKSPEED", drv_cmd_get_linkspeed, false}, + {"RXFILTER-REMOVE", drv_cmd_rx_filter_remove, true}, + {"RXFILTER-ADD", drv_cmd_rx_filter_add, true}, + {"SET_FCC_CHANNEL", drv_cmd_set_fcc_channel, true}, + {"CHANNEL_SWITCH", drv_cmd_set_channel_switch, true}, + {"SETANTENNAMODE", drv_cmd_set_antenna_mode, true}, + {"GETANTENNAMODE", drv_cmd_get_antenna_mode, false}, + {"STOP", drv_cmd_dummy, false}, }; /** @@ -6828,6 +6897,7 @@ static int hdd_drv_cmd_process(hdd_adapter_t *adapter, uint8_t *cmd_i = NULL; hdd_drv_cmd_handler_t handler = NULL; int len = 0; + bool args; if (!adapter || !cmd || !priv_data) { hdd_err("at least 1 param is NULL"); @@ -6841,15 +6911,20 @@ static int hdd_drv_cmd_process(hdd_adapter_t *adapter, cmd_i = (uint8_t *)hdd_drv_cmds[i].cmd; handler = hdd_drv_cmds[i].handler; len = strlen(cmd_i); + args = hdd_drv_cmds[i].args; if (!handler) { hdd_err("no. %d handler is NULL", i); return -EINVAL; } - if (strncasecmp(cmd, cmd_i, len) == 0) + if (strncasecmp(cmd, cmd_i, len) == 0) { + if (args && drv_cmd_validate(cmd, len)) + return -EINVAL; + return handler(adapter, hdd_ctx, cmd, len, priv_data); + } } return drv_cmd_invalid(adapter, hdd_ctx, cmd, len, priv_data);