net: ar8216: address security vulnerabilities in swconfig & ar8216

Imported from e1aaf7ec00%5E%21/#F0
Signed-off-by: Pavel Kubelun <be.dissent@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@codeaurora.org>
Reviewed-on: https://chromium-review.googlesource.com/236490
Reviewed-by: Toshi Kikuchi <toshik@chromium.org>
Commit-Queue: Toshi Kikuchi <toshik@chromium.org>
Tested-by: Toshi Kikuchi <toshik@chromium.org>
master
Pavel Kubelun 8 years ago committed by John Crispin
parent a3454d1929
commit 5a69f59602
  1. 21
      target/linux/generic/files/drivers/net/phy/ar8216.c
  2. 12
      target/linux/generic/files/drivers/net/phy/swconfig.c
  3. 12
      target/linux/generic/files/include/linux/switch.h

@ -536,7 +536,7 @@ ar8216_mangle_rx(struct net_device *dev, struct sk_buff *skb)
if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00)) if ((buf[12 + 2] != 0x81) || (buf[13 + 2] != 0x00))
return; return;
port = buf[0] & 0xf; port = buf[0] & 0x7;
/* no need to fix up packets coming from a tagged source */ /* no need to fix up packets coming from a tagged source */
if (priv->vlan_tagged & (1 << port)) 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 */ /* 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; return -EINVAL;
priv->pvid[port] = vlan; priv->pvid[port] = vlan;
@ -960,6 +961,10 @@ int
ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan) ar8xxx_sw_get_pvid(struct switch_dev *dev, int port, int *vlan)
{ {
struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
if (port < 0 || port >= AR8X16_MAX_PORTS)
return -EINVAL;
*vlan = priv->pvid[port]; *vlan = priv->pvid[port];
return 0; return 0;
} }
@ -969,6 +974,10 @@ ar8xxx_sw_set_vid(struct switch_dev *dev, const struct switch_attr *attr,
struct switch_val *val) struct switch_val *val)
{ {
struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); 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; priv->vlan_id[val->port_vlan] = val->value.i;
return 0; return 0;
} }
@ -996,9 +1005,13 @@ static int
ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val) ar8xxx_sw_get_ports(struct switch_dev *dev, struct switch_val *val)
{ {
struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev); struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
u8 ports = priv->vlan_table[val->port_vlan]; u8 ports;
int i; int i;
if (val->port_vlan >= AR8X16_MAX_VLANS)
return -EINVAL;
ports = priv->vlan_table[val->port_vlan];
val->len = 0; val->len = 0;
for (i = 0; i < dev->ports; i++) { for (i = 0; i < dev->ports; i++) {
struct switch_port *p; 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); struct ar8xxx_priv *priv = swdev_to_ar8xxx(dev);
const struct ar8xxx_chip *chip = priv->chip; const struct ar8xxx_chip *chip = priv->chip;
u64 *mib_stats, mib_data; u64 *mib_stats, mib_data;
int port; unsigned int port;
int ret; int ret;
char *buf = priv->buf; char *buf = priv->buf;
char buf1[64]; char buf1[64];

@ -506,7 +506,7 @@ swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
struct genlmsghdr *hdr = nlmsg_data(info->nlhdr); struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
const struct switch_attrlist *alist; const struct switch_attrlist *alist;
const struct switch_attr *attr = NULL; const struct switch_attr *attr = NULL;
int attr_id; unsigned int attr_id;
/* defaults */ /* defaults */
struct switch_attr *def_list; struct switch_attr *def_list;
@ -590,11 +590,13 @@ swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,
val->len = 0; val->len = 0;
nla_for_each_nested(nla, head, rem) { nla_for_each_nested(nla, head, rem) {
struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1]; 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) if (val->len >= max)
return -EINVAL; return -EINVAL;
port = &val->value.ports[val->len];
if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla, if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,
port_policy)) port_policy))
return -EINVAL; return -EINVAL;
@ -1111,6 +1113,11 @@ register_switch(struct switch_dev *dev, struct net_device *netdev)
} }
BUG_ON(!dev->alias); BUG_ON(!dev->alias);
/* Make sure swdev_id doesn't overflow */
if (swdev_id == INT_MAX) {
return -ENOMEM;
}
if (dev->ports > 0) { if (dev->ports > 0) {
dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->portbuf = kzalloc(sizeof(struct switch_port) *
dev->ports, GFP_KERNEL); dev->ports, GFP_KERNEL);
@ -1227,4 +1234,3 @@ swconfig_exit(void)
module_init(swconfig_init); module_init(swconfig_init);
module_exit(swconfig_exit); module_exit(swconfig_exit);

@ -115,12 +115,12 @@ struct switch_dev {
const char *alias; const char *alias;
struct net_device *netdev; struct net_device *netdev;
int ports; unsigned int ports;
int vlans; unsigned int vlans;
int cpu_port; unsigned int cpu_port;
/* the following fields are internal for swconfig */ /* the following fields are internal for swconfig */
int id; unsigned int id;
struct list_head dev_list; struct list_head dev_list;
unsigned long def_global, def_port, def_vlan; unsigned long def_global, def_port, def_vlan;
@ -148,8 +148,8 @@ struct switch_portmap {
struct switch_val { struct switch_val {
const struct switch_attr *attr; const struct switch_attr *attr;
int port_vlan; unsigned int port_vlan;
int len; unsigned int len;
union { union {
const char *s; const char *s;
u32 i; u32 i;

Loading…
Cancel
Save