Skip to content

Commit c74751f

Browse files
Vasundhara Volamdavem330
Vasundhara Volam
authored andcommitted
bnxt_en: Return error if FW returns more data than dump length
If any change happened in the configuration of VF in VM while collecting live dump, there could be a race and firmware can return more data than allocated dump length. Fix it by keeping track of the accumulated core dump length copied so far and abort the copy with error code if the next chunk of core dump will exceed the original dump length. Fixes: 6c5657d ("bnxt_en: Add support for ethtool get dump.") Signed-off-by: Vasundhara Volam <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 325f85f commit c74751f

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3071,8 +3071,15 @@ static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, int msg_len,
30713071
}
30723072
}
30733073

3074-
if (info->dest_buf)
3075-
memcpy(info->dest_buf + off, dma_buf, len);
3074+
if (info->dest_buf) {
3075+
if ((info->seg_start + off + len) <=
3076+
BNXT_COREDUMP_BUF_LEN(info->buf_len)) {
3077+
memcpy(info->dest_buf + off, dma_buf, len);
3078+
} else {
3079+
rc = -ENOBUFS;
3080+
break;
3081+
}
3082+
}
30763083

30773084
if (cmn_req->req_type ==
30783085
cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE))
@@ -3126,7 +3133,7 @@ static int bnxt_hwrm_dbg_coredump_initiate(struct bnxt *bp, u16 component_id,
31263133

31273134
static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id,
31283135
u16 segment_id, u32 *seg_len,
3129-
void *buf, u32 offset)
3136+
void *buf, u32 buf_len, u32 offset)
31303137
{
31313138
struct hwrm_dbg_coredump_retrieve_input req = {0};
31323139
struct bnxt_hwrm_dbg_dma_info info = {NULL};
@@ -3141,8 +3148,11 @@ static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id,
31413148
seq_no);
31423149
info.data_len_off = offsetof(struct hwrm_dbg_coredump_retrieve_output,
31433150
data_len);
3144-
if (buf)
3151+
if (buf) {
31453152
info.dest_buf = buf + offset;
3153+
info.buf_len = buf_len;
3154+
info.seg_start = offset;
3155+
}
31463156

31473157
rc = bnxt_hwrm_dbg_dma_data(bp, &req, sizeof(req), &info);
31483158
if (!rc)
@@ -3232,14 +3242,17 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record,
32323242
static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
32333243
{
32343244
u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output);
3245+
u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0;
32353246
struct coredump_segment_record *seg_record = NULL;
3236-
u32 offset = 0, seg_hdr_len, seg_record_len;
32373247
struct bnxt_coredump_segment_hdr seg_hdr;
32383248
struct bnxt_coredump coredump = {NULL};
32393249
time64_t start_time;
32403250
u16 start_utc;
32413251
int rc = 0, i;
32423252

3253+
if (buf)
3254+
buf_len = *dump_len;
3255+
32433256
start_time = ktime_get_real_seconds();
32443257
start_utc = sys_tz.tz_minuteswest * 60;
32453258
seg_hdr_len = sizeof(seg_hdr);
@@ -3272,6 +3285,12 @@ static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
32723285
u32 duration = 0, seg_len = 0;
32733286
unsigned long start, end;
32743287

3288+
if (buf && ((offset + seg_hdr_len) >
3289+
BNXT_COREDUMP_BUF_LEN(buf_len))) {
3290+
rc = -ENOBUFS;
3291+
goto err;
3292+
}
3293+
32753294
start = jiffies;
32763295

32773296
rc = bnxt_hwrm_dbg_coredump_initiate(bp, comp_id, seg_id);
@@ -3284,9 +3303,11 @@ static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
32843303

32853304
/* Write segment data into the buffer */
32863305
rc = bnxt_hwrm_dbg_coredump_retrieve(bp, comp_id, seg_id,
3287-
&seg_len, buf,
3306+
&seg_len, buf, buf_len,
32883307
offset + seg_hdr_len);
3289-
if (rc)
3308+
if (rc && rc == -ENOBUFS)
3309+
goto err;
3310+
else if (rc)
32903311
netdev_err(bp->dev,
32913312
"Failed to retrieve coredump for seg = %d\n",
32923313
seg_record->segment_id);
@@ -3316,7 +3337,8 @@ static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
33163337
rc);
33173338
kfree(coredump.data);
33183339
*dump_len += sizeof(struct bnxt_coredump_record);
3319-
3340+
if (rc == -ENOBUFS)
3341+
netdev_err(bp->dev, "Firmware returned large coredump buffer");
33203342
return rc;
33213343
}
33223344

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ struct bnxt_coredump {
3131
u16 total_segs;
3232
};
3333

34+
#define BNXT_COREDUMP_BUF_LEN(len) ((len) - sizeof(struct bnxt_coredump_record))
35+
3436
struct bnxt_hwrm_dbg_dma_info {
3537
void *dest_buf;
3638
int dest_buf_size;
3739
u16 dma_len;
3840
u16 seq_off;
3941
u16 data_len_off;
4042
u16 segs;
43+
u32 seg_start;
44+
u32 buf_len;
4145
};
4246

4347
struct hwrm_dbg_cmn_input {

0 commit comments

Comments
 (0)