Commit 5692dbb5 authored by Simon Horman's avatar Simon Horman Committed by David S. Miller

nfp: prevent theoretical buffer overrun in nfp_eth_read_ports

Prevent theoretical buffer overrun by returning an error if
the number of entries returned by the firmware does not match those
present.

Also use a common handling error path.

Found by inspection.
Signed-off-by: default avatarSimon Horman <simon.horman@netronome.com>
Tested-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9dcf88a
...@@ -191,8 +191,7 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) ...@@ -191,8 +191,7 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
{ {
struct eth_table_entry *entries; struct eth_table_entry *entries;
struct nfp_eth_table *table; struct nfp_eth_table *table;
unsigned int cnt; int i, j, ret, cnt = 0;
int i, j, ret;
entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
if (!entries) if (!entries)
...@@ -201,24 +200,27 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) ...@@ -201,24 +200,27 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
if (ret < 0) { if (ret < 0) {
nfp_err(cpp, "reading port table failed %d\n", ret); nfp_err(cpp, "reading port table failed %d\n", ret);
kfree(entries); goto err;
return NULL;
} }
/* Some versions of flash will give us 0 instead of port count */
cnt = ret;
if (!cnt) {
for (i = 0; i < NSP_ETH_MAX_COUNT; i++) for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
if (entries[i].port & NSP_ETH_PORT_LANES_MASK) if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
cnt++; cnt++;
/* Some versions of flash will give us 0 instead of port count.
* For those that give a port count, verify it against the value
* calculated above.
*/
if (ret && ret != cnt) {
nfp_err(cpp, "table entry count reported (%d) does not match entries present (%d)\n",
ret, cnt);
goto err;
} }
table = kzalloc(sizeof(*table) + table = kzalloc(sizeof(*table) +
sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL); sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL);
if (!table) { if (!table)
kfree(entries); goto err;
return NULL;
}
table->count = cnt; table->count = cnt;
for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++) for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
...@@ -231,6 +233,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) ...@@ -231,6 +233,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
kfree(entries); kfree(entries);
return table; return table;
err:
kfree(entries);
return NULL;
} }
/** /**
......
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