=======================================================================
This patch validates the ethtool autoneg parameter before relaying it on
to the driver's set_settings() function. All implementers of
set_settings have been audited and redundant checks have been removed.
---
drivers/net/arm/etherh.c | 10 ++--------
drivers/net/cassini.c | 4 ----
drivers/net/forcedeth.c | 4 +---
drivers/net/ibm_newemac/core.c | 2 --
drivers/net/mii.c | 2 --
drivers/net/natsemi.c | 4 +---
drivers/net/phy/phy.c | 3 ---
drivers/net/r8169.c | 7 +++----
drivers/net/sc92031.c | 2 --
drivers/net/sungem.c | 4 ----
drivers/net/sunhme.c | 3 ---
drivers/net/tulip/de2104x.c | 2 --
net/core/ethtool.c | 3 +++
13 files changed, 10 insertions(+), 40 deletions(-)
@@ -601,12 +601,9 @@ static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- switch (cmd->autoneg) {
- case AUTONEG_ENABLE:
+ if (cmd->autoneg == AUTONEG_ENABLE)
dev->flags |= IFF_AUTOMEDIA;
- break;
-
- case AUTONEG_DISABLE:
+ else {
switch (cmd->port) {
case PORT_TP:
dev->if_port = IF_PORT_10BASET;
@@ -621,9 +618,6 @@ static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
}
dev->flags &= ~IFF_AUTOMEDIA;
break;
-
- default:
- return -EINVAL;
}
etherh_setif(dev);
@@ -4725,10 +4725,6 @@ static int cas_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
unsigned long flags;
/* Verify the settings we care about. */
- if (cmd->autoneg != AUTONEG_ENABLE &&
- cmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
-
if (cmd->autoneg == AUTONEG_DISABLE &&
((cmd->speed != SPEED_1000 &&
cmd->speed != SPEED_100 &&
@@ -4268,7 +4268,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
if ((ecmd->advertising & mask) == 0)
return -EINVAL;
- } else if (ecmd->autoneg == AUTONEG_DISABLE) {
+ } else {
/* Note: autonegotiation disable, speed 1000 intentionally
* forbidden - noone should need that. */
@@ -4276,8 +4276,6 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EINVAL;
if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
return -EINVAL;
- } else {
- return -EINVAL;
}
netif_carrier_off(dev);
@@ -1960,8 +1960,6 @@ static int emac_ethtool_set_settings(struct net_device *ndev,
/* Basic sanity checks */
if (dev->phy.address < 0)
return -EOPNOTSUPP;
- if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
return -EINVAL;
if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
@@ -144,8 +144,6 @@ int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
return -EINVAL;
if (ecmd->phy_address != mii->phy_id)
return -EINVAL;
- if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
- return -EINVAL;
if ((ecmd->speed == SPEED_1000) && (!mii->supports_gmii))
return -EINVAL;
@@ -2903,13 +2903,11 @@ static int netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
ADVERTISED_100baseT_Full)) == 0) {
return -EINVAL;
}
- } else if (ecmd->autoneg == AUTONEG_DISABLE) {
+ } else {
if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
return -EINVAL;
if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
return -EINVAL;
- } else {
- return -EINVAL;
}
/*
@@ -248,9 +248,6 @@ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd)
cmd->advertising &= phydev->supported;
/* Verify the settings we care about. */
- if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
-
if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
return -EINVAL;
@@ -805,11 +805,10 @@ static int rtl8169_set_speed_tbi(struct net_device *dev,
u32 reg;
reg = RTL_R32(TBICSR);
- if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) &&
- (duplex == DUPLEX_FULL)) {
- RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
- } else if (autoneg == AUTONEG_ENABLE)
+ if (autoneg == AUTONEG_ENABLE)
RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
+ else if (speed == SPEED_1000 && duplex == DUPLEX_FULL)
+ RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart));
else {
if (netif_msg_link(tp)) {
printk(KERN_WARNING "%s: "
@@ -1207,8 +1207,6 @@ static int sc92031_ethtool_set_settings(struct net_device *dev,
return -EINVAL;
if (!(cmd->transceiver == XCVR_INTERNAL))
return -EINVAL;
- if (!(cmd->autoneg == AUTONEG_DISABLE || cmd->autoneg == AUTONEG_ENABLE))
- return -EINVAL;
if (cmd->autoneg == AUTONEG_ENABLE) {
if (!(cmd->advertising & (ADVERTISED_Autoneg
@@ -2690,10 +2690,6 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct gem *gp = netdev_priv(dev);
/* Verify the settings we care about. */
- if (cmd->autoneg != AUTONEG_ENABLE &&
- cmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
-
if (cmd->autoneg == AUTONEG_ENABLE &&
cmd->advertising == 0)
return -EINVAL;
@@ -2448,9 +2448,6 @@ static int hme_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
struct happy_meal *hp = netdev_priv(dev);
/* Verify the settings we care about. */
- if (cmd->autoneg != AUTONEG_ENABLE &&
- cmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
if (cmd->autoneg == AUTONEG_DISABLE &&
((cmd->speed != SPEED_100 &&
cmd->speed != SPEED_10) ||
@@ -1520,8 +1520,6 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd)
return -EINVAL;
if (ecmd->transceiver != XCVR_INTERNAL)
return -EINVAL;
- if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
- return -EINVAL;
if (ecmd->advertising & ~de->media_supported)
return -EINVAL;
if (ecmd->autoneg == AUTONEG_ENABLE &&
@@ -164,6 +164,9 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr)
if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
return -EFAULT;
+ if (cmd.autoneg != AUTONEG_ENABLE && cmd.autoneg != AUTONEG_DISABLE)
+ return -EFAULT;
+
return dev->ethtool_ops->set_settings(dev, &cmd);
}