diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index f4dc2bf406..5e9988c23f 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -5244,6 +5244,84 @@ enum dot11p_mode { #define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MAX (100) #define CFG_MAX_SCHED_SCAN_PLAN_ITRNS_DEFAULT (10) +/** + * enum hdd_wext_control - knob for wireless extensions + * @hdd_wext_disabled - interface is completely disabled. An access + * control error log will be generated for each attempted use. + * @hdd_wext_deprecated - interface is available but should not be + * used. An access control warning log will be generated for each + * use. + * @hdd_wext_enabled - interface is available without restriction. No + * access control logs will be generated. + * + * enum hdd_wext_control is used to enable coarse grained control on + * wireless extensions ioctls. This control is used by configuration + * items standard_wext_control and private_wext_control. + * + */ +enum hdd_wext_control { + hdd_wext_disabled = 0, + hdd_wext_deprecated = 1, + hdd_wext_enabled = 2, +}; + +/* + * + * standard_wext_control - Standard wireless extensions control + * @Min: 0 + * @Max: 2 + * @Default: 0 + * + * Values are per enum hdd_wext_control. + * + * This ini is used to control access to standard wireless extensions + * ioctls SIOCSIWCOMMIT (0x8B00) thru SIOCSIWPMKSA (0x8B36). The + * functionality originally provided by these ioctls has been + * completely superceeded by the functionality of cfg80211, and hence + * by default support for these ioctls is disabled. + * + * Related: None + * + * Supported Feature: All + * + * Usage: Internal/External + * + * + */ +#define CFG_STANDARD_WEXT_CONTROL_NAME "standard_wext_control" +#define CFG_STANDARD_WEXT_CONTROL_MIN (hdd_wext_disabled) +#define CFG_STANDARD_WEXT_CONTROL_MAX (hdd_wext_enabled) +#define CFG_STANDARD_WEXT_CONTROL_DEFAULT (hdd_wext_disabled) + +/* + * + * private_wext_control - Private wireless extensions control + * @Min: 0 + * @Max: 2 + * @Default: 1 + * + * Values are per enum hdd_wext_control. + * + * This ini is used to control access to private wireless extensions + * ioctls SIOCIWFIRSTPRIV (0x8BE0) thru SIOCIWLASTPRIV (0x8BFF). The + * functionality provided by some of these ioctls has been superceeded + * by cfg80211 (either standard commands or vendor commands), but many + * of the private ioctls do not have a cfg80211-based equivalent, so + * by default support for these ioctls is deprecated. + * + * Related: None + * + * Supported Feature: All + * + * Usage: Internal/External + * + * + */ +#define CFG_PRIVATE_WEXT_CONTROL_NAME "private_wext_control" +#define CFG_PRIVATE_WEXT_CONTROL_MIN (hdd_wext_disabled) +#define CFG_PRIVATE_WEXT_CONTROL_MAX (hdd_wext_enabled) +#define CFG_PRIVATE_WEXT_CONTROL_DEFAULT (hdd_wext_deprecated) + /* * * gPowerUsage - Preferred Power Usage @@ -6473,6 +6551,8 @@ struct hdd_config { uint16_t wow_pulse_interval_high; uint16_t wow_pulse_interval_low; #endif + enum hdd_wext_control standard_wext_control; + enum hdd_wext_control private_wext_control; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/inc/wlan_hdd_wext.h b/core/hdd/inc/wlan_hdd_wext.h index 7c8ef89af5..de41c5c3d1 100644 --- a/core/hdd/inc/wlan_hdd_wext.h +++ b/core/hdd/inc/wlan_hdd_wext.h @@ -386,4 +386,42 @@ int wlan_hdd_update_phymode(struct net_device *net, tHalHandle hal, int wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, int *temperature); int wlan_hdd_get_link_speed(hdd_adapter_t *sta_adapter, uint32_t *link_speed); + +struct iw_request_info; +/** + * hdd_check_standard_wext_control() - Check to see if standard + * wireless extensions ioctls are allowed + * @hdd_ctx: Global HDD context + * @info: Wireless extensions ioctl information passed by the kernel + * + * This function will examine the "standard_wext_control" configuration + * item to determine whether or not standard wireless extensions ioctls + * are allowed. + * + * Return: 0 if the ioctl is allowed to be processed, -ENOTSUPP if the + * ioctls have been disabled. Note that in addition to returning + * status, this function will log a message if the ioctls are disabled + * or deprecated. + */ +int hdd_check_standard_wext_control(struct hdd_context_s *hdd_ctx, + struct iw_request_info *info); + +/** + * hdd_check_private_wext_control() - Check to see if private + * wireless extensions ioctls are allowed + * @hdd_ctx: Global HDD context + * @info: Wireless extensions ioctl information passed by the kernel + * + * This function will examine the "private_wext_control" configuration + * item to determine whether or not private wireless extensions ioctls + * are allowed. + * + * Return: 0 if the ioctl is allowed to be processed, -ENOTSUPP if the + * ioctls have been disabled. Note that in addition to returning + * status, this function will log a message if the ioctls are disabled + * or deprecated. + */ +int hdd_check_private_wext_control(struct hdd_context_s *hdd_ctx, + struct iw_request_info *info); + #endif /* __WEXT_IW_H__ */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 5062d0d06f..0f17639850 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -5514,6 +5514,10 @@ static int __iw_set_essid(struct net_device *dev, if (ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (pAdapter->device_mode != QDF_STA_MODE && pAdapter->device_mode != QDF_IBSS_MODE && pAdapter->device_mode != QDF_P2P_CLIENT_MODE) { @@ -5747,6 +5751,10 @@ static int __iw_get_essid(struct net_device *dev, if (ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if ((pHddStaCtx->conn_info.connState == eConnectionState_Associated && wextBuf->roamProfile.SSIDs.SSIDList->SSID.length > 0) || ((pHddStaCtx->conn_info.connState == eConnectionState_IbssConnected @@ -5817,6 +5825,10 @@ static int __iw_set_auth(struct net_device *dev, struct iw_request_info *info, if (ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (wrqu->param.flags & IW_AUTH_INDEX) { case IW_AUTH_WPA_VERSION: pWextState->wpaVersion = wrqu->param.value; @@ -6050,6 +6062,10 @@ static int __iw_get_auth(struct net_device *dev, struct iw_request_info *info, if (ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (pRoamProfile->negotiatedAuthType) { case eCSR_AUTH_TYPE_WPA_NONE: wrqu->param.flags = IW_AUTH_WPA_VERSION; @@ -6209,6 +6225,10 @@ static int __iw_set_ap_address(struct net_device *dev, if (ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pMacAddress = (uint8_t *) wrqu->ap_addr.sa_data; hdd_info(" " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pMacAddress)); qdf_mem_copy(pHddStaCtx->conn_info.bssId.bytes, pMacAddress, @@ -6267,6 +6287,10 @@ static int __iw_get_ap_address(struct net_device *dev, if (ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (pHddStaCtx->conn_info.connState == eConnectionState_Associated || eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState) { qdf_mem_copy(wrqu->ap_addr.sa_data, diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index f03abb94b2..4e6774e5b6 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -4134,6 +4134,18 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_MAX_SCHED_SCAN_PLAN_ITRNS_DEFAULT, CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MIN, CFG_MAX_SCHED_SCAN_PLAN_ITRNS_MAX), + REG_VARIABLE(CFG_STANDARD_WEXT_CONTROL_NAME, WLAN_PARAM_Integer, + struct hdd_config, standard_wext_control, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_STANDARD_WEXT_CONTROL_DEFAULT, + CFG_STANDARD_WEXT_CONTROL_MIN, + CFG_STANDARD_WEXT_CONTROL_MAX), + REG_VARIABLE(CFG_PRIVATE_WEXT_CONTROL_NAME, WLAN_PARAM_Integer, + struct hdd_config, private_wext_control, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_PRIVATE_WEXT_CONTROL_DEFAULT, + CFG_PRIVATE_WEXT_CONTROL_MIN, + CFG_PRIVATE_WEXT_CONTROL_MAX), }; /** diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 5fd3dead44..0a0ac19881 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -2365,22 +2365,26 @@ static __iw_softap_set_ini_cfg(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - QDF_STATUS vstatus; - int ret = 0; /* success */ - hdd_adapter_t *pAdapter = (netdev_priv(dev)); - hdd_context_t *pHddCtx; + QDF_STATUS status; + int ret; + hdd_adapter_t *adapter = (netdev_priv(dev)); + hdd_context_t *hdd_ctx; ENTER_DEV(dev); - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ret = wlan_hdd_validate_context(pHddCtx); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); if (ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_notice("Received data %s", extra); - vstatus = hdd_execute_global_config_command(pHddCtx, extra); - if (QDF_STATUS_SUCCESS != vstatus) { + status = hdd_execute_global_config_command(hdd_ctx, extra); + if (QDF_STATUS_SUCCESS != status) { ret = -EINVAL; } @@ -2427,19 +2431,23 @@ static __iw_softap_get_ini_cfg(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - hdd_context_t *pHddCtx; - int ret = 0; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int ret; ENTER_DEV(dev); - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ret = wlan_hdd_validate_context(pHddCtx); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); if (ret != 0) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_notice("Printing CLD global INI Config"); - hdd_cfg_get_global_config(pHddCtx, extra, QCSAP_IOCTL_MAX_STR_LEN); + hdd_cfg_get_global_config(hdd_ctx, extra, QCSAP_IOCTL_MAX_STR_LEN); wrqu->data.length = strlen(extra) + 1; return 0; @@ -2483,7 +2491,11 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, hdd_ctx = WLAN_HDD_GET_CTX(adapter); ret = wlan_hdd_validate_context(hdd_ctx); if (ret != 0) - goto out; + return ret; + + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; switch (sub_cmd) { #ifdef WLAN_DEBUG @@ -2530,7 +2542,6 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev, break; } -out: return ret; } @@ -2635,6 +2646,10 @@ static __iw_softap_setparam(struct net_device *dev, if (0 != ret) return -EINVAL; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); if (!hHal) { hdd_err("Hal ctx is null"); @@ -3269,6 +3284,10 @@ static int __iw_softap_get_three(struct net_device *dev, if (ret != 0) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (sub_cmd) { case QCSAP_GET_TSF: ret = hdd_indicate_tsf(adapter, value, 3); @@ -3341,6 +3360,10 @@ static __iw_softap_getparam(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (sub_cmd) { case QCSAP_PARAM_MAX_ASSOC: status = @@ -3598,6 +3621,10 @@ int __iw_softap_modify_acl(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) pPeerStaMac[i] = *(value + i); @@ -3650,6 +3677,10 @@ static __iw_softap_getchannel(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + *value = 0; if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) *value = (WLAN_HDD_GET_AP_CTX_PTR( @@ -3696,7 +3727,11 @@ static __iw_softap_set_max_tx_power(struct net_device *dev, if (0 != ret) return ret; - /* Assign correct slef MAC address */ + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + + /* Assign correct self MAC address */ qdf_copy_macaddr(&bssid, &pHostapdAdapter->macAddressCurrent); qdf_copy_macaddr(&selfMac, &pHostapdAdapter->macAddressCurrent); @@ -3729,21 +3764,23 @@ static __iw_softap_set_pktlog(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - hdd_adapter_t *pHostapdAdapter = netdev_priv(dev); + hdd_adapter_t *adapter = netdev_priv(dev); hdd_context_t *hdd_ctx; int *value = (int *)extra; + int ret; ENTER_DEV(dev); - if (NULL == value) - return -ENOMEM; + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; if (wrqu->data.length < 1 || wrqu->data.length > 2) { hdd_err("pktlog: either 1 or 2 parameters are required"); return -EINVAL; } - hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); return hdd_process_pktlog_command(hdd_ctx, value[0], value[1]); } @@ -3782,8 +3819,9 @@ static __iw_softap_set_tx_power(struct net_device *dev, if (0 != ret) return ret; - if (NULL == value) - return -ENOMEM; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; qdf_copy_macaddr(&bssid, &pHostapdAdapter->macAddressCurrent); @@ -3851,6 +3889,10 @@ static __iw_softap_getassoc_stamacaddr(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* make sure userspace allocated a reasonable buffer size */ if (wrqu->data.length < sizeof(maclist_index)) { hdd_notice("invalid userspace buffer"); @@ -3942,6 +3984,10 @@ static __iw_softap_disassoc_sta(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* iwpriv tool or framework calls this ioctl with * data passed in extra (less than 16 octets); */ @@ -3997,6 +4043,10 @@ static int __iw_get_char_setnone(struct net_device *dev, if (ret != 0) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (sub_cmd) { case QCSAP_GET_STATS: hdd_wlan_get_stats(adapter, &(wrqu->data.length), @@ -4031,6 +4081,7 @@ static int wlan_hdd_set_force_acs_ch_range(struct net_device *dev, { hdd_adapter_t *adapter = (netdev_priv(dev)); hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int ret; int *value = (int *)extra; ENTER_DEV(dev); @@ -4040,6 +4091,14 @@ static int wlan_hdd_set_force_acs_ch_range(struct net_device *dev, return -EPERM; } + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (wlan_hdd_validate_operation_channel(adapter, value[0]) != QDF_STATUS_SUCCESS || wlan_hdd_validate_operation_channel(adapter, value[1]) != @@ -4087,6 +4146,10 @@ static int __iw_get_channel_list(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (QDF_STATUS_SUCCESS != sme_get_freq_band(hal, &cur_band)) { hdd_err("not able get the current frequency band"); return -EIO; @@ -4169,6 +4232,10 @@ int __iw_get_genie(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* * Actually retrieve the RSN IE from CSR. * (We previously sent it down in the CSR Roam Profile.) @@ -4226,6 +4293,10 @@ int __iw_get_wpspbc_probe_req_ies(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_notice("get_WPSPBCProbeReqIEs ioctl"); memset((void *)&WPSPBCProbeReqIEs, 0, sizeof(WPSPBCProbeReqIEs)); @@ -4291,6 +4362,10 @@ int __iw_set_auth_hostap(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (wrqu->param.flags & IW_AUTH_INDEX) { case IW_AUTH_TKIP_COUNTERMEASURES: { @@ -4380,6 +4455,10 @@ static int __iw_set_ap_encodeext(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + key_index = encoding->flags & IW_ENCODE_INDEX; if (key_index > 0) { @@ -4582,6 +4661,10 @@ static int __iw_get_ap_freq(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); @@ -4665,6 +4748,10 @@ static int __iw_get_mode(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + wrqu->mode = IW_MODE_MASTER; return ret; @@ -4709,6 +4796,10 @@ __iw_softap_stopbss(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pHostapdAdapter); @@ -4766,6 +4857,10 @@ __iw_softap_version(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_wlan_get_version(hdd_ctx, wrqu, extra); EXIT(); return 0; @@ -4851,6 +4946,10 @@ static int __iw_softap_get_sta_info(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + status = hdd_softap_get_sta_info(pHostapdAdapter, extra, WE_SAP_MAX_STA_INFO); @@ -4905,6 +5004,10 @@ static int __iw_set_ap_genie(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (!wrqu->data.length) { EXIT(); return 0; @@ -4976,14 +5079,18 @@ int __iw_get_softap_linkspeed(struct net_device *dev, struct qdf_mac_addr macAddress; char pmacAddress[MAC_ADDRESS_STR_LEN + 1]; QDF_STATUS status = QDF_STATUS_E_FAILURE; - int rc, valid, i; + int rc, ret, i; ENTER_DEV(dev); hdd_ctx = WLAN_HDD_GET_CTX(pHostapdAdapter); - valid = wlan_hdd_validate_context(hdd_ctx); - if (0 != valid) - return valid; + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; hdd_notice("wrqu->data.length(%d)", wrqu->data.length); diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index 6019b072f4..a6f0bd5d27 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -481,8 +481,9 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { - int rc = 0; + int rc; struct dot11p_channel_sched *sched; + hdd_context_t *hdd_ctx; hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct sir_ocb_config *config = NULL; uint8_t *mac_addr; @@ -491,8 +492,14 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, ENTER_DEV(dev); - if (wlan_hdd_validate_context(WLAN_HDD_GET_CTX(adapter))) - return -EINVAL; + hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); + rc = wlan_hdd_validate_context(hdd_ctx); + if (0 != rc) + return rc; + + rc = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != rc) + return rc; if (adapter->device_mode != QDF_OCB_MODE) { hdd_err("Device not in OCB mode!"); diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index a0aea11718..1f0b767d78 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -757,6 +757,10 @@ static int __iw_set_scan(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* Block All Scan during DFS operation and send null scan result */ con_sap_adapter = hdd_get_con_sap_adapter(pAdapter, true); if (con_sap_adapter) { @@ -939,6 +943,10 @@ static int __iw_get_scan(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_notice("enter buffer length %d!!!", (wrqu->data.length) ? wrqu->data.length : IW_SCAN_MAX_DATA); diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index 73976cef42..e628640f4f 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -1128,6 +1128,35 @@ int hdd_priv_get_data(struct iw_point *p_priv_data, union iwreq_data *wrqu) return 0; } +static int hdd_check_wext_control(enum hdd_wext_control wext_control, + struct iw_request_info *info) +{ + switch (wext_control) { + default: + case hdd_wext_disabled: + hdd_err("Rejecting disabled ioctl %x", info->cmd); + return -ENOTSUPP; + case hdd_wext_deprecated: + hdd_warn("Using deprecated ioctl %x", info->cmd); + return 0; + case hdd_wext_enabled: + return 0; + } +} + +int hdd_check_standard_wext_control(struct hdd_context_s *hdd_ctx, + struct iw_request_info *info) +{ + return hdd_check_wext_control(hdd_ctx->config->standard_wext_control, + info); +} + +int hdd_check_private_wext_control(struct hdd_context_s *hdd_ctx, + struct iw_request_info *info) +{ + return hdd_check_wext_control(hdd_ctx->config->private_wext_control, + info); +} /** * hdd_wlan_get_stats() - Get txrx stats in SAP mode @@ -2456,6 +2485,10 @@ static int __iw_set_commit(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* Do nothing for now */ return 0; } @@ -2505,6 +2538,10 @@ static int __iw_get_name(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + strlcpy(wrqu, "Qcom:802.11n", IFNAMSIZ); EXIT(); return 0; @@ -2561,6 +2598,10 @@ static int __iw_set_mode(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); wdev = dev->ieee80211_ptr; pRoamProfile = &pWextState->roamProfile; @@ -2669,6 +2710,10 @@ __iw_get_mode(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); switch (pWextState->roamProfile.BSSType) { @@ -2743,6 +2788,10 @@ static int __iw_set_freq(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); pRoamProfile = &pWextState->roamProfile; @@ -2867,6 +2916,10 @@ static int __iw_get_freq(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); @@ -2948,6 +3001,10 @@ static int __iw_get_tx_power(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { wrqu->txpower.value = 0; return 0; @@ -3005,6 +3062,10 @@ static int __iw_set_tx_power(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (sme_cfg_set_int(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, wrqu->txpower.value) != QDF_STATUS_SUCCESS) { hdd_err("failed to set ini parameter, WNI_CFG_CURRENT_TX_POWER_LEVEL"); @@ -3065,6 +3126,10 @@ static int __iw_get_bitrate(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { wrqu->bitrate.value = 0; } else { @@ -3160,6 +3225,10 @@ static int __iw_set_bitrate(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { @@ -3260,6 +3329,10 @@ static int __iw_set_genie(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (!wrqu->data.length) { hdd_clear_roam_profile_ie(pAdapter); EXIT(); @@ -3431,6 +3504,10 @@ static int __iw_get_genie(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_notice("getGEN_IE ioctl"); pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); @@ -3522,6 +3599,10 @@ static int __iw_get_encode(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + keyId = pRoamProfile->Keys.defaultIndex; if (keyId < 0 || keyId >= MAX_WEP_KEYS) { @@ -3613,6 +3694,10 @@ static int __iw_get_rts_threshold(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (QDF_STATUS_SUCCESS != sme_cfg_get_int(hal, WNI_CFG_RTS_THRESHOLD, &threshold)) { hdd_warn("failed to get ini parameter, WNI_CFG_RTS_THRESHOLD"); @@ -3652,6 +3737,10 @@ static int __iw_set_rts_threshold(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (wrqu->rts.value < WNI_CFG_RTS_THRESHOLD_STAMIN || wrqu->rts.value > WNI_CFG_RTS_THRESHOLD_STAMAX) { return -EINVAL; @@ -3738,6 +3827,10 @@ static int __iw_get_frag_threshold(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (sme_cfg_get_int(hal, WNI_CFG_FRAGMENTATION_THRESHOLD, &threshold) != QDF_STATUS_SUCCESS) { hdd_warn("failed to get ini parameter, WNI_CFG_FRAGMENTATION_THRESHOLD"); @@ -3799,6 +3892,10 @@ static int __iw_set_frag_threshold(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (wrqu->frag.value < WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN || wrqu->frag.value > WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX) { return -EINVAL; @@ -3863,6 +3960,10 @@ static int __iw_get_power_mode(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + return -EOPNOTSUPP; } @@ -3913,6 +4014,10 @@ static int __iw_set_power_mode(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + return -EOPNOTSUPP; } @@ -3972,6 +4077,10 @@ static int __iw_get_range(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + wrqu->data.length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); @@ -4384,18 +4493,23 @@ static int __iw_get_linkspeed(struct net_device *dev, int len = sizeof(uint32_t) + 1; uint32_t link_speed = 0; hdd_context_t *hdd_ctx; - int rc, valid; + int ret; + int rc; ENTER_DEV(dev); hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); - valid = wlan_hdd_validate_context(hdd_ctx); - if (0 != valid) - return valid; + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; - rc = wlan_hdd_get_link_speed(pAdapter, &link_speed); - if (0 != rc) { - return rc; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + + ret = wlan_hdd_get_link_speed(pAdapter, &link_speed); + if (0 != ret) { + return ret; } wrqu->data.length = len; @@ -4476,6 +4590,10 @@ static int __iw_set_nick(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + return 0; } @@ -4526,6 +4644,10 @@ static int __iw_get_nick(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + return 0; } @@ -4582,6 +4704,10 @@ static int __iw_set_encode(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + keyId = encoderq->flags & IW_ENCODE_INDEX; if (keyId) { @@ -4762,6 +4888,10 @@ static int __iw_get_encodeext(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + keyId = pRoamProfile->Keys.defaultIndex; if (keyId < 0 || keyId >= MAX_WEP_KEYS) { @@ -4865,6 +4995,10 @@ static int __iw_set_encodeext(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + key_index = encoding->flags & IW_ENCODE_INDEX; if (key_index > 0) { @@ -5070,6 +5204,10 @@ static int __iw_set_retry(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (wrqu->retry.value < WNI_CFG_LONG_RETRY_LIMIT_STAMIN || wrqu->retry.value > WNI_CFG_LONG_RETRY_LIMIT_STAMAX) { @@ -5153,6 +5291,10 @@ static int __iw_get_retry(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if ((wrqu->retry.flags & IW_RETRY_LONG)) { wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG; @@ -5232,6 +5374,10 @@ static int __iw_set_mlme(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_standard_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* reason_code is unused. By default it is set to * eCSR_DISCONNECT_REASON_UNSPECIFIED */ @@ -5716,14 +5862,18 @@ static int __iw_setint_getnone(struct net_device *dev, ENTER_DEV(dev); - INIT_COMPLETION(pWextState->completion_var); - memset(&smeConfig, 0x00, sizeof(smeConfig)); - hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); ret = wlan_hdd_validate_context(hdd_ctx); if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + + INIT_COMPLETION(pWextState->completion_var); + memset(&smeConfig, 0x00, sizeof(smeConfig)); + switch (sub_cmd) { case WE_SET_11D_STATE: { @@ -6843,6 +6993,10 @@ static int __iw_setnone_get_threeint(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_info("param = %d", value[0]); switch (value[0]) { case WE_GET_TSF: @@ -6911,6 +7065,10 @@ static int __iw_setchar_getnone(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* helper function to get iwreq_data with compat handling. */ if (hdd_priv_get_data(&s_priv_data, wrqu)) { return -EINVAL; @@ -7039,6 +7197,10 @@ static int __iw_setnone_getint(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (value[0]) { case WE_GET_11D_STATE: { @@ -7584,6 +7746,10 @@ static int __iw_set_three_ints_getnone(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (sub_cmd) { case WE_SET_WLAN_DBG: @@ -7701,6 +7867,10 @@ static int __iw_get_char_setnone(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (sub_cmd) { case WE_WLAN_VERSION: { @@ -8246,6 +8416,10 @@ static int __iw_setnone_getnone(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + #ifdef CONFIG_COMPAT /* this ioctl is a special case where a sub-ioctl is used and both * the number of get and set args is 0. in this specific case the @@ -8553,10 +8727,9 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, if (0 != ret) return ret; - if (extra == NULL) { - hdd_err("NULL extra buffer pointer"); - return -EINVAL; - } + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; sub_cmd = wrqu->data.flags; num_args = wrqu->data.length; @@ -8907,6 +9080,10 @@ static int __iw_add_tspec(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* make sure the application is sufficiently priviledged */ /* note that the kernel will do this for "set" ioctls, but since */ /* this ioctl wants to return status to user space it must be */ @@ -9078,6 +9255,10 @@ static int __iw_del_tspec(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* make sure the application is sufficiently priviledged */ /* note that the kernel will do this for "set" ioctls, but since */ /* this ioctl wants to return status to user space it must be */ @@ -9142,6 +9323,10 @@ static int __iw_get_tspec(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + /* although we are defined to be a "get" ioctl, the params we require */ /* will fit in the iwreq_data, therefore unlike iw_add_tspec() there */ /* is no need to copy the params from user space */ @@ -9200,6 +9385,10 @@ static int __iw_set_fties(struct net_device *dev, struct iw_request_info *info, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (!wrqu->data.length) { hdd_err("called with 0 length IEs"); return -EINVAL; @@ -9291,6 +9480,10 @@ static int __iw_set_host_offload(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { hdd_err("dev is not in CONNECTED state, ignore!!!"); return -EINVAL; @@ -9398,6 +9591,10 @@ static int __iw_set_keepalive_params(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (wrqu->data.length != sizeof(*request)) { hdd_err("Invalid length %d", wrqu->data.length); return -EINVAL; @@ -9631,6 +9828,10 @@ static int __iw_set_packet_filter_params(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (hdd_priv_get_data(&priv_data, wrqu)) { hdd_err("failed to get priv data"); return -EINVAL; @@ -9704,6 +9905,10 @@ static int __iw_get_statistics(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + if (eConnectionState_Associated != (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) { @@ -9948,6 +10153,10 @@ static int __iw_set_pno(struct net_device *dev, if (ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + hdd_notice("PNO data len %d data %s", wrqu->data.length, extra); request.enable = 0; @@ -10287,6 +10496,9 @@ static int __iw_set_band_config(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx; + int ret; int *value = (int *)extra; ENTER_DEV(dev); @@ -10296,6 +10508,11 @@ static int __iw_set_band_config(struct net_device *dev, return -EPERM; } + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + return hdd_set_band(dev, value[0]); } @@ -10376,6 +10593,10 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, if (0 != ret) return ret; + ret = hdd_check_private_wext_control(hdd_ctx, info); + if (0 != ret) + return ret; + switch (sub_cmd) { case WE_SET_SMPS_PARAM: hdd_notice("WE_SET_SMPS_PARAM val %d %d", value[1], value[2]);