Commit a60faa60 authored by Vasundhara Volam's avatar Vasundhara Volam Committed by David S. Miller

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: 3ebf6f0a ("bnxt_en: Add installed-package firmware version reporting via Ethtool GDRVINFO")
Signed-off-by: default avatarVasundhara Volam <vasundhara-v.volam@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0df8bb01
...@@ -1927,22 +1927,39 @@ static char *bnxt_parse_pkglog(int desired_field, u8 *data, size_t datalen) ...@@ -1927,22 +1927,39 @@ static char *bnxt_parse_pkglog(int desired_field, u8 *data, size_t datalen)
return retval; 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; u16 index = 0;
u32 datalen; char *pkgver;
u32 pkglen;
u8 *pkgbuf;
int len;
if (bnxt_find_nvram_item(dev, BNX_DIR_TYPE_PKG_LOG, if (bnxt_find_nvram_item(dev, BNX_DIR_TYPE_PKG_LOG,
BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE, BNX_DIR_ORDINAL_FIRST, BNX_DIR_EXT_NONE,
&index, NULL, &datalen) != 0) &index, NULL, &pkglen) != 0)
return NULL; return;
memset(buf, 0, buflen); pkgbuf = kzalloc(pkglen, GFP_KERNEL);
if (bnxt_get_nvram_item(dev, index, 0, datalen, buf) != 0) if (!pkgbuf) {
return NULL; dev_err(&bp->pdev->dev, "Unable to allocate memory for pkg version, length = %u\n",
pkglen);
return;
}
if (bnxt_get_nvram_item(dev, index, 0, pkglen, pkgbuf))
goto err;
return bnxt_parse_pkglog(BNX_PKG_LOG_FIELD_IDX_PKG_VERSION, buf, pkgver = bnxt_parse_pkglog(BNX_PKG_LOG_FIELD_IDX_PKG_VERSION, pkgbuf,
datalen); 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, static int bnxt_get_eeprom(struct net_device *dev,
...@@ -2615,22 +2632,10 @@ void bnxt_ethtool_init(struct bnxt *bp) ...@@ -2615,22 +2632,10 @@ void bnxt_ethtool_init(struct bnxt *bp)
struct hwrm_selftest_qlist_input req = {0}; struct hwrm_selftest_qlist_input req = {0};
struct bnxt_test_info *test_info; struct bnxt_test_info *test_info;
struct net_device *dev = bp->dev; struct net_device *dev = bp->dev;
char *pkglog;
int i, rc; int i, rc;
pkglog = kzalloc(BNX_PKG_LOG_MAX_LENGTH, GFP_KERNEL); bnxt_get_pkgver(dev);
if (pkglog) {
char *pkgver;
int len;
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)) if (bp->hwrm_spec_code < 0x10704 || !BNXT_SINGLE_PF(bp))
return; return;
......
...@@ -59,8 +59,6 @@ enum bnxt_nvm_directory_type { ...@@ -59,8 +59,6 @@ enum bnxt_nvm_directory_type {
#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0) #define BNX_DIR_ATTR_NO_CHKSUM (1 << 0)
#define BNX_DIR_ATTR_PROP_STREAM (1 << 1) #define BNX_DIR_ATTR_PROP_STREAM (1 << 1)
#define BNX_PKG_LOG_MAX_LENGTH 4096
enum bnxnvm_pkglog_field_index { enum bnxnvm_pkglog_field_index {
BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0,
BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment