From 7a26da4e7e79ae1b863c003179b8143feb8efcf7 Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Sat, 29 Feb 2020 20:42:28 +0530 Subject: [PATCH] qcacmn: Validate the rx descriptor before dereferencing The rx descriptor obtained using the cookie can be NULL if the cookie is invalid. Hence dereferencing the rx descriptor without any validation can cause invalid address access. Fix this by validating the rx descriptor which has been obtained using the cookie from the hal ring descriptor. Change-Id: Ib584f0d8175b581d15b0e1c67d2f6ed9119ecbfc CRs-Fixed: 2629254 --- dp/wifi3.0/dp_rx.c | 42 +++++++++++++++++++++++++++++++++++++++++- dp/wifi3.0/dp_stats.c | 3 +++ dp/wifi3.0/dp_types.h | 2 ++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 4143f347fd08..8df54658920d 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -89,6 +89,40 @@ void dp_rx_dump_info_and_assert(struct dp_soc *soc, } #endif +#ifdef RX_DESC_SANITY_WAR +static inline +QDF_STATUS dp_rx_desc_sanity(struct dp_soc *soc, hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) +{ + if (qdf_unlikely(!rx_desc)) { + /* + * This is an unlikely case where the cookie obtained + * from the ring_desc is invalid and hence we are not + * able to find the corresponding rx_desc + */ + DP_STATS_INC(soc, rx.err.invalid_cookie, 1); + dp_err("Ring Desc:"); + hal_srng_dump_ring_desc(hal_soc, hal_ring_hdl, + ring_desc); + qdf_assert(0); + return QDF_STATUS_E_NULL_VALUE; + } + + return QDF_STATUS_SUCCESS; +} +#else +static inline +QDF_STATUS dp_rx_desc_sanity(struct dp_soc *soc, hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, + hal_ring_desc_t ring_desc, + struct dp_rx_desc *rx_desc) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /* * dp_rx_buffers_replenish() - replenish rxdma ring with rx nbufs * called during dp rx initialization @@ -1831,6 +1865,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, uint32_t rx_ol_pkt_cnt = 0; uint32_t num_entries = 0; struct hal_rx_msdu_metadata msdu_metadata; + QDF_STATUS status; DP_HIST_INIT(); @@ -1894,7 +1929,12 @@ more_data: rx_buf_cookie = HAL_RX_REO_BUF_COOKIE_GET(ring_desc); rx_desc = dp_rx_cookie_2_va_rxdma_buf(soc, rx_buf_cookie); - qdf_assert(rx_desc); + status = dp_rx_desc_sanity(soc, hal_soc, hal_ring_hdl, + ring_desc, rx_desc); + if (QDF_IS_STATUS_ERROR(status)) { + hal_srng_dst_get_next(hal_soc, hal_ring_hdl); + continue; + } /* * this is a unlikely scenario where the host is reaping diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index 8dbe757c055b..d85d7bc7172e 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -6033,6 +6033,9 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("RX scatter msdu: %d", soc->stats.rx.err.scatter_msdu); + DP_PRINT_STATS("RX invalid cookie: %d", + soc->stats.rx.err.invalid_cookie); + DP_PRINT_STATS("RX wait completed msdu break: %d", soc->stats.rx.msdu_scatter_wait_break); diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 875af22168a2..4e66ec7f1cc4 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -784,6 +784,8 @@ struct dp_soc_stats { uint32_t reo_cmd_send_fail; /* RX msdu drop count due to scatter */ uint32_t scatter_msdu; + /* RX msdu drop count due to invalid cookie */ + uint32_t invalid_cookie; } err; /* packet count per core - per ring */