Browse Source

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: Simon Horman <simon.horman@netronome.com>
Tested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Simon Horman 8 years ago
parent
commit
5692dbb56e
1 changed files with 20 additions and 14 deletions
  1. 20 14
      drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c

+ 20 - 14
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c

@@ -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;
+	int i, j, ret, cnt = 0;
 
 
 	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)
 	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);
-		return NULL;
+		goto err;
 	}
 	}
 
 
-	/* 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++)
-			if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
-				cnt++;
+	for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
+		if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
+			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) {
-		kfree(entries);
-		return NULL;
-	}
+	if (!table)
+		goto err;
 
 
 	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)
 	kfree(entries);
 	kfree(entries);
 
 
 	return table;
 	return table;
+
+err:
+	kfree(entries);
+	return NULL;
 }
 }
 
 
 /**
 /**