net: ethernet: bcmasp: fix possible OOB write in bcmasp_netfilt_get_all_active()
authorHangyu Hua <hbh25y@gmail.com>
Fri, 8 Sep 2023 06:19:48 +0000 (14:19 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 11 Sep 2023 07:26:10 +0000 (08:26 +0100)
rule_locs is allocated in ethtool_get_rxnfc and the size is determined by
rule_cnt from user space. So rule_cnt needs to be check before using
rule_locs to avoid OOB writing or NULL pointer dereference.

Fixes: c5d511c49587 ("net: bcmasp: Add support for wake on net filters")
Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/asp2/bcmasp.c
drivers/net/ethernet/broadcom/asp2/bcmasp.h
drivers/net/ethernet/broadcom/asp2/bcmasp_ethtool.c

index f048e3d..41a6098 100644 (file)
@@ -528,13 +528,16 @@ void bcmasp_netfilt_suspend(struct bcmasp_intf *intf)
                                  ASP_RX_FILTER_BLK_CTRL);
 }
 
-void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
-                                  u32 *rule_cnt)
+int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
+                                 u32 *rule_cnt)
 {
        struct bcmasp_priv *priv = intf->parent;
        int j = 0, i;
 
        for (i = 0; i < NUM_NET_FILTERS; i++) {
+               if (j == *rule_cnt)
+                       return -EMSGSIZE;
+
                if (!priv->net_filters[i].claimed ||
                    priv->net_filters[i].port != intf->port)
                        continue;
@@ -548,6 +551,8 @@ void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
        }
 
        *rule_cnt = j;
+
+       return 0;
 }
 
 int bcmasp_netfilt_get_active(struct bcmasp_intf *intf)
index 5b512f7..ec90add 100644 (file)
@@ -577,8 +577,8 @@ void bcmasp_netfilt_release(struct bcmasp_intf *intf,
 
 int bcmasp_netfilt_get_active(struct bcmasp_intf *intf);
 
-void bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
-                                  u32 *rule_cnt);
+int bcmasp_netfilt_get_all_active(struct bcmasp_intf *intf, u32 *rule_locs,
+                                 u32 *rule_cnt);
 
 void bcmasp_netfilt_suspend(struct bcmasp_intf *intf);
 
index c4f1604..ce6a3d5 100644 (file)
@@ -335,7 +335,7 @@ static int bcmasp_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
                err = bcmasp_flow_get(intf, cmd);
                break;
        case ETHTOOL_GRXCLSRLALL:
-               bcmasp_netfilt_get_all_active(intf, rule_locs, &cmd->rule_cnt);
+               err = bcmasp_netfilt_get_all_active(intf, rule_locs, &cmd->rule_cnt);
                cmd->data = NUM_NET_FILTERS;
                break;
        default: