Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fjes: fix memleaks in fjes_hw_setup

In fjes_hw_setup, it allocates several memory and delay the deallocation
to the fjes_hw_exit in fjes_probe through the following call chain:

fjes_probe
|-> fjes_hw_init
|-> fjes_hw_setup
|-> fjes_hw_exit

However, when fjes_hw_setup fails, fjes_hw_exit won't be called and thus
all the resources allocated in fjes_hw_setup will be leaked. In this
patch, we free those resources in fjes_hw_setup and prevents such leaks.

Fixes: 2fcbca687702 ("fjes: platform_driver's .probe and .remove routine")
Signed-off-by: Zhipeng Lu <alexious@zju.edu.cn>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20240122172445.3841883-1-alexious@zju.edu.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Zhipeng Lu and committed by
Jakub Kicinski
f6cc4b6a 77be2247

+30 -7
+30 -7
drivers/net/fjes/fjes_hw.c
··· 221 221 222 222 mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid); 223 223 hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL); 224 - if (!(hw->hw_info.req_buf)) 225 - return -ENOMEM; 224 + if (!(hw->hw_info.req_buf)) { 225 + result = -ENOMEM; 226 + goto free_ep_info; 227 + } 226 228 227 229 hw->hw_info.req_buf_size = mem_size; 228 230 229 231 mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid); 230 232 hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL); 231 - if (!(hw->hw_info.res_buf)) 232 - return -ENOMEM; 233 + if (!(hw->hw_info.res_buf)) { 234 + result = -ENOMEM; 235 + goto free_req_buf; 236 + } 233 237 234 238 hw->hw_info.res_buf_size = mem_size; 235 239 236 240 result = fjes_hw_alloc_shared_status_region(hw); 237 241 if (result) 238 - return result; 242 + goto free_res_buf; 239 243 240 244 hw->hw_info.buffer_share_bit = 0; 241 245 hw->hw_info.buffer_unshare_reserve_bit = 0; ··· 250 246 251 247 result = fjes_hw_alloc_epbuf(&buf_pair->tx); 252 248 if (result) 253 - return result; 249 + goto free_epbuf; 254 250 255 251 result = fjes_hw_alloc_epbuf(&buf_pair->rx); 256 252 if (result) 257 - return result; 253 + goto free_epbuf; 258 254 259 255 spin_lock_irqsave(&hw->rx_status_lock, flags); 260 256 fjes_hw_setup_epbuf(&buf_pair->tx, mac, ··· 277 273 fjes_hw_init_command_registers(hw, &param); 278 274 279 275 return 0; 276 + 277 + free_epbuf: 278 + for (epidx = 0; epidx < hw->max_epid ; epidx++) { 279 + if (epidx == hw->my_epid) 280 + continue; 281 + fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx); 282 + fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx); 283 + } 284 + fjes_hw_free_shared_status_region(hw); 285 + free_res_buf: 286 + kfree(hw->hw_info.res_buf); 287 + hw->hw_info.res_buf = NULL; 288 + free_req_buf: 289 + kfree(hw->hw_info.req_buf); 290 + hw->hw_info.req_buf = NULL; 291 + free_ep_info: 292 + kfree(hw->ep_shm_info); 293 + hw->ep_shm_info = NULL; 294 + return result; 280 295 } 281 296 282 297 static void fjes_hw_cleanup(struct fjes_hw *hw)