Преглед изворни кода

qcacmn: Filter out invalid BSSID from rx MGMT frame

Currently the driver accepts zero BSSID obtained from the
beacon/probe response and also allows to connect to them
by creating a peer, but since connection doesn't go
forward with the peer as BSSID is zero, the driver
deletes the peer, but since the BSSID is zero, the
host doesnt sends the peer delete to FW, which causes
a peer leak.

Fix is to filter out the beacons which has invalid BSSID,
and try to recreate the address from the addr2 which is
the FROM address in the MAC address. In case of AP the
BSSID and FROM address would be same, and hence BSSID
can be copied from the same.

Change-Id: I75842c2d80254aaffc31e689782be2eebc118466
CRs-Fixed: 2391346
gaurank kathpalia пре 6 година
родитељ
комит
c81b9a3b34

+ 3 - 1
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -50,6 +50,8 @@
 	QDF_TRACE_DEBUG(QDF_MODULE_ID_MGMT_TXRX, params)
 #define mgmt_txrx_err_rl(params...) \
 	QDF_TRACE_ERROR_RL(QDF_MODULE_ID_MGMT_TXRX, params)
+#define mgmt_txrx_debug_rl(params...) \
+	QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_MGMT_TXRX, params)
 
 #define mgmttxrx_nofl_alert(params...) \
 	QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_MGMT_TXRX, params)

+ 36 - 0
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c

@@ -833,6 +833,16 @@ static QDF_STATUS wlan_mgmt_txrx_rx_handler_list_copy(
 	return QDF_STATUS_SUCCESS;
 }
 
+static bool
+mgmt_rx_is_bssid_valid(struct qdf_mac_addr *mac_addr)
+{
+	if (qdf_is_macaddr_group(mac_addr) ||
+	    qdf_is_macaddr_zero(mac_addr))
+		return false;
+
+	return true;
+}
+
 QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 			struct wlan_objmgr_psoc *psoc,
 			qdf_nbuf_t buf,
@@ -850,6 +860,7 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 	u_int8_t *data, *ivp = NULL;
 	uint16_t buflen;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	bool is_from_addr_valid, is_bssid_valid;
 
 	if (!buf) {
 		mgmt_txrx_err("buffer passed is NULL");
@@ -881,6 +892,31 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	is_from_addr_valid = mgmt_rx_is_bssid_valid((struct qdf_mac_addr *)
+							      wh->i_addr2);
+	is_bssid_valid = mgmt_rx_is_bssid_valid((struct qdf_mac_addr *)
+							      wh->i_addr3);
+
+	if (!is_from_addr_valid && !is_bssid_valid) {
+		mgmt_txrx_debug_rl("from addr %pM bssid addr %pM both not valid, dropping them",
+				   wh->i_addr2, wh->i_addr3);
+		qdf_nbuf_free(buf);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if ((mgmt_subtype == MGMT_SUBTYPE_BEACON ||
+	     mgmt_subtype == MGMT_SUBTYPE_PROBE_RESP) &&
+	    !(is_from_addr_valid && is_bssid_valid)) {
+		mgmt_txrx_debug_rl("from addr %pM bssid addr %pM not valid, modifying them",
+				   wh->i_addr2, wh->i_addr3);
+		if (!is_from_addr_valid)
+			qdf_mem_copy(wh->i_addr2, wh->i_addr3,
+				     IEEE80211_ADDR_LEN);
+		else
+			qdf_mem_copy(wh->i_addr3, wh->i_addr2,
+				     IEEE80211_ADDR_LEN);
+	}
+
 	/* mpdu_data_ptr is pointer to action header */
 	mpdu_data_ptr = (uint8_t *)qdf_nbuf_data(buf) +
 			sizeof(struct ieee80211_frame);