wlan: Use variable length for Ext Cap IE

Ext Cap IE is defined as fixed length in driver. But some
AP sends beacon or probe resp with variable length of
Ext Cap IE, then dot11f will decode it to invalid value.

To fix this, use variable length for Ext Cap IE.

Change-Id: I910edfddf3ea64bc3000b6e7803dc57a50399dbb
CRs-Fixed: 1052140
This commit is contained in:
Hu Wang
2020-05-21 10:54:44 +02:00
committed by Francescodario Cuzzocrea
parent d4c2d6a92d
commit 0409e22658
10 changed files with 1054 additions and 2252 deletions
@@ -2673,63 +2673,7 @@ IE WiderBWChanSwitchAnn (EID_WIDER_BW_CHANNEL_SWITCH_ANN)
IE ExtCap (EID_EXT_CAP)
{
{
bssCoexistMgmtSupport: 1;
reserved1: 1;
extChanSwitch: 1;
reserved2: 1;
psmpCap: 1;
reserved3: 1;
spsmpCap: 1;
event: 1;
diagnostics: 1;
multiDiagnostics: 1;
locTracking: 1;
FMS: 1;
proxyARPService: 1;
coLocIntfReporting: 1;
civicLoc: 1;
geospatialLoc: 1;
TFS: 1;
wnmSleepMode: 1;
timBroadcast: 1;
bssTransition: 1;
qosTrafficCap: 1;
acStaCnt: 1;
multiBSSID: 1;
timingMeas: 1;
chanUsage: 1;
ssidList: 1;
DMS: 1;
UTCTSFOffset: 1;
TDLSPeerUAPSDBufferSTA: 1;
TDLSPeerPSMSupp: 1;
TDLSChannelSwitching: 1;
interworkingService: 1;
}
{
qosMap: 1;
EBR: 1;
sspnInterface: 1;
reserved4: 1;
msgCFCap: 1;
TDLSSupport: 1;
TDLSProhibited: 1;
TDLSChanSwitProhibited: 1;
rejectUnadmittedTraffic: 1;
serviceIntervalGranularity: 3;
identifierLoc: 1;
uapsdCoexistence: 1;
wnmNotification: 1;
reserved5: 1;
}
{
UTF8SSID: 1;
reserved6: 12;
TDLSWiderBW: 1;
operModeNotification: 1;
reserved7: 1;
}
bytes[1..9];
}
IE HTCaps (EID_HT_CAPABILITIES)
@@ -3510,65 +3510,16 @@ tANI_U32 dot11fGetPackedIEESEVersion(tpAniSirGlobal, tDot11fIEESEVersion*, tANI_
// EID 127 (0x7f)
typedef struct sDot11fIEExtCap {
tANI_U8 present;
tANI_U32 bssCoexistMgmtSupport: 1;
tANI_U32 reserved1: 1;
tANI_U32 extChanSwitch: 1;
tANI_U32 reserved2: 1;
tANI_U32 psmpCap: 1;
tANI_U32 reserved3: 1;
tANI_U32 spsmpCap: 1;
tANI_U32 event: 1;
tANI_U32 diagnostics: 1;
tANI_U32 multiDiagnostics: 1;
tANI_U32 locTracking: 1;
tANI_U32 FMS: 1;
tANI_U32 proxyARPService: 1;
tANI_U32 coLocIntfReporting: 1;
tANI_U32 civicLoc: 1;
tANI_U32 geospatialLoc: 1;
tANI_U32 TFS: 1;
tANI_U32 wnmSleepMode: 1;
tANI_U32 timBroadcast: 1;
tANI_U32 bssTransition: 1;
tANI_U32 qosTrafficCap: 1;
tANI_U32 acStaCnt: 1;
tANI_U32 multiBSSID: 1;
tANI_U32 timingMeas: 1;
tANI_U32 chanUsage: 1;
tANI_U32 ssidList: 1;
tANI_U32 DMS: 1;
tANI_U32 UTCTSFOffset: 1;
tANI_U32 TDLSPeerUAPSDBufferSTA: 1;
tANI_U32 TDLSPeerPSMSupp: 1;
tANI_U32 TDLSChannelSwitching: 1;
tANI_U32 interworkingService: 1;
tANI_U16 qosMap: 1;
tANI_U16 EBR: 1;
tANI_U16 sspnInterface: 1;
tANI_U16 reserved4: 1;
tANI_U16 msgCFCap: 1;
tANI_U16 TDLSSupport: 1;
tANI_U16 TDLSProhibited: 1;
tANI_U16 TDLSChanSwitProhibited: 1;
tANI_U16 rejectUnadmittedTraffic: 1;
tANI_U16 serviceIntervalGranularity: 3;
tANI_U16 identifierLoc: 1;
tANI_U16 uapsdCoexistence: 1;
tANI_U16 wnmNotification: 1;
tANI_U16 reserved5: 1;
tANI_U16 UTF8SSID: 1;
tANI_U16 reserved6: 12;
tANI_U16 TDLSWiderBW: 1;
tANI_U16 operModeNotification: 1;
tANI_U16 reserved7: 1;
tANI_U8 num_bytes;
tANI_U8 bytes[9];
} tDot11fIEExtCap;
#define DOT11F_EID_EXTCAP ( 127 )
// N.B. These #defines do *not* include the EID & length
#define DOT11F_IE_EXTCAP_MIN_LEN ( 8 )
#define DOT11F_IE_EXTCAP_MIN_LEN ( 1 )
#define DOT11F_IE_EXTCAP_MAX_LEN ( 8 )
#define DOT11F_IE_EXTCAP_MAX_LEN ( 9 )
#ifdef __cplusplus
extern "C" {
@@ -5309,7 +5260,7 @@ typedef struct sDot11fIESuppRates {
((_x) == 48) || \
((_x) == 72) || \
((_x) == 96) || \
((_x) == 108))
((_x) == 108))
#ifdef __cplusplus
extern "C" {
@@ -5796,7 +5747,7 @@ tANI_U32 dot11fGetPackedIEWMMParams(tpAniSirGlobal, tDot11fIEWMMParams*, tANI_U3
typedef struct sDot11fIEWPA {
tANI_U8 present;
tANI_U16 version /* Must be 1! */;
tANI_U8 multicast_cipher_present; //field added to fix the bug in dot11fPackIEWPA
tANI_U8 multicast_cipher_present; //field added to fix the bug in dot11fPackIEWPA
tANI_U8 multicast_cipher[4];
tANI_U16 unicast_cipher_count;
tANI_U8 unicast_ciphers[4][4];
@@ -298,6 +298,79 @@ typedef struct sSirEseBcnReportMandatoryIe
} tSirEseBcnReportMandatoryIe, *tpSirEseBcnReportMandatoryIe;
#endif /* FEATURE_WLAN_ESE_UPLOAD */
struct s_ext_cap {
uint8_t bssCoexistMgmtSupport: 1;
uint8_t reserved1: 1;
uint8_t extChanSwitch: 1;
uint8_t reserved2: 1;
uint8_t psmpCap: 1;
uint8_t reserved3: 1;
uint8_t spsmpCap: 1;
uint8_t event: 1;
uint8_t diagnostics: 1;
uint8_t multiDiagnostics: 1;
uint8_t locTracking: 1;
uint8_t FMS: 1;
uint8_t proxyARPService: 1;
uint8_t coLocIntfReporting: 1;
uint8_t civicLoc: 1;
uint8_t geospatialLoc: 1;
uint8_t TFS: 1;
uint8_t wnmSleepMode: 1;
uint8_t timBroadcast: 1;
uint8_t bssTransition: 1;
uint8_t qosTrafficCap: 1;
uint8_t acStaCnt: 1;
uint8_t multiBSSID: 1;
uint8_t timingMeas: 1;
uint8_t chanUsage: 1;
uint8_t ssidList: 1;
uint8_t DMS: 1;
uint8_t UTCTSFOffset: 1;
uint8_t TDLSPeerUAPSDBufferSTA: 1;
uint8_t TDLSPeerPSMSupp: 1;
uint8_t TDLSChannelSwitching: 1;
uint8_t interworkingService: 1;
uint8_t qosMap: 1;
uint8_t EBR: 1;
uint8_t sspnInterface: 1;
uint8_t reserved4: 1;
uint8_t msgCFCap: 1;
uint8_t TDLSSupport: 1;
uint8_t TDLSProhibited: 1;
uint8_t TDLSChanSwitProhibited: 1;
uint8_t rejectUnadmittedTraffic: 1;
uint8_t serviceIntervalGranularity: 3;
uint8_t identifierLoc: 1;
uint8_t uapsdCoexistence: 1;
uint8_t wnmNotification: 1;
uint8_t QABcapbility: 1;
uint8_t UTF8SSID: 1;
uint8_t QMFActivated: 1;
uint8_t QMFreconAct: 1;
uint8_t RobustAVStreaming: 1;
uint8_t AdvancedGCR: 1;
uint8_t MeshGCR: 1;
uint8_t SCS: 1;
uint8_t QLoadReport: 1;
uint8_t AlternateEDCA: 1;
uint8_t UnprotTXOPneg: 1;
uint8_t ProtTXOPneg: 1;
uint8_t reserved6: 1;
uint8_t ProtQLoadReport: 1;
uint8_t TDLSWiderBW: 1;
uint8_t operModeNotification: 1;
uint8_t maxNumOfMSDU_bit1: 1;
uint8_t maxNumOfMSDU_bit2: 1;
uint8_t ChanSchMgmt: 1;
uint8_t GeoDBInbandEnSignal: 1;
uint8_t NwChanControl: 1;
uint8_t WhiteSpaceMap: 1;
uint8_t ChanAvailQuery: 1;
uint8_t fineTimingMeas: 1;
uint8_t reserved7: 1;
};
tANI_U8
sirIsPropCapabilityEnabled(struct sAniSirGlobal *pMac, tANI_U32 bitnum);
@@ -469,9 +469,12 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub
}
if(pAssocRsp->ExtCap.present)
{
limLog(pMac, LOGE, FL("Filling tdls prohibited in session entry"));
struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)
pAssocRsp->ExtCap.bytes;
limLog(pMac, LOG1,
FL("Filling tdls prohibited in session entry"));
psessionEntry->tdlsChanSwitProhibited =
pAssocRsp->ExtCap.TDLSChanSwitProhibited ;
p_ext_cap->TDLSChanSwitProhibited;
}
if(!pAssocRsp->suppRatesPresent)
{
@@ -2914,13 +2914,18 @@ void PopulateDot11fLinkIden(tpAniSirGlobal pMac, tpPESession psessionEntry,
void PopulateDot11fTdlsExtCapability(tpAniSirGlobal pMac,
tDot11fIEExtCap *extCapability)
{
extCapability->TDLSPeerPSMSupp = PEER_PSM_SUPPORT ;
extCapability->TDLSPeerUAPSDBufferSTA = pMac->lim.gLimTDLSBufStaEnabled;
extCapability->TDLSChannelSwitching = pMac->lim.gLimTDLSOffChannelEnabled ;
extCapability->TDLSSupport = TDLS_SUPPORT ;
extCapability->TDLSProhibited = TDLS_PROHIBITED ;
extCapability->TDLSChanSwitProhibited = TDLS_CH_SWITCH_PROHIBITED ;
extCapability->present = 1 ;
struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extCapability->bytes;
p_ext_cap->TDLSPeerPSMSupp = PEER_PSM_SUPPORT ;
p_ext_cap->TDLSPeerUAPSDBufferSTA = pMac->lim.gLimTDLSBufStaEnabled;
p_ext_cap->TDLSChannelSwitching = pMac->lim.gLimTDLSOffChannelEnabled ;
p_ext_cap->TDLSSupport = TDLS_SUPPORT ;
p_ext_cap->TDLSProhibited = TDLS_PROHIBITED ;
p_ext_cap->TDLSChanSwitProhibited = TDLS_CH_SWITCH_PROHIBITED ;
extCapability->present = 1;
extCapability->num_bytes = lim_compute_ext_cap_ie_length(extCapability);
return ;
}
@@ -109,7 +109,7 @@ tSirRetStatus limStripOffExtCapIE(tpAniSirGlobal pMac,
tempLen += (elem_len + 2);
}
else
{ /*Est Cap present size is 8 + 2 byte at present*/
{
if ( NULL != pExtractedExtCapIEBuf )
{
vos_mem_set(pExtractedExtCapIEBuf,
@@ -135,6 +135,7 @@ void limUpdateExtCapIEtoStruct(tpAniSirGlobal pMac,
tDot11fIEExtCap *pDst)
{
tANI_U8 pOut[DOT11F_IE_EXTCAP_MAX_LEN];
tANI_U8 tag, len, *val;
if ( NULL == pBuf )
{
@@ -149,22 +150,23 @@ void limUpdateExtCapIEtoStruct(tpAniSirGlobal pMac,
return ;
}
if ( DOT11F_EID_EXTCAP != pBuf[0] ||
pBuf[1] > DOT11F_IE_EXTCAP_MAX_LEN )
/* Get tlv */
tag = pBuf[0];
len = pBuf[1];
val = &pBuf[2];
if ( DOT11F_EID_EXTCAP != tag ||
len > DOT11F_IE_EXTCAP_MAX_LEN )
{
limLog( pMac, LOG1,
FL("Invalid IEs eid = %d elem_len=%d "),
pBuf[0],pBuf[1]);
FL("Invalid IEs eid = %d elem_len=%d "), tag, len);
return;
}
vos_mem_set(( tANI_U8* )&pOut[0], DOT11F_IE_EXTCAP_MAX_LEN, 0);
/* conversion should follow 4, 2, 2 byte order */
limUtilsframeshtonl(pMac, &pOut[0],*((tANI_U32*)&pBuf[2]),0);
limUtilsframeshtons(pMac, &pOut[4],*((tANI_U16*)&pBuf[6]),0);
limUtilsframeshtons(pMac, &pOut[6],*((tANI_U16*)&pBuf[8]),0);
vos_mem_zero(pOut, DOT11F_IE_EXTCAP_MAX_LEN);
vos_mem_copy(pOut, val, len);
if ( DOT11F_PARSE_SUCCESS != dot11fUnpackIeExtCap( pMac,
&pOut[0], DOT11F_IE_EXTCAP_MAX_LEN, pDst) )
pOut, len, pDst) )
{
limLog( pMac, LOGE,
FL("dot11fUnpackIeExtCap Parse Error "));
@@ -208,6 +210,7 @@ void limMergeExtCapIEStruct(tDot11fIEExtCap *pDst,
tempDst++;
tempSrc++;
}
pDst->num_bytes = lim_compute_ext_cap_ie_length(pDst);
}
/**
@@ -2310,9 +2313,12 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac,
*/
else
{
if (extractedExtCap.interworkingService)
extractedExtCap.qosMap = 1;
extractedExtCapFlag = lim_is_ext_cap_ie_present(&extractedExtCap);
struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extractedExtCap.bytes;
if (p_ext_cap->interworkingService) {
p_ext_cap->qosMap = 1;
}
extractedExtCap.num_bytes = lim_compute_ext_cap_ie_length(&extractedExtCap);
extractedExtCapFlag = (extractedExtCap.num_bytes > 0);
}
caps = pMlmAssocReq->capabilityInfo;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2016. The Linux Foundation. All rights reserved.
* Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -8542,22 +8542,21 @@ bool lim_is_robust_mgmt_action_frame(uint8 action_catagory)
}
/**
* lim_is_ext_cap_ie_present - checks if ext ie is present
* lim_compute_ext_cap_ie_length - compute the length of ext cap ie
* based on the bits set
* @ext_cap: extended IEs structure
*
* Return: true if ext IEs are present else false
* Return: length of the ext cap ie, 0 means should not present
*/
bool lim_is_ext_cap_ie_present (tDot11fIEExtCap *ext_cap)
{
int i, size;
uint8_t *tmp_buf;
tANI_U8 lim_compute_ext_cap_ie_length (tDot11fIEExtCap *ext_cap) {
tANI_U8 i = DOT11F_IE_EXTCAP_MAX_LEN;
tmp_buf = (uint8_t *) ext_cap;
size = sizeof(*ext_cap);
while (i) {
if (ext_cap->bytes[i-1]) {
break;
}
i --;
}
for (i = 0; i < size; i++)
if (tmp_buf[i])
return true;
return false;
return i;
}
@@ -559,6 +559,6 @@ void limDecrementPendingMgmtCount (tpAniSirGlobal pMac);
eHalStatus limTxBdComplete(tpAniSirGlobal pMac, void *pData);
bool lim_is_robust_mgmt_action_frame(uint8 action_catagory);
bool lim_is_ext_cap_ie_present (tDot11fIEExtCap *ext_cap);
tANI_U8 lim_compute_ext_cap_ie_length (tDot11fIEExtCap *ext_cap);
#endif /* __LIM_UTILS_H */
File diff suppressed because it is too large Load Diff
@@ -1027,12 +1027,13 @@ PopulateDot11fExtCap(tpAniSirGlobal pMac,
tDot11fIEExtCap *pDot11f,
tpPESession psessionEntry)
{
struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)pDot11f->bytes;
#ifdef WLAN_FEATURE_11AC
if (psessionEntry->vhtCapability &&
psessionEntry->limSystemRole != eLIM_STA_IN_IBSS_ROLE )
{
pDot11f->operModeNotification = 1;
p_ext_cap->operModeNotification = 1;
pDot11f->present = 1;
}
#endif
@@ -1049,10 +1050,16 @@ PopulateDot11fExtCap(tpAniSirGlobal pMac,
&& pMac->roam.configParam.channelBondingMode24GHz)
#endif
{
pDot11f->bssCoexistMgmtSupport = 1;
p_ext_cap->bssCoexistMgmtSupport = 1;
pDot11f->present = 1;
}
}
if (pDot11f->present)
{
/* Need to compute the num_bytes based on bits set */
pDot11f->num_bytes = lim_compute_ext_cap_ie_length(pDot11f);
}
return eSIR_SUCCESS;
}
@@ -2625,10 +2632,13 @@ sirConvertAssocRespFrame2Struct(tpAniSirGlobal pMac,
}
if (ar.ExtCap.present)
{
struct s_ext_cap *p_ext_cap;
vos_mem_copy(&pAssocRsp->ExtCap, &ar.ExtCap, sizeof(tDot11fIEExtCap));
p_ext_cap = (struct s_ext_cap *)&pAssocRsp->ExtCap.bytes;
limLog(pMac, LOG1,
FL("ExtCap is present, TDLSChanSwitProhibited: %d"),
ar.ExtCap.TDLSChanSwitProhibited);
p_ext_cap->TDLSChanSwitProhibited);
}
if ( ar.WMMParams.present )
{
@@ -2945,6 +2955,8 @@ sirFillBeaconMandatoryIEforEseBcnReport(tpAniSirGlobal pMac,
limLog(pMac, LOGE, FL("Failed to allocate memory") );
return eSIR_FAILURE;
}
vos_mem_zero(pBies, sizeof(tDot11fBeaconIEs));
// delegate to the framesc-generated code,
status = dot11fUnpackBeaconIEs( pMac, pPayload, nPayload, pBies );
@@ -3239,6 +3251,8 @@ sirParseBeaconIE(tpAniSirGlobal pMac,
limLog(pMac, LOGE, FL("Failed to allocate memory") );
return eSIR_FAILURE;
}
vos_mem_zero(pBies, sizeof(tDot11fBeaconIEs));
// delegate to the framesc-generated code,
status = dot11fUnpackBeaconIEs( pMac, pPayload, nPayload, pBies );