[source] net: ar8216: address security vulnerabilities in swconfig & ar8216

LEDE Commits lede-commits at lists.infradead.org
Thu Dec 1 06:47:59 PST 2016


blogic pushed a commit to source.git, branch master:
https://git.lede-project.org/5a69f596027ff45d9daf7c6584a8a9d4f7ea0770

commit 5a69f596027ff45d9daf7c6584a8a9d4f7ea0770
Author: Pavel Kubelun <be.dissent at gmail.com>
AuthorDate: Mon Nov 28 18:10:05 2016 +0300

    net: ar8216: address security vulnerabilities in swconfig & ar8216
    
    Imported from https://chromium.googlesource.com/chromiumos/third_party/kernel/+/e1aaf7ec008a97311867f0a7d0418e4693fecfd4%5E%21/#F0
    Signed-off-by: Pavel Kubelun <be.dissent at gmail.com>
    
    CHROMIUM: net: ar8216: address security vulnerabilities in swconfig & ar8216
    
    This patch does the following changes:
    *address the security vulnerabilities in both swconfig framework and in
     ar8216 driver (many bound check additions, and turned swconfig structure
     signed element into unsigned when applicable)
    *address a couple of whitespaces and indendation issues
    
    BUG=chrome-os-partner:33096
    TEST=none
    
    Change-Id: I94ea78fcce8c1932cc584d1508c6e3b5dfb93ce9
    Signed-off-by: Mathieu Olivari <mathieu at codeaurora.org>
    Reviewed-on: https://chromium-review.googlesource.com/236490
    Reviewed-by: Toshi Kikuchi <toshik at chromium.org>
    Commit-Queue: Toshi Kikuchi <toshik at chromium.org>
    Tested-by: Toshi Kikuchi <toshik at chromium.org>
---
 target/linux/generic/files/drivers/net/phy/ar8216.c | 21 +++++++++++++++++----
 .../linux/generic/files/drivers/net/phy/swconfig.c  | 12 +++++++++---
 target/linux/generic/files/include/linux/switch.h   | 12 ++++++------
 3 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c
index 6c670dd..746d8e6 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -536,7 +536,7 @@ ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb)
 	if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00))
 		return;
 
-	port = buf[0] & 0xf;
+	port = buf[0] & 0x7;
 
 	/* no need to fix up packets coming from a tagged source */
 	if (priv->vlan_tagged & (1 << port))
@@ -949,7 +949,8 @@ ar8xxx_sw_set_pvid(struct switch_dev *dev, int port, int vlan)
 
 	/* make sure no invalid PVIDs get set */
 
-	if (vlan >= dev->vlans)
+	if (vlan < 0 || vlan >= dev->vlans ||
+	    port < 0 || port >= AR8X16_MAX_PORTS)
 		return -EINVAL;
 
 	priv->pvid[port] = vlan;
@@ -960,6 +961,10 @@ int
 ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan)
 {
 	struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
+
+	if (port < 0 || port >= AR8X16_MAX_PORTS)
+		return -EINVAL;
+
 	*vlan = priv->pvid[port];
 	return 0;
 }
@@ -969,6 +974,10 @@ ar8xxx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
 		  struct switch_val *val)
 {
 	struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
+
+	if (val->port_vlan >= AR8X16_MAX_PORTS)
+		return -EINVAL;
+
 	priv->vlan_id[val->port_vlan] = val->value.i;
 	return 0;
 }
@@ -996,9 +1005,13 @@ static int
 ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val)
 {
 	struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
-	u8 ports = priv->vlan_table[val->port_vlan];
+	u8 ports;
 	int i;
 
+	if (val->port_vlan >= AR8X16_MAX_VLANS)
+		return -EINVAL;
+
+	ports = priv->vlan_table[val->port_vlan];
 	val->len = 0;
 	for (i = 0; i < dev->ports; i++) {
 		struct switch_port *p;
@@ -1378,7 +1391,7 @@ ar8xxx_sw_get_port_mib(struct switch_dev *dev,
 	struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
 	const struct ar8xxx_chip *chip = priv->chip;
 	u64 *mib_stats, mib_data;
-	int port;
+	unsigned int port;
 	int ret;
 	char *buf = priv->buf;
 	char buf1[64];
diff --git a/target/linux/generic/files/drivers/net/phy/swconfig.c b/target/linux/generic/files/drivers/net/phy/swconfig.c
index c70ca74..63a9588 100644
--- a/target/linux/generic/files/drivers/net/phy/swconfig.c
+++ b/target/linux/generic/files/drivers/net/phy/swconfig.c
@@ -506,7 +506,7 @@ swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
 	struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
 	const struct switch_attrlist *alist;
 	const struct switch_attr *attr = NULL;
-	int attr_id;
+	unsigned int attr_id;
 
 	/* defaults */
 	struct switch_attr *def_list;
@@ -590,11 +590,13 @@ swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,
 	val->len = 0;
 	nla_for_each_nested(nla, head, rem) {
 		struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
-		struct switch_port *port = &val->value.ports[val->len];
+		struct switch_port *port;
 
 		if (val->len >= max)
 			return -EINVAL;
 
+		port = &val->value.ports[val->len];
+
 		if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,
 				port_policy))
 			return -EINVAL;
@@ -1111,6 +1113,11 @@ register_switch(struct switch_dev *dev, struct net_device *netdev)
 	}
 	BUG_ON(!dev->alias);
 
+	/* Make sure swdev_id doesn't overflow */
+	if (swdev_id == INT_MAX) {
+		return -ENOMEM;
+	}
+
 	if (dev->ports > 0) {
 		dev->portbuf = kzalloc(sizeof(struct switch_port) *
 				dev->ports, GFP_KERNEL);
@@ -1227,4 +1234,3 @@ swconfig_exit(void)
 
 module_init(swconfig_init);
 module_exit(swconfig_exit);
-
diff --git a/target/linux/generic/files/include/linux/switch.h b/target/linux/generic/files/include/linux/switch.h
index dda4820..f8380b9 100644
--- a/target/linux/generic/files/include/linux/switch.h
+++ b/target/linux/generic/files/include/linux/switch.h
@@ -115,12 +115,12 @@ struct switch_dev {
 	const char *alias;
 	struct net_device *netdev;
 
-	int ports;
-	int vlans;
-	int cpu_port;
+	unsigned int ports;
+	unsigned int vlans;
+	unsigned int cpu_port;
 
 	/* the following fields are internal for swconfig */
-	int id;
+	unsigned int id;
 	struct list_head dev_list;
 	unsigned long def_global, def_port, def_vlan;
 
@@ -148,8 +148,8 @@ struct switch_portmap {
 
 struct switch_val {
 	const struct switch_attr *attr;
-	int port_vlan;
-	int len;
+	unsigned int port_vlan;
+	unsigned int len;
 	union {
 		const char *s;
 		u32 i;



More information about the lede-commits mailing list