bnxt_en: Fix memory fault in bnxt_ethtool_init()
In some firmware images, the length of BNX_DIR_TYPE_PKG_LOG nvram type
could be greater than the fixed buffer length of 4096 bytes allocated by
the driver. This was causing HWRM_NVM_READ to copy more data to the buffer
than the allocated size, causing general protection fault.
Fix the issue by allocating the exact buffer length returned by
HWRM_NVM_FIND_DIR_ENTRY, instead of 4096. Move the kzalloc() call
into the bnxt_get_pkgver() function.
Fixes: 3ebf6f0a09
("bnxt_en: Add installed-package firmware version reporting via Ethtool GDRVINFO")
Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0df8bb01cb
commit
a60faa60da
|
@ -1927,22 +1927,39 @@ static char *bnxt_parse_pkglog(int desired_field, u8 *data, size_t datalen)
|
|||
return retval;
|
||||
}
|
||||
|
||||
static char *bnxt_get_pkgver(struct net_device *dev, char *buf, size_t buflen)
|
||||
static void bnxt_get_pkgver(struct net_device *dev)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
u16 index = 0;
|
||||
u32 datalen;
|
||||
char *pkgver;
|
||||
u32 pkglen;
|
||||
u8 *pkgbuf;
|
||||
int len;
|
||||
|
||||
if (bnxt_find_nvram_item(dev, BNX_DIR_TYPE_PKG_LOG,
|
||||
BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE,
|
||||
&index, NULL, &datalen) != 0)
|
||||
return NULL;
|
||||
&index, NULL, &pkglen) != 0)
|
||||
return;
|
||||
|
||||
memset(buf, 0, buflen);
|
||||
if (bnxt_get_nvram_item(dev, index, 0, datalen, buf) != 0)
|
||||
return NULL;
|
||||
pkgbuf = kzalloc(pkglen, GFP_KERNEL);
|
||||
if (!pkgbuf) {
|
||||
dev_err(&bp->pdev->dev, "Unable to allocate memory for pkg version, length = %u\n",
|
||||
pkglen);
|
||||
return;
|
||||
}
|
||||
|
||||
return bnxt_parse_pkglog(BNX_PKG_LOG_FIELD_IDX_PKG_VERSION, buf,
|
||||
datalen);
|
||||
if (bnxt_get_nvram_item(dev, index, 0, pkglen, pkgbuf))
|
||||
goto err;
|
||||
|
||||
pkgver = bnxt_parse_pkglog(BNX_PKG_LOG_FIELD_IDX_PKG_VERSION, pkgbuf,
|
||||
pkglen);
|
||||
if (pkgver && *pkgver != 0 && isdigit(*pkgver)) {
|
||||
len = strlen(bp->fw_ver_str);
|
||||
snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
|
||||
"/pkg %s", pkgver);
|
||||
}
|
||||
err:
|
||||
kfree(pkgbuf);
|
||||
}
|
||||
|
||||
static int bnxt_get_eeprom(struct net_device *dev,
|
||||
|
@ -2615,22 +2632,10 @@ void bnxt_ethtool_init(struct bnxt *bp)
|
|||
struct hwrm_selftest_qlist_input req = {0};
|
||||
struct bnxt_test_info *test_info;
|
||||
struct net_device *dev = bp->dev;
|
||||
char *pkglog;
|
||||
int i, rc;
|
||||
|
||||
pkglog = kzalloc(BNX_PKG_LOG_MAX_LENGTH, GFP_KERNEL);
|
||||
if (pkglog) {
|
||||
char *pkgver;
|
||||
int len;
|
||||
bnxt_get_pkgver(dev);
|
||||
|
||||
pkgver = bnxt_get_pkgver(dev, pkglog, BNX_PKG_LOG_MAX_LENGTH);
|
||||
if (pkgver && *pkgver != 0 && isdigit(*pkgver)) {
|
||||
len = strlen(bp->fw_ver_str);
|
||||
snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
|
||||
"/pkg %s", pkgver);
|
||||
}
|
||||
kfree(pkglog);
|
||||
}
|
||||
if (bp->hwrm_spec_code < 0x10704 || !BNXT_SINGLE_PF(bp))
|
||||
return;
|
||||
|
||||
|
|
|
@ -59,8 +59,6 @@ enum bnxt_nvm_directory_type {
|
|||
#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0)
|
||||
#define BNX_DIR_ATTR_PROP_STREAM (1 << 1)
|
||||
|
||||
#define BNX_PKG_LOG_MAX_LENGTH 4096
|
||||
|
||||
enum bnxnvm_pkglog_field_index {
|
||||
BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0,
|
||||
BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1,
|
||||
|
|
Loading…
Reference in a new issue