From 9f72aa9c82e83c7b46f592c84b2bf93c91e05ed1 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Sat, 18 Jul 2020 01:07:29 +0530 Subject: [PATCH] qcacld-3.0: Fix use-after-free when skb is copied When we receive a packet from the network stack for transmission, we make a copy of this skb and free the shared skb before trying to trasnmit it. Currently the mac address used for tdls operations is taken as a pointer to the original skb, which gets freed after the skb_unshare. Copy the mac address into a local stack memory instead of using a pointer to the skb data to avoid the use-after-free condition. Change-Id: I9f0e6260476d5a41b7209a6a599f50a548b953b5 CRs-Fixed: 2733445 --- core/hdd/src/wlan_hdd_tx_rx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index c42064c36978..b57f71f18f13 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -945,7 +945,7 @@ static void __hdd_hard_start_xmit(struct sk_buff *skb, struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); bool granted; struct hdd_station_ctx *sta_ctx = &adapter->session.station; - struct qdf_mac_addr *mac_addr; + struct qdf_mac_addr mac_addr; struct qdf_mac_addr mac_addr_tx_allowed = QDF_MAC_ADDR_ZERO_INIT; uint8_t pkt_type = 0; bool is_arp = false; @@ -965,7 +965,7 @@ static void __hdd_hard_start_xmit(struct sk_buff *skb, ++adapter->hdd_stats.tx_rx_stats.tx_called; adapter->hdd_stats.tx_rx_stats.cont_txtimeout_cnt = 0; - mac_addr = (struct qdf_mac_addr *)skb->data; + qdf_mem_copy(mac_addr.bytes, skb->data, sizeof(mac_addr.bytes)); if (cds_is_driver_recovering() || cds_is_driver_in_bad_state() || cds_is_load_or_unload_in_progress()) { @@ -1024,7 +1024,7 @@ static void __hdd_hard_start_xmit(struct sk_buff *skb, goto drop_pkt; } - hdd_get_tx_resource(adapter, mac_addr, + hdd_get_tx_resource(adapter, &mac_addr, WLAN_HDD_TX_FLOW_CONTROL_OS_Q_BLOCK_TIME); /* Get TL AC corresponding to Qdisc queue index/AC. */ @@ -1122,7 +1122,7 @@ static void __hdd_hard_start_xmit(struct sk_buff *skb, vdev = hdd_objmgr_get_vdev(adapter); if (vdev) { - ucfg_tdls_update_tx_pkt_cnt(vdev, mac_addr); + ucfg_tdls_update_tx_pkt_cnt(vdev, &mac_addr); hdd_objmgr_put_vdev(vdev); } @@ -1180,7 +1180,7 @@ static void __hdd_hard_start_xmit(struct sk_buff *skb, QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_INFO_HIGH, "%s: Failed to send packet to txrx for sta_id: " QDF_MAC_ADDR_STR, - __func__, QDF_MAC_ADDR_ARRAY(mac_addr->bytes)); + __func__, QDF_MAC_ADDR_ARRAY(mac_addr.bytes)); ++adapter->hdd_stats.tx_rx_stats.tx_dropped_ac[ac]; goto drop_pkt_and_release_skb; }