Skip to content

Commit c188afd

Browse files
pkitszelanguy11
authored andcommitted
ice: fix memleak in ice_init_tx_topology()
Fix leak of the FW blob (DDP pkg). Make ice_cfg_tx_topo() const-correct, so ice_init_tx_topology() can avoid copying whole FW blob. Copy just the topology section, and only when needed. Reuse the buffer allocated for the read of the current topology. This was found by kmemleak, with the following trace for each PF: [<ffffffff8761044d>] kmemdup_noprof+0x1d/0x50 [<ffffffffc0a0a480>] ice_init_ddp_config+0x100/0x220 [ice] [<ffffffffc0a0da7f>] ice_init_dev+0x6f/0x200 [ice] [<ffffffffc0a0dc49>] ice_init+0x29/0x560 [ice] [<ffffffffc0a10c1d>] ice_probe+0x21d/0x310 [ice] Constify ice_cfg_tx_topo() @buf parameter. This cascades further down to few more functions. Fixes: cc5776f ("ice: Enable switching default Tx scheduler topology") CC: Larysa Zaremba <[email protected]> CC: Jacob Keller <[email protected]> CC: Pucha Himasekhar Reddy <[email protected]> CC: Mateusz Polchlopek <[email protected]> Signed-off-by: Przemek Kitszel <[email protected]> Reviewed-by: Jacob Keller <[email protected]> Tested-by: Pucha Himasekhar Reddy <[email protected]> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <[email protected]>
1 parent d019b1a commit c188afd

File tree

3 files changed

+31
-39
lines changed

3 files changed

+31
-39
lines changed

drivers/net/ethernet/intel/ice/ice_ddp.c

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static const struct ice_tunnel_type_scan tnls[] = {
3131
* Verifies various attributes of the package file, including length, format
3232
* version, and the requirement of at least one segment.
3333
*/
34-
static enum ice_ddp_state ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)
34+
static enum ice_ddp_state ice_verify_pkg(const struct ice_pkg_hdr *pkg, u32 len)
3535
{
3636
u32 seg_count;
3737
u32 i;
@@ -57,13 +57,13 @@ static enum ice_ddp_state ice_verify_pkg(struct ice_pkg_hdr *pkg, u32 len)
5757
/* all segments must fit within length */
5858
for (i = 0; i < seg_count; i++) {
5959
u32 off = le32_to_cpu(pkg->seg_offset[i]);
60-
struct ice_generic_seg_hdr *seg;
60+
const struct ice_generic_seg_hdr *seg;
6161

6262
/* segment header must fit */
6363
if (len < off + sizeof(*seg))
6464
return ICE_DDP_PKG_INVALID_FILE;
6565

66-
seg = (struct ice_generic_seg_hdr *)((u8 *)pkg + off);
66+
seg = (void *)pkg + off;
6767

6868
/* segment body must fit */
6969
if (len < off + le32_to_cpu(seg->seg_size))
@@ -119,13 +119,13 @@ static enum ice_ddp_state ice_chk_pkg_version(struct ice_pkg_ver *pkg_ver)
119119
*
120120
* This helper function validates a buffer's header.
121121
*/
122-
static struct ice_buf_hdr *ice_pkg_val_buf(struct ice_buf *buf)
122+
static const struct ice_buf_hdr *ice_pkg_val_buf(const struct ice_buf *buf)
123123
{
124-
struct ice_buf_hdr *hdr;
124+
const struct ice_buf_hdr *hdr;
125125
u16 section_count;
126126
u16 data_end;
127127

128-
hdr = (struct ice_buf_hdr *)buf->buf;
128+
hdr = (const struct ice_buf_hdr *)buf->buf;
129129
/* verify data */
130130
section_count = le16_to_cpu(hdr->section_count);
131131
if (section_count < ICE_MIN_S_COUNT || section_count > ICE_MAX_S_COUNT)
@@ -165,8 +165,8 @@ static struct ice_buf_table *ice_find_buf_table(struct ice_seg *ice_seg)
165165
* unexpected value has been detected (for example an invalid section count or
166166
* an invalid buffer end value).
167167
*/
168-
static struct ice_buf_hdr *ice_pkg_enum_buf(struct ice_seg *ice_seg,
169-
struct ice_pkg_enum *state)
168+
static const struct ice_buf_hdr *ice_pkg_enum_buf(struct ice_seg *ice_seg,
169+
struct ice_pkg_enum *state)
170170
{
171171
if (ice_seg) {
172172
state->buf_table = ice_find_buf_table(ice_seg);
@@ -1800,9 +1800,9 @@ int ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
18001800
* success it returns a pointer to the segment header, otherwise it will
18011801
* return NULL.
18021802
*/
1803-
static struct ice_generic_seg_hdr *
1803+
static const struct ice_generic_seg_hdr *
18041804
ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
1805-
struct ice_pkg_hdr *pkg_hdr)
1805+
const struct ice_pkg_hdr *pkg_hdr)
18061806
{
18071807
u32 i;
18081808

@@ -1813,11 +1813,9 @@ ice_find_seg_in_pkg(struct ice_hw *hw, u32 seg_type,
18131813

18141814
/* Search all package segments for the requested segment type */
18151815
for (i = 0; i < le32_to_cpu(pkg_hdr->seg_count); i++) {
1816-
struct ice_generic_seg_hdr *seg;
1816+
const struct ice_generic_seg_hdr *seg;
18171817

1818-
seg = (struct ice_generic_seg_hdr
1819-
*)((u8 *)pkg_hdr +
1820-
le32_to_cpu(pkg_hdr->seg_offset[i]));
1818+
seg = (void *)pkg_hdr + le32_to_cpu(pkg_hdr->seg_offset[i]);
18211819

18221820
if (le32_to_cpu(seg->seg_type) == seg_type)
18231821
return seg;
@@ -2354,12 +2352,12 @@ ice_get_set_tx_topo(struct ice_hw *hw, u8 *buf, u16 buf_size,
23542352
*
23552353
* Return: zero when update was successful, negative values otherwise.
23562354
*/
2357-
int ice_cfg_tx_topo(struct ice_hw *hw, u8 *buf, u32 len)
2355+
int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len)
23582356
{
2359-
u8 *current_topo, *new_topo = NULL;
2360-
struct ice_run_time_cfg_seg *seg;
2361-
struct ice_buf_hdr *section;
2362-
struct ice_pkg_hdr *pkg_hdr;
2357+
u8 *new_topo = NULL, *topo __free(kfree) = NULL;
2358+
const struct ice_run_time_cfg_seg *seg;
2359+
const struct ice_buf_hdr *section;
2360+
const struct ice_pkg_hdr *pkg_hdr;
23632361
enum ice_ddp_state state;
23642362
u16 offset, size = 0;
23652363
u32 reg = 0;
@@ -2375,15 +2373,13 @@ int ice_cfg_tx_topo(struct ice_hw *hw, u8 *buf, u32 len)
23752373
return -EOPNOTSUPP;
23762374
}
23772375

2378-
current_topo = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
2379-
if (!current_topo)
2376+
topo = kzalloc(ICE_AQ_MAX_BUF_LEN, GFP_KERNEL);
2377+
if (!topo)
23802378
return -ENOMEM;
23812379

2382-
/* Get the current Tx topology */
2383-
status = ice_get_set_tx_topo(hw, current_topo, ICE_AQ_MAX_BUF_LEN, NULL,
2384-
&flags, false);
2385-
2386-
kfree(current_topo);
2380+
/* Get the current Tx topology flags */
2381+
status = ice_get_set_tx_topo(hw, topo, ICE_AQ_MAX_BUF_LEN, NULL, &flags,
2382+
false);
23872383

23882384
if (status) {
23892385
ice_debug(hw, ICE_DBG_INIT, "Get current topology is failed\n");
@@ -2419,7 +2415,7 @@ int ice_cfg_tx_topo(struct ice_hw *hw, u8 *buf, u32 len)
24192415
goto update_topo;
24202416
}
24212417

2422-
pkg_hdr = (struct ice_pkg_hdr *)buf;
2418+
pkg_hdr = (const struct ice_pkg_hdr *)buf;
24232419
state = ice_verify_pkg(pkg_hdr, len);
24242420
if (state) {
24252421
ice_debug(hw, ICE_DBG_INIT, "Failed to verify pkg (err: %d)\n",
@@ -2428,7 +2424,7 @@ int ice_cfg_tx_topo(struct ice_hw *hw, u8 *buf, u32 len)
24282424
}
24292425

24302426
/* Find runtime configuration segment */
2431-
seg = (struct ice_run_time_cfg_seg *)
2427+
seg = (const struct ice_run_time_cfg_seg *)
24322428
ice_find_seg_in_pkg(hw, SEGMENT_TYPE_ICE_RUN_TIME_CFG, pkg_hdr);
24332429
if (!seg) {
24342430
ice_debug(hw, ICE_DBG_INIT, "5 layer topology segment is missing\n");
@@ -2461,8 +2457,10 @@ int ice_cfg_tx_topo(struct ice_hw *hw, u8 *buf, u32 len)
24612457
return -EIO;
24622458
}
24632459

2464-
/* Get the new topology buffer */
2465-
new_topo = ((u8 *)section) + offset;
2460+
/* Get the new topology buffer, reuse current topo copy mem */
2461+
static_assert(ICE_PKG_BUF_SIZE == ICE_AQ_MAX_BUF_LEN);
2462+
new_topo = topo;
2463+
memcpy(new_topo, (u8 *)section + offset, size);
24662464

24672465
update_topo:
24682466
/* Acquire global lock to make sure that set topology issued

drivers/net/ethernet/intel/ice/ice_ddp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ struct ice_pkg_enum {
438438
u32 buf_idx;
439439

440440
u32 type;
441-
struct ice_buf_hdr *buf;
441+
const struct ice_buf_hdr *buf;
442442
u32 sect_idx;
443443
void *sect;
444444
u32 sect_type;
@@ -467,6 +467,6 @@ ice_pkg_enum_entry(struct ice_seg *ice_seg, struct ice_pkg_enum *state,
467467
void *ice_pkg_enum_section(struct ice_seg *ice_seg, struct ice_pkg_enum *state,
468468
u32 sect_type);
469469

470-
int ice_cfg_tx_topo(struct ice_hw *hw, u8 *buf, u32 len);
470+
int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len);
471471

472472
#endif

drivers/net/ethernet/intel/ice/ice_main.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,16 +4536,10 @@ ice_init_tx_topology(struct ice_hw *hw, const struct firmware *firmware)
45364536
u8 num_tx_sched_layers = hw->num_tx_sched_layers;
45374537
struct ice_pf *pf = hw->back;
45384538
struct device *dev;
4539-
u8 *buf_copy;
45404539
int err;
45414540

45424541
dev = ice_pf_to_dev(pf);
4543-
/* ice_cfg_tx_topo buf argument is not a constant,
4544-
* so we have to make a copy
4545-
*/
4546-
buf_copy = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
4547-
4548-
err = ice_cfg_tx_topo(hw, buf_copy, firmware->size);
4542+
err = ice_cfg_tx_topo(hw, firmware->data, firmware->size);
45494543
if (!err) {
45504544
if (hw->num_tx_sched_layers > num_tx_sched_layers)
45514545
dev_info(dev, "Tx scheduling layers switching feature disabled\n");

0 commit comments

Comments
 (0)