From 6db0dac5b6d52b70a6793cd761d024829f242822 Mon Sep 17 00:00:00 2001 From: Shiva Krishna Pittala Date: Thu, 26 Jul 2018 16:41:30 +0530 Subject: [PATCH] qcacmn: Fix SKB leak in Spectral Netlink Spectral allocates its nbuf using qdf_nbuf_alloc() and calls Netlink functions to send the SKB to the application layer. After sending SKB, the Netlink send functions free the SKB using dev_kfree_skb(). As a result, QDF nbuf tracker treats this an SKB leak and panics the system. To avoid this leak, remove the SKB entry from QDF nbuf debug hash table by calling qdf_net_buf_debug_release_skb() before handling the SKB to Netlink send functions. Change-Id: I62c7046d1481c2a38ef5321410ebca9f5f5f34ed CRs-Fixed: 2285654 --- .../spectral/src/os_if_spectral_netlink.c | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/os_if/linux/spectral/src/os_if_spectral_netlink.c b/os_if/linux/spectral/src/os_if_spectral_netlink.c index e888eba64715..91584dcaeaa5 100644 --- a/os_if/linux/spectral/src/os_if_spectral_netlink.c +++ b/os_if/linux/spectral/src/os_if_spectral_netlink.c @@ -27,6 +27,20 @@ #include #endif +/** + * os_if_spectral_remove_nbuf_debug_entry() - Remove nbuf from nbuf debug table + * @nbuf - nbuf to remove from the nbuf debug table + * + * Remove nbuf from the nbuf debug hash table and decrement the nbuf count + * + * Return: None + */ +static inline void os_if_spectral_remove_nbuf_debug_entry(qdf_nbuf_t nbuf) +{ + qdf_nbuf_count_dec(nbuf); + qdf_net_buf_debug_release_skb(nbuf); +} + #ifndef CNSS_GENL static struct sock *os_if_spectral_nl_sock; static atomic_t spectral_nl_users = ATOMIC_INIT(0); @@ -334,7 +348,7 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev) if (!ps->spectral_sock) { spectral_err("Spectral Socket is invalid"); - dev_kfree_skb(ps->skb); + qdf_nbuf_free(ps->skb); return -EINVAL; } @@ -345,6 +359,7 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev) /* to mcast group 1<<0 */ NETLINK_CB(ps->skb).dst_group = 0; + os_if_spectral_remove_nbuf_debug_entry(ps->skb); status = netlink_unicast(ps->spectral_sock, ps->skb, ps->spectral_pid, MSG_DONTWAIT); @@ -378,6 +393,7 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev) os_if_init_spectral_skb_pid_portid(ps->skb); + os_if_spectral_remove_nbuf_debug_entry(ps->skb); status = nl_srv_ucast(ps->skb, ps->spectral_pid, MSG_DONTWAIT, WLAN_NL_MSG_SPECTRAL_SCAN, CLD80211_MCGRP_OEM_MSGS); if (status < 0) @@ -425,10 +441,11 @@ os_if_spectral_nl_bcast_msg(struct wlan_objmgr_pdev *pdev) } if (!ps->spectral_sock) { - dev_kfree_skb(ps->skb); + qdf_nbuf_free(ps->skb); return -EINVAL; } + os_if_spectral_remove_nbuf_debug_entry(ps->skb); status = netlink_broadcast(ps->spectral_sock, ps->skb, 0, 1, GFP_ATOMIC);