From b70014489c296bb9081241bd00855fbe2dc48216 Mon Sep 17 00:00:00 2001 From: Karthik Kantamneni Date: Tue, 7 Jun 2022 16:10:22 +0530 Subject: [PATCH] qcacmn: Avoid invalid Rx descriptor access in error path There is possibility of receiving invalid SW cookie which maps to invalid rx descriptor access, to avoid such issues validate the SW cookie before using it for fetching rx descriptor Change-Id: Ib90a398865c5e0afedd5804615d6df6ad5ee77f6 CRs-Fixed: 3214570 --- dp/wifi3.0/dp_rx.h | 48 ++++++++++++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_rx_err.c | 10 +++++++++ 2 files changed, 58 insertions(+) diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index ca90e46929..011f6f2ac5 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -656,6 +656,54 @@ dp_rx_cookie_reset_invalid_bit(hal_ring_desc_t ring_desc) #endif /* QCA_HOST_MODE_WIFI_DISABLED */ +#ifdef RX_DESC_MULTI_PAGE_ALLOC +/** + * dp_rx_is_sw_cookie_valid() - check whether SW cookie valid + * @soc: dp soc ref + * @cookie: Rx buf SW cookie value + * + * Return: true if cookie is valid else false + */ +static inline bool dp_rx_is_sw_cookie_valid(struct dp_soc *soc, + uint32_t cookie) +{ + uint8_t pool_id = DP_RX_DESC_MULTI_PAGE_COOKIE_GET_POOL_ID(cookie); + uint16_t page_id = DP_RX_DESC_MULTI_PAGE_COOKIE_GET_PAGE_ID(cookie); + uint8_t offset = DP_RX_DESC_MULTI_PAGE_COOKIE_GET_OFFSET(cookie); + struct rx_desc_pool *rx_desc_pool; + + if (qdf_unlikely(pool_id >= MAX_PDEV_CNT)) + goto fail; + + rx_desc_pool = &soc->rx_desc_buf[pool_id]; + + if (page_id >= rx_desc_pool->desc_pages.num_pages || + offset >= rx_desc_pool->desc_pages.num_element_per_page) + goto fail; + + return true; + +fail: + DP_STATS_INC(soc, rx.err.invalid_cookie, 1); + return false; +} +#else +/** + * dp_rx_is_sw_cookie_valid() - check whether SW cookie valid + * @soc: dp soc ref + * @cookie: Rx buf SW cookie value + * + * When multi page alloc is disabled SW cookie validness is + * checked while fetching Rx descriptor, so no need to check here + * Return: true if cookie is valid else false + */ +static inline bool dp_rx_is_sw_cookie_valid(struct dp_soc *soc, + uint32_t cookie) +{ + return true; +} +#endif + QDF_STATUS dp_rx_desc_pool_is_allocated(struct rx_desc_pool *rx_desc_pool); QDF_STATUS dp_rx_desc_pool_alloc(struct dp_soc *soc, uint32_t pool_size, diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 2002b973f7..a1043d7922 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -2383,8 +2383,18 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, hal_rx_reo_buf_paddr_get(soc->hal_soc, ring_desc, &hbi); link_desc_va = dp_rx_cookie_2_link_desc_va(soc, &hbi); + num_msdus = 0; hal_rx_msdu_list_get(soc->hal_soc, link_desc_va, &msdu_list, &num_msdus); + if (!num_msdus || + !dp_rx_is_sw_cookie_valid(soc, msdu_list.sw_cookie[0])) { + dp_rx_err_info_rl("Invalid MSDU info num_msdus %u cookie: 0x%x", + num_msdus, msdu_list.sw_cookie[0]); + dp_rx_link_desc_return(soc, ring_desc, + HAL_BM_ACTION_PUT_IN_IDLE_LIST); + goto next_entry; + } + dp_rx_err_ring_record_entry(soc, msdu_list.paddr[0], msdu_list.sw_cookie[0], msdu_list.rbm[0]);