From 4f5c3f564519f64d40486da40de8f4a5b2e55f55 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Thu, 14 Sep 2023 12:31:50 +0530 Subject: [PATCH] qcacld-3.0: Fix ethertype inspection logic of offload tx data pkt Offload TX data packets such as ARP response, EAPOL during roaming are sent by firmware through HTT msg if packet capture mode is enabled. Whenever any such packet is received via HTT msg, host inspects the ether type of the packet and matches with the TX filter set by user via vendor command. If the ether type matches with the TX filter set by user, then host forwards that packet to packet capture mode interface otherwise, drops it. To inspect the ether type of any packet, host uses generic API which expects packet to be in SKB format. Currently, whenever any offload TX data packet is received in HTT msg, host wrongly passes the buffer received in HTT msg instead of SKB to APIs expecting SKB buffer. This leads to undefined behavior. So, to fix above issue, whenever any offload TX data packet received, first allocate the SKB, copy the payload buf of HTT msg which is TX packet to SKB data and then pass that SKB to the generic APIs to get the ether type. Additionally, this change fixes the minor logging error. Change-Id: If09d49d8a1dcc04ca81454fc262bb5789a0f56be CRs-Fixed: 3613594 --- .../core/inc/wlan_pkt_capture_main.h | 15 +++++ .../core/src/wlan_pkt_capture_data_txrx.c | 60 ++++++++++++++----- .../core/src/wlan_pkt_capture_main.c | 14 +---- os_if/pkt_capture/src/os_if_pkt_capture.c | 4 +- 4 files changed, 64 insertions(+), 29 deletions(-) diff --git a/components/pkt_capture/core/inc/wlan_pkt_capture_main.h b/components/pkt_capture/core/inc/wlan_pkt_capture_main.h index cb48a75b7b8d..312c0d4f2638 100644 --- a/components/pkt_capture/core/inc/wlan_pkt_capture_main.h +++ b/components/pkt_capture/core/inc/wlan_pkt_capture_main.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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 @@ -238,6 +239,20 @@ QDF_STATUS pkt_capture_set_filter(struct pkt_capture_frame_filter frame_filter, */ bool pkt_capture_is_tx_mgmt_enable(struct wlan_objmgr_pdev *pdev); +/** + * pkt_capture_is_frame_filter_set - Check if filter type set by user and packet + * type matches + * @buf: netbuf + * @frame_filter: filter set by user via vendor command + * @direction: Tx or Rx + * + * Return: bool + */ +bool +pkt_capture_is_frame_filter_set(qdf_nbuf_t buf, + struct pkt_capture_frame_filter *frame_filter, + bool direction); + #ifdef WLAN_FEATURE_PKT_CAPTURE_V2 /** * pkt_capture_get_pktcap_mode_v2 - Get packet capture mode diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c b/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c index 7170c423a6fc..b4dbc0a375cc 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_data_txrx.c @@ -1634,9 +1634,51 @@ void pkt_capture_offload_deliver_indication_handler( struct pkt_capture_tx_hdr_elem_t *ptr_pktcapture_hdr; struct pkt_capture_tx_hdr_elem_t pktcapture_hdr = {0}; uint32_t txcap_hdr_size = sizeof(struct pkt_capture_tx_hdr_elem_t); + struct wlan_objmgr_vdev *vdev; + struct pkt_capture_vdev_priv *vdev_priv; + struct pkt_capture_frame_filter *frame_filter; + QDF_STATUS ret = QDF_STATUS_SUCCESS; offload_deliver_msg = (struct htt_tx_offload_deliver_ind_hdr_t *)msg; + vdev = pkt_capture_get_vdev(); + ret = pkt_capture_vdev_get_ref(vdev); + if (QDF_IS_STATUS_ERROR(ret)) + return; + + vdev_priv = pkt_capture_vdev_get_priv(vdev); + if (!vdev_priv) { + pkt_capture_err("vdev priv is NULL"); + pkt_capture_vdev_put_ref(vdev); + return; + } + + frame_filter = &vdev_priv->frame_filter; + + nbuf_len = offload_deliver_msg->tx_mpdu_bytes; + netbuf = qdf_nbuf_alloc(NULL, + roundup(nbuf_len + RESERVE_BYTES, 4), + RESERVE_BYTES, 4, false); + if (!netbuf) { + pkt_capture_vdev_put_ref(vdev); + return; + } + + qdf_nbuf_put_tail(netbuf, nbuf_len); + + qdf_mem_copy(qdf_nbuf_data(netbuf), + buf + sizeof(struct htt_tx_offload_deliver_ind_hdr_t), + nbuf_len); + + if (!(frame_filter->data_tx_frame_filter & + PKT_CAPTURE_DATA_FRAME_TYPE_ALL) && + !pkt_capture_is_frame_filter_set( + netbuf, frame_filter, IEEE80211_FC1_DIR_TODS)) { + qdf_nbuf_free(netbuf); + pkt_capture_vdev_put_ref(vdev); + return; + } + pktcapture_hdr.timestamp = offload_deliver_msg->phy_timestamp_l32; pktcapture_hdr.preamble = offload_deliver_msg->preamble; pktcapture_hdr.mcs = offload_deliver_msg->mcs; @@ -1656,25 +1698,11 @@ void pkt_capture_offload_deliver_indication_handler( status = offload_deliver_msg->status; pkt_format = offload_deliver_msg->format; - nbuf_len = offload_deliver_msg->tx_mpdu_bytes; - - netbuf = qdf_nbuf_alloc(NULL, - roundup(nbuf_len + RESERVE_BYTES, 4), - RESERVE_BYTES, 4, false); - - if (!netbuf) - return; - - qdf_nbuf_put_tail(netbuf, nbuf_len); - - qdf_mem_copy(qdf_nbuf_data(netbuf), - buf + sizeof(struct htt_tx_offload_deliver_ind_hdr_t), - nbuf_len); - qdf_nbuf_push_head(netbuf, txcap_hdr_size); ptr_pktcapture_hdr = (struct pkt_capture_tx_hdr_elem_t *)qdf_nbuf_data(netbuf); + qdf_mem_copy(ptr_pktcapture_hdr, &pktcapture_hdr, txcap_hdr_size); pkt_capture_datapkt_process( @@ -1682,5 +1710,7 @@ void pkt_capture_offload_deliver_indication_handler( netbuf, TXRX_PROCESS_TYPE_DATA_TX, tid, status, pkt_format, bssid, soc, offload_deliver_msg->tx_retry_cnt); + + pkt_capture_vdev_put_ref(vdev); } #endif diff --git a/components/pkt_capture/core/src/wlan_pkt_capture_main.c b/components/pkt_capture/core/src/wlan_pkt_capture_main.c index 9c6b1b36d45d..6c29e65cfda7 100644 --- a/components/pkt_capture/core/src/wlan_pkt_capture_main.c +++ b/components/pkt_capture/core/src/wlan_pkt_capture_main.c @@ -407,7 +407,7 @@ pkt_capture_process_tx_data(void *soc, void *log_data, u_int16_t vdev_id, * Return: true, if filter bit is set * false, if filter bit is not set */ -static bool +bool pkt_capture_is_frame_filter_set(qdf_nbuf_t buf, struct pkt_capture_frame_filter *frame_filter, bool direction) @@ -595,8 +595,6 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, struct htt_tx_offload_deliver_ind_hdr_t *offload_deliver_msg; bool is_pkt_during_roam = false; uint32_t freq = 0; - qdf_nbuf_t buf = log_data + - sizeof(struct htt_tx_offload_deliver_ind_hdr_t); if (!frame_filter->data_tx_frame_filter) { pkt_capture_vdev_put_ref(vdev); @@ -616,17 +614,9 @@ void pkt_capture_callback(void *soc, enum WDI_EVENT event, void *log_data, vdev_id = offload_deliver_msg->vdev_id; } - if (frame_filter->data_tx_frame_filter & - PKT_CAPTURE_DATA_FRAME_TYPE_ALL) { - pkt_capture_offload_deliver_indication_handler( + pkt_capture_offload_deliver_indication_handler( log_data, vdev_id, bssid, soc); - } else if (pkt_capture_is_frame_filter_set( - buf, frame_filter, IEEE80211_FC1_DIR_TODS)) { - pkt_capture_offload_deliver_indication_handler( - log_data, - vdev_id, bssid, soc); - } break; } diff --git a/os_if/pkt_capture/src/os_if_pkt_capture.c b/os_if/pkt_capture/src/os_if_pkt_capture.c index c1e836a57ffc..eae4ca23fa56 100644 --- a/os_if/pkt_capture/src/os_if_pkt_capture.c +++ b/os_if/pkt_capture/src/os_if_pkt_capture.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. 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 @@ -150,7 +150,7 @@ QDF_STATUS os_if_monitor_mode_configure(struct hdd_adapter *adapter, BIT(SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL); } - osif_debug("Monitor mode config %s data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d bi %d\n", + osif_debug("Monitor mode config data tx %d data rx %d mgmt tx %d mgmt rx %d ctrl tx %d ctrl rx %d bi %d\n", frame_filter.data_tx_frame_filter, frame_filter.data_rx_frame_filter, frame_filter.mgmt_tx_frame_filter,