mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-10-31 18:09:19 +00:00
qcacld-2.0: Fix layering violation while handling management frames
qcacld-3.0 to qcacld-2.0 propagation Fix layering violation while handling management frames. Currently LIM data structures are accessed before dropping Assoc, Disassoc and Deauth packets to avoid DoS attacks. Since the LIM data structures are accessed in different thread context, data present in them are out of sync resulting in a crash. Fix the layering violation by doing appropriate check in WMA instead of doing the same in LIM. Change-Id: I8876a4d4b99948cd9ab3ccec403cf5e4050b1cff CRs-Fixed: 977773
This commit is contained in:
parent
cd3ae2df46
commit
5d6242a3b5
8 changed files with 136 additions and 183 deletions
|
@ -461,6 +461,94 @@ is_ccmp_pn_replay_attack(void *vos_ctx, struct ieee80211_frame *wh,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tlshim_is_pkt_drop_candidate() - check if the mgmt frame should be droppped
|
||||
* @wma_handle: wma handle
|
||||
* @peer_addr: peer MAC address
|
||||
* @subtype: Management frame subtype
|
||||
*
|
||||
* This function is used to decide if a particular management frame should be
|
||||
* dropped to prevent DOS attack. Timestamp is used to decide the DOS attack.
|
||||
*
|
||||
* Return: true if the packet should be dropped and false oterwise
|
||||
*/
|
||||
static bool tlshim_is_pkt_drop_candidate(tp_wma_handle wma_handle,
|
||||
uint8_t *peer_addr, uint8_t subtype)
|
||||
{
|
||||
struct ol_txrx_peer_t *peer;
|
||||
struct ol_txrx_pdev_t *pdev_ctx;
|
||||
uint8_t peer_id;
|
||||
tANI_BOOLEAN should_drop = eANI_BOOLEAN_FALSE;
|
||||
|
||||
/*
|
||||
* Currently this function handles only Disassoc,
|
||||
* Deauth and Assoc req frames. Return false for all other frames.
|
||||
*/
|
||||
if (subtype != IEEE80211_FC0_SUBTYPE_DISASSOC &&
|
||||
subtype != IEEE80211_FC0_SUBTYPE_DEAUTH &&
|
||||
subtype != IEEE80211_FC0_SUBTYPE_ASSOC_REQ) {
|
||||
should_drop = FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
pdev_ctx = vos_get_context(VOS_MODULE_ID_TXRX, wma_handle->vos_context);
|
||||
if (!pdev_ctx) {
|
||||
TLSHIM_LOGE(FL("Failed to get the context"));
|
||||
should_drop = TRUE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
peer = ol_txrx_find_peer_by_addr(pdev_ctx, peer_addr, &peer_id);
|
||||
if (!peer) {
|
||||
if (SIR_MAC_MGMT_ASSOC_REQ != subtype) {
|
||||
TLSHIM_LOGE(FL("Received mgmt frame: %0x from unknow peer: %pM"),
|
||||
subtype, peer_addr);
|
||||
should_drop = TRUE;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (subtype) {
|
||||
case SIR_MAC_MGMT_ASSOC_REQ:
|
||||
if (peer->last_assoc_rcvd) {
|
||||
if (adf_os_gettimestamp() - peer->last_assoc_rcvd <
|
||||
TLSHIM_MGMT_FRAME_DETECT_DOS_TIMER) {
|
||||
TLSHIM_LOGD(FL("Dropping Assoc Req received"));
|
||||
should_drop = TRUE;
|
||||
}
|
||||
}
|
||||
peer->last_assoc_rcvd = adf_os_gettimestamp();
|
||||
break;
|
||||
case SIR_MAC_MGMT_DISASSOC:
|
||||
if (peer->last_disassoc_rcvd) {
|
||||
if (adf_os_gettimestamp() -
|
||||
peer->last_disassoc_rcvd <
|
||||
TLSHIM_MGMT_FRAME_DETECT_DOS_TIMER) {
|
||||
TLSHIM_LOGD(FL("Dropping DisAssoc received"));
|
||||
should_drop = TRUE;
|
||||
}
|
||||
}
|
||||
peer->last_disassoc_rcvd = adf_os_gettimestamp();
|
||||
break;
|
||||
case SIR_MAC_MGMT_DEAUTH:
|
||||
if (peer->last_deauth_rcvd) {
|
||||
if (adf_os_gettimestamp() -
|
||||
peer->last_deauth_rcvd <
|
||||
TLSHIM_MGMT_FRAME_DETECT_DOS_TIMER) {
|
||||
TLSHIM_LOGD(FL("Dropping Deauth received"));
|
||||
should_drop = TRUE;
|
||||
}
|
||||
}
|
||||
peer->last_deauth_rcvd = adf_os_gettimestamp();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
return should_drop;
|
||||
}
|
||||
|
||||
#define RESERVE_BYTES 100
|
||||
static int tlshim_mgmt_rx_process(void *context, u_int8_t *data,
|
||||
u_int32_t data_len, bool saved_beacon, u_int32_t vdev_id)
|
||||
|
@ -468,9 +556,7 @@ static int tlshim_mgmt_rx_process(void *context, u_int8_t *data,
|
|||
void *vos_ctx = vos_get_global_context(VOS_MODULE_ID_TL, NULL);
|
||||
struct txrx_tl_shim_ctx *tl_shim = vos_get_context(VOS_MODULE_ID_TL,
|
||||
vos_ctx);
|
||||
#ifdef FEATURE_WLAN_D0WOW
|
||||
tp_wma_handle wma_handle = vos_get_context(VOS_MODULE_ID_WDA, vos_ctx);
|
||||
#endif
|
||||
WMI_MGMT_RX_EVENTID_param_tlvs *param_tlvs = NULL;
|
||||
wmi_mgmt_rx_hdr *hdr = NULL;
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
|
@ -804,6 +890,11 @@ static int tlshim_mgmt_rx_process(void *context, u_int8_t *data,
|
|||
}
|
||||
}
|
||||
#endif /* WLAN_FEATURE_11W */
|
||||
if (tlshim_is_pkt_drop_candidate(wma_handle, wh->i_addr2,
|
||||
mgt_subtype)) {
|
||||
vos_pkt_return_packet(rx_pkt);
|
||||
return -EINVAL;
|
||||
}
|
||||
return tl_shim->mgmt_rx(vos_ctx, rx_pkt);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
#include <adf_os_atomic.h>
|
||||
#include <vos_sched.h>
|
||||
|
||||
/* Time(in ms) to detect DOS attack */
|
||||
#define TLSHIM_MGMT_FRAME_DETECT_DOS_TIMER 1000
|
||||
|
||||
#ifdef FEATURE_WLAN_ESE
|
||||
typedef struct deferred_iapp_work {
|
||||
pVosContextType pVosGCtx;
|
||||
|
|
|
@ -1130,6 +1130,10 @@ ol_rx_peer_init(struct ol_txrx_pdev_t *pdev, struct ol_txrx_peer_t *peer)
|
|||
peer->security[txrx_sec_ucast].sec_type =
|
||||
peer->security[txrx_sec_mcast].sec_type = htt_sec_type_none;
|
||||
peer->keyinstalled = 0;
|
||||
peer->last_assoc_rcvd = 0;
|
||||
peer->last_disassoc_rcvd = 0;
|
||||
peer->last_deauth_rcvd = 0;
|
||||
|
||||
adf_os_atomic_init(&peer->fw_pn_check);
|
||||
}
|
||||
|
||||
|
@ -1137,6 +1141,9 @@ void
|
|||
ol_rx_peer_cleanup(struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer)
|
||||
{
|
||||
peer->keyinstalled = 0;
|
||||
peer->last_assoc_rcvd = 0;
|
||||
peer->last_disassoc_rcvd = 0;
|
||||
peer->last_deauth_rcvd = 0;
|
||||
ol_rx_reorder_peer_cleanup(vdev, peer);
|
||||
adf_os_mem_free(peer->reorder_history);
|
||||
peer->reorder_history = NULL;
|
||||
|
|
|
@ -1136,6 +1136,9 @@ struct ol_txrx_peer_t {
|
|||
u_int16_t tx_limit_flag;
|
||||
u_int16_t tx_pause_flag;
|
||||
#endif
|
||||
adf_os_time_t last_assoc_rcvd;
|
||||
adf_os_time_t last_disassoc_rcvd;
|
||||
adf_os_time_t last_deauth_rcvd;
|
||||
struct ol_rx_reorder_history * reorder_history;
|
||||
};
|
||||
|
||||
|
|
|
@ -179,10 +179,6 @@ void limPsOffloadHandleMissedBeaconInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
|
|||
void
|
||||
limSendHeartBeatTimeoutInd(tpAniSirGlobal pMac, tpPESession psessionEntry);
|
||||
tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U32 subType);
|
||||
bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info);
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info);
|
||||
#endif
|
||||
void limMicFailureInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
|
||||
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
|
||||
void limRoamOffloadSynchInd(tpAniSirGlobal pMac, tpSirMsgQ pMsg);
|
||||
|
|
|
@ -809,133 +809,6 @@ limCleanup(tpAniSirGlobal pMac)
|
|||
|
||||
} /*** end limCleanup() ***/
|
||||
|
||||
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
/**
|
||||
* lim_is_assoc_req_for_drop()- function to decides to drop assoc\reassoc
|
||||
* frames.
|
||||
* @mac: pointer to global mac structure
|
||||
* @rx_pkt_info: rx packet meta information
|
||||
*
|
||||
* This function is called before enqueuing the frame to PE queue to
|
||||
* drop flooded assoc/reassoc frames getting into PE Queue.
|
||||
*
|
||||
* Return: true for dropping the frame otherwise false
|
||||
*/
|
||||
|
||||
bool lim_is_assoc_req_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info)
|
||||
{
|
||||
uint8_t session_id;
|
||||
uint16_t aid;
|
||||
tpPESession session_entry;
|
||||
tpSirMacMgmtHdr mac_hdr;
|
||||
tpDphHashNode sta_ds;
|
||||
|
||||
mac_hdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info);
|
||||
session_entry = peFindSessionByBssid(mac, mac_hdr->bssId, &session_id);
|
||||
if (!session_entry) {
|
||||
PELOG1(limLog(mac, LOG1,
|
||||
FL("session does not exist for given STA [%pM]"),
|
||||
mac_hdr->sa););
|
||||
return false;
|
||||
}
|
||||
|
||||
sta_ds = dphLookupHashEntry(mac, mac_hdr->sa, &aid,
|
||||
&session_entry->dph.dphHashTable);
|
||||
if (!sta_ds) {
|
||||
PELOG1(limLog(mac, LOG1, FL("pStaDs is NULL")););
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sta_ds->rmfEnabled)
|
||||
return false;
|
||||
|
||||
if (sta_ds->pmfSaQueryState == DPH_SA_QUERY_IN_PROGRESS)
|
||||
return true;
|
||||
|
||||
if (sta_ds->last_assoc_received_time &&
|
||||
((vos_timer_get_system_time() -
|
||||
sta_ds->last_assoc_received_time) < 1000))
|
||||
return true;
|
||||
|
||||
sta_ds->last_assoc_received_time = vos_timer_get_system_time();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* lim_is_deauth_diassoc_for_drop()- function to decides to drop deauth\diassoc
|
||||
* frames.
|
||||
* @mac: pointer to global mac structure
|
||||
* @rx_pkt_info: rx packet meta information
|
||||
*
|
||||
* This function is called before enqueuing the frame to PE queue to
|
||||
* drop flooded deauth/diassoc frames getting into PE Queue.
|
||||
*
|
||||
* Return: true for dropping the frame otherwise false
|
||||
*/
|
||||
|
||||
bool lim_is_deauth_diassoc_for_drop(tpAniSirGlobal mac, uint8_t *rx_pkt_info)
|
||||
{
|
||||
uint8_t session_id;
|
||||
uint16_t aid;
|
||||
tpPESession session_entry;
|
||||
tpSirMacMgmtHdr mac_hdr;
|
||||
tpDphHashNode sta_ds;
|
||||
|
||||
mac_hdr = WDA_GET_RX_MAC_HEADER(rx_pkt_info);
|
||||
session_entry = peFindSessionByBssid(mac, mac_hdr->bssId, &session_id);
|
||||
if (!session_entry) {
|
||||
PELOG1(limLog(mac, LOG1,
|
||||
FL("session does not exist for given STA [%pM]"),
|
||||
mac_hdr->sa););
|
||||
return true;
|
||||
}
|
||||
|
||||
sta_ds = dphLookupHashEntry(mac, mac_hdr->sa, &aid,
|
||||
&session_entry->dph.dphHashTable);
|
||||
if (!sta_ds) {
|
||||
PELOG1(limLog(mac, LOG1,FL("pStaDs is NULL")););
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
if (session_entry->limRmfEnabled) {
|
||||
if ((WDA_GET_RX_DPU_FEEDBACK(rx_pkt_info) &
|
||||
DPU_FEEDBACK_UNPROTECTED_ERROR)) {
|
||||
/* It may be possible that deauth/diassoc frames from a
|
||||
* spoofy AP is received. So if all further
|
||||
* deauth/diassoc frmaes are dropped, then it may
|
||||
* result in lossing deauth/diassoc frames from genuine
|
||||
* AP. So process all deauth/diassoc frames with
|
||||
* a time difference of 1 sec.
|
||||
*/
|
||||
if ((vos_timer_get_system_time() -
|
||||
sta_ds->last_unprot_deauth_disassoc) < 1000)
|
||||
return true;
|
||||
|
||||
sta_ds->last_unprot_deauth_disassoc =
|
||||
vos_timer_get_system_time();
|
||||
} else {
|
||||
/* PMF enabed, Management frames are protected */
|
||||
if (sta_ds->proct_deauh_disassoc_cnt)
|
||||
return true;
|
||||
else
|
||||
sta_ds->proct_deauh_disassoc_cnt++;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* PMF disabled */
|
||||
{
|
||||
if (sta_ds->isDisassocDeauthInProgress)
|
||||
return true;
|
||||
else
|
||||
sta_ds->isDisassocDeauthInProgress++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** -------------------------------------------------------------
|
||||
\fn peOpen
|
||||
\brief will be called in Open sequence from macOpen
|
||||
|
@ -2618,17 +2491,6 @@ tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPac
|
|||
framelen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
|
||||
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
|
||||
|
||||
if ((subType == SIR_MAC_MGMT_DEAUTH ||
|
||||
subType == SIR_MAC_MGMT_DISASSOC) &&
|
||||
lim_is_deauth_diassoc_for_drop(pMac, pRxPacketInfo))
|
||||
return eMGMT_DROP_SPURIOUS_FRAME;
|
||||
|
||||
#ifdef WLAN_FEATURE_11W
|
||||
if ((subType == SIR_MAC_MGMT_ASSOC_REQ ||
|
||||
subType == SIR_MAC_MGMT_REASSOC_REQ) &&
|
||||
lim_is_assoc_req_for_drop(pMac, pRxPacketInfo))
|
||||
return eMGMT_DROP_SPURIOUS_FRAME;
|
||||
#endif
|
||||
//Drop INFRA Beacons and Probe Responses in IBSS Mode
|
||||
if( (subType == SIR_MAC_MGMT_BEACON) ||
|
||||
(subType == SIR_MAC_MGMT_PROBE_RSP))
|
||||
|
|
|
@ -717,6 +717,13 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg)
|
|||
fcOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(pRxPacketInfo);
|
||||
fc = pHdr->fc;
|
||||
|
||||
if (pMac->sap.SapDfsInfo.is_dfs_cac_timer_running) {
|
||||
psessionEntry = peFindSessionByBssid(pMac, pHdr->bssId, &sessionId);
|
||||
if (psessionEntry && (VOS_STA_SAP_MODE == psessionEntry->pePersona)) {
|
||||
limLog(pMac, LOG1, FL("CAC timer running - drop the frame"));
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#ifdef WLAN_DUMP_MGMTFRAMES
|
||||
limLog( pMac, LOGE, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"),
|
||||
fc.protVer, fc.type, fc.subType,
|
||||
|
|
|
@ -121,9 +121,6 @@ sysBbtProcessMessageCore(tpAniSirGlobal pMac, tpSirMsgQ pMsg, tANI_U32 type,
|
|||
vos_pkt_t *pVosPkt = (vos_pkt_t *)pMsg->bodyptr;
|
||||
VOS_STATUS vosStatus =
|
||||
WDA_DS_PeekRxPacketInfo( pVosPkt, (v_PVOID_t *)&pBd, VOS_FALSE );
|
||||
tANI_U8 sessionId;
|
||||
tpPESession psessionEntry;
|
||||
tpSirMacMgmtHdr pMacHdr;
|
||||
|
||||
pMac->sys.gSysBbtReceived++;
|
||||
|
||||
|
@ -141,20 +138,7 @@ sysBbtProcessMessageCore(tpAniSirGlobal pMac, tpSirMsgQ pMsg, tANI_U32 type,
|
|||
|
||||
if(type == SIR_MAC_MGMT_FRAME)
|
||||
{
|
||||
if (VOS_TRUE == pMac->sap.SapDfsInfo.is_dfs_cac_timer_running)
|
||||
{
|
||||
pMacHdr = WDA_GET_RX_MAC_HEADER(pBd);
|
||||
psessionEntry = peFindSessionByBssid(pMac,
|
||||
pMacHdr->bssId, &sessionId);
|
||||
if (psessionEntry &&
|
||||
(psessionEntry->pePersona == VOS_STA_SAP_MODE))
|
||||
{
|
||||
VOS_TRACE(VOS_MODULE_ID_SYS, VOS_TRACE_LEVEL_INFO_HIGH,
|
||||
FL("CAC timer is running, dropping the mgmt frame"));
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
tpSirMacMgmtHdr mac_hdr;
|
||||
/*
|
||||
* Drop beacon frames in deferred state to avoid VOSS run out of
|
||||
* message wrappers.
|
||||
|
@ -177,33 +161,33 @@ sysBbtProcessMessageCore(tpAniSirGlobal pMac, tpSirMsgQ pMsg, tANI_U32 type,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
mac_hdr = WDA_GET_RX_MAC_HEADER(pBd);
|
||||
if (subType == SIR_MAC_MGMT_ASSOC_REQ) {
|
||||
sysLog(pMac, LOG1,
|
||||
FL("ASSOC REQ frame allowed: da: " MAC_ADDRESS_STR ", sa: " MAC_ADDRESS_STR ", bssid: " MAC_ADDRESS_STR ", Assoc Req count so far: %d\n"),
|
||||
MAC_ADDR_ARRAY(mac_hdr->da),
|
||||
MAC_ADDR_ARRAY(mac_hdr->sa),
|
||||
MAC_ADDR_ARRAY(mac_hdr->bssId),
|
||||
pMac->sys.gSysFrameCount[type][subType]);
|
||||
}
|
||||
|
||||
if (subType == SIR_MAC_MGMT_DEAUTH)
|
||||
{
|
||||
tpSirMacMgmtHdr pMacHdr = WDA_GET_RX_MAC_HEADER(pBd);
|
||||
PELOGE(sysLog( pMac, LOGE,
|
||||
FL("DEAUTH frame allowed: "
|
||||
"da: " MAC_ADDRESS_STR ", "
|
||||
"sa: " MAC_ADDRESS_STR ", "
|
||||
"bssid: " MAC_ADDRESS_STR ", "
|
||||
"DEAUTH count so far: %d\n"),
|
||||
MAC_ADDR_ARRAY(pMacHdr->da),
|
||||
MAC_ADDR_ARRAY(pMacHdr->sa),
|
||||
MAC_ADDR_ARRAY(pMacHdr->bssId),
|
||||
pMac->sys.gSysFrameCount[type][subType] ););
|
||||
sysLog(pMac, LOG1,
|
||||
FL("DEAUTH frame allowed: da: " MAC_ADDRESS_STR ", sa: " MAC_ADDRESS_STR ", bssid: " MAC_ADDRESS_STR ", DEAUTH count so far: %d\n"),
|
||||
MAC_ADDR_ARRAY(mac_hdr->da),
|
||||
MAC_ADDR_ARRAY(mac_hdr->sa),
|
||||
MAC_ADDR_ARRAY(mac_hdr->bssId),
|
||||
pMac->sys.gSysFrameCount[type][subType]);
|
||||
}
|
||||
if (subType == SIR_MAC_MGMT_DISASSOC)
|
||||
{
|
||||
tpSirMacMgmtHdr pMacHdr = WDA_GET_RX_MAC_HEADER(pBd);
|
||||
PELOGE(sysLog( pMac, LOGE,
|
||||
FL("DISASSOC frame allowed: "
|
||||
"da: " MAC_ADDRESS_STR ", "
|
||||
"sa: " MAC_ADDRESS_STR ", "
|
||||
"bssid: " MAC_ADDRESS_STR ", "
|
||||
"DISASSOC count so far: %d\n"),
|
||||
MAC_ADDR_ARRAY(pMacHdr->da),
|
||||
MAC_ADDR_ARRAY(pMacHdr->sa),
|
||||
MAC_ADDR_ARRAY(pMacHdr->bssId),
|
||||
pMac->sys.gSysFrameCount[type][subType] ););
|
||||
sysLog(pMac, LOG1,
|
||||
FL("DISASSOC frame allowed: da: " MAC_ADDRESS_STR ", sa: " MAC_ADDRESS_STR ", bssid: " MAC_ADDRESS_STR ", DISASSOC count so far: %d\n"),
|
||||
MAC_ADDR_ARRAY(mac_hdr->da),
|
||||
MAC_ADDR_ARRAY(mac_hdr->sa),
|
||||
MAC_ADDR_ARRAY(mac_hdr->bssId),
|
||||
pMac->sys.gSysFrameCount[type][subType]);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue