[<prev] [next>] [day] [month] [year] [list]
Message-ID: <ZfOhWVnTsE8JAhXk@cy-server>
Date: Thu, 14 Mar 2024 20:16:09 -0500
From: Chenyuan Yang <chenyuan0y@...il.com>
To: chandrashekar.devegowda@...el.com, chiranjeevi.rapolu@...ux.intel.com,
haijun.liu@...iatek.com, m.chetan.kumar@...ux.intel.com,
ricardo.martinez@...ux.intel.com, loic.poulain@...aro.org,
ryazanov.s.a@...il.com, johannes@...solutions.net,
davem@...emloft.net, edumazet@...gle.com, kuba@...nel.org,
pabeni@...hat.com
Cc: netdev@...r.kernel.org, zzjas98@...il.com
Subject: [drivers/net/wwan] Question about possible memory leaks in
t7xx_dpmaif_rx_buf_alloc() and t7xx_dpmaif_rx_frag_alloc()
Dear WWAN Driver Developers,
We are curious whether the functions `t7xx_dpmaif_rx_buf_alloc()` and `t7xx_dpmaif_rx_frag_alloc` might have memory leaks.
#1. The function `t7xx_dpmaif_rx_buf_alloc` is https://elixir.bootlin.com/linux/v6.8/source/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c#L164
and the relevant code is
```
int t7xx_dpmaif_rx_buf_alloc(struct dpmaif_ctrl *dpmaif_ctrl,
const struct dpmaif_bat_request *bat_req,
const unsigned int q_num, const unsigned int buf_cnt,
const bool initial)
{
unsigned int i, bat_cnt, bat_max_cnt, bat_start_idx;
int ret;
...
for (i = 0; i < buf_cnt; i++) {
unsigned int cur_bat_idx = bat_start_idx + i;
struct dpmaif_bat_skb *cur_skb;
struct dpmaif_bat *cur_bat;
if (cur_bat_idx >= bat_max_cnt)
cur_bat_idx -= bat_max_cnt;
cur_skb = (struct dpmaif_bat_skb *)bat_req->bat_skb + cur_bat_idx;
if (!cur_skb->skb &&
!t7xx_alloc_and_map_skb_info(dpmaif_ctrl, bat_req->pkt_buf_sz, cur_skb))
break;
cur_bat = (struct dpmaif_bat *)bat_req->bat_base + cur_bat_idx;
}
...
ret = t7xx_dpmaif_update_bat_wr_idx(dpmaif_ctrl, q_num, i);
if (ret)
goto err_unmap_skbs;
...
err_unmap_skbs:
while (--i > 0)
t7xx_unmap_bat_skb(dpmaif_ctrl->dev, bat_req->bat_skb, i);
}
```
In the label `err_unmap_skbs`, the function will unmap the allocated memory for `bat_req->bat_skb` by checking `while (--i > 0)`. However, the first element (`i=0`) of `bat_req->bat_skb` is not unmapped since `i` is decremented before the check.
By contrast, in the function `t7xx_dpmaif_bat_free` (https://elixir.bootlin.com/linux/v6.8/source/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c#L984), the first element of `bat_req->bat_skb` is unmapped.
Based on our understanding, a possible fix would be
```
- while (--i > 0)
+ while (--i >= 0)
```
#2. For another function `t7xx_dpmaif_rx_frag_alloc`, the function is https://elixir.bootlin.com/linux/v6.8/source/drivers/net/wwan/t7xx/t7xx_hif_dpmaif_rx.c#L319
```
int t7xx_dpmaif_rx_frag_alloc(struct dpmaif_ctrl *dpmaif_ctrl, struct dpmaif_bat_request *bat_req,
const unsigned int buf_cnt, const bool initial)
{
unsigned int buf_space, cur_bat_idx = bat_req->bat_wr_idx;
struct dpmaif_bat_page *bat_skb = bat_req->bat_skb;
int ret = 0, i;
if (!buf_cnt || buf_cnt > bat_req->bat_size_cnt)
return -EINVAL;
...
for (i = 0; i < buf_cnt; i++) {
struct dpmaif_bat_page *cur_page = bat_skb + cur_bat_idx;
struct dpmaif_bat *cur_bat;
dma_addr_t data_base_addr;
...
cur_bat = (struct dpmaif_bat *)bat_req->bat_base + cur_bat_idx;
cur_bat->buffer_addr_ext = upper_32_bits(data_base_addr);
cur_bat->p_buffer_addr = lower_32_bits(data_base_addr);
cur_bat_idx = t7xx_ring_buf_get_next_wr_idx(bat_req->bat_size_cnt, cur_bat_idx);
}
...
if (i < buf_cnt) {
ret = -ENOMEM;
if (initial) {
while (--i > 0)
t7xx_unmap_bat_page(dpmaif_ctrl->dev, bat_req->bat_skb, i);
}
}
return ret;
}
```
Similarly, the function will unmap the allocated memory for `bat_req->bat_skb` by checking `while (--i > 0)`. However, the first element (`i=0`) of `bat_req->bat_skb` is not unmapped since `i` is decremented before the check.
Please kindly correct us if we missed any key information. Looking forward to your response!
Best,
Chenyuan
Powered by blists - more mailing lists