nfp: prevent theoretical buffer overrun in nfp_eth_read_ports
authorSimon Horman <simon.horman@netronome.com>
Wed, 8 Mar 2017 16:57:08 +0000 (08:57 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 10 Mar 2017 00:39:58 +0000 (16:39 -0800)
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>
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c

index 10a0c8392d2b4781f2b0c19580687f1bed95ee67..38bd80077e33fe82438a993e333af3162b78acce 100644 (file)
@@ -191,8 +191,7 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
 {
        struct eth_table_entry *entries;
        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);
        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);
        if (ret < 0) {
                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) +
                        sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL);
-       if (!table) {
-               kfree(entries);
-               return NULL;
-       }
+       if (!table)
+               goto err;
 
        table->count = cnt;
        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);
 
        return table;
+
+err:
+       kfree(entries);
+       return NULL;
 }
 
 /**