Skip to content

Commit 43544b4

Browse files
pkitszelgregkh
authored andcommitted
ice: fix memleak in ice_init_tx_topology()
[ Upstream commit c188afd ] 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]> Signed-off-by: Sasha Levin <[email protected]>
1 parent d35f2ae commit 43544b4

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
@@ -430,7 +430,7 @@ struct ice_pkg_enum {
430430
u32 buf_idx;
431431

432432
u32 type;
433-
struct ice_buf_hdr *buf;
433+
const struct ice_buf_hdr *buf;
434434
u32 sect_idx;
435435
void *sect;
436436
u32 sect_type;
@@ -454,6 +454,6 @@ u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld);
454454
void *ice_pkg_enum_section(struct ice_seg *ice_seg, struct ice_pkg_enum *state,
455455
u32 sect_type);
456456

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

459459
#endif

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4548,16 +4548,10 @@ ice_init_tx_topology(struct ice_hw *hw, const struct firmware *firmware)
45484548
u8 num_tx_sched_layers = hw->num_tx_sched_layers;
45494549
struct ice_pf *pf = hw->back;
45504550
struct device *dev;
4551-
u8 *buf_copy;
45524551
int err;
45534552

45544553
dev = ice_pf_to_dev(pf);
4555-
/* ice_cfg_tx_topo buf argument is not a constant,
4556-
* so we have to make a copy
4557-
*/
4558-
buf_copy = kmemdup(firmware->data, firmware->size, GFP_KERNEL);
4559-
4560-
err = ice_cfg_tx_topo(hw, buf_copy, firmware->size);
4554+
err = ice_cfg_tx_topo(hw, firmware->data, firmware->size);
45614555
if (!err) {
45624556
if (hw->num_tx_sched_layers > num_tx_sched_layers)
45634557
dev_info(dev, "Tx scheduling layers switching feature disabled\n");

0 commit comments

Comments
 (0)