From: Greg Kroah-Hartman Date: Wed, 28 Jul 2010 23:14:55 +0000 (-0700) Subject: .33 patch X-Git-Tag: v2.6.27.49~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=811a6a938e29593a2ccff9f81aa10f8e9a6bfe25;p=thirdparty%2Fkernel%2Fstable-queue.git .33 patch --- diff --git a/queue-2.6.33/ethtool-fix-potential-user-buffer-overflow-for-ethtool_-g-s-rxfh.patch b/queue-2.6.33/ethtool-fix-potential-user-buffer-overflow-for-ethtool_-g-s-rxfh.patch new file mode 100644 index 00000000000..b4f81850244 --- /dev/null +++ b/queue-2.6.33/ethtool-fix-potential-user-buffer-overflow-for-ethtool_-g-s-rxfh.patch @@ -0,0 +1,120 @@ +From 1adf5345186a99f08ef026bbb3337205802706a1 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Wed, 28 Jul 2010 23:53:47 +0100 +Subject: ethtool: Fix potential user buffer overflow for ETHTOOL_{G, S}RXFH + +commit bf988435bd5b53529f4408a8efb1f433f6ddfda9 upstream. + +struct ethtool_rxnfc was originally defined in 2.6.27 for the +ETHTOOL_{G,S}RXFH command with only the cmd, flow_type and data +fields. It was then extended in 2.6.30 to support various additional +commands. These commands should have been defined to use a new +structure, but it is too late to change that now. + +Since user-space may still be using the old structure definition +for the ETHTOOL_{G,S}RXFH commands, and since they do not need the +additional fields, only copy the originally defined fields to and +from user-space. + +Signed-off-by: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/ethtool.h | 2 ++ + net/core/ethtool.c | 38 +++++++++++++++++++++++++++++--------- + 2 files changed, 31 insertions(+), 9 deletions(-) + +--- a/include/linux/ethtool.h ++++ b/include/linux/ethtool.h +@@ -358,6 +358,8 @@ struct ethtool_rxnfc { + __u32 flow_type; + /* The rx flow hash value or the rule DB size */ + __u64 data; ++ /* The following fields are not valid and must not be used for ++ * the ETHTOOL_{G,X}RXFH commands. */ + struct ethtool_rx_flow_spec fs; + __u32 rule_cnt; + __u32 rule_locs[0]; +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -209,22 +209,34 @@ static int ethtool_get_drvinfo(struct ne + return 0; + } + +-static int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) ++static int ethtool_set_rxnfc(struct net_device *dev, ++ u32 cmd, void __user *useraddr) + { +- struct ethtool_rxnfc cmd; ++ struct ethtool_rxnfc info; ++ size_t info_size = sizeof(info); + + if (!dev->ethtool_ops->set_rxnfc) + return -EOPNOTSUPP; + +- if (copy_from_user(&cmd, useraddr, sizeof(cmd))) ++ /* struct ethtool_rxnfc was originally defined for ++ * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data ++ * members. User-space might still be using that ++ * definition. */ ++ if (cmd == ETHTOOL_SRXFH) ++ info_size = (offsetof(struct ethtool_rxnfc, data) + ++ sizeof(info.data)); ++ ++ if (copy_from_user(&info, useraddr, info_size)) + return -EFAULT; + +- return dev->ethtool_ops->set_rxnfc(dev, &cmd); ++ return dev->ethtool_ops->set_rxnfc(dev, &info); + } + +-static int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) ++static int ethtool_get_rxnfc(struct net_device *dev, ++ u32 cmd, void __user *useraddr) + { + struct ethtool_rxnfc info; ++ size_t info_size = sizeof(info); + const struct ethtool_ops *ops = dev->ethtool_ops; + int ret; + void *rule_buf = NULL; +@@ -232,7 +244,15 @@ static int ethtool_get_rxnfc(struct net_ + if (!ops->get_rxnfc) + return -EOPNOTSUPP; + +- if (copy_from_user(&info, useraddr, sizeof(info))) ++ /* struct ethtool_rxnfc was originally defined for ++ * ETHTOOL_{G,S}RXFH with only the cmd, flow_type and data ++ * members. User-space might still be using that ++ * definition. */ ++ if (cmd == ETHTOOL_GRXFH) ++ info_size = (offsetof(struct ethtool_rxnfc, data) + ++ sizeof(info.data)); ++ ++ if (copy_from_user(&info, useraddr, info_size)) + return -EFAULT; + + if (info.cmd == ETHTOOL_GRXCLSRLALL) { +@@ -250,7 +270,7 @@ static int ethtool_get_rxnfc(struct net_ + goto err_out; + + ret = -EFAULT; +- if (copy_to_user(useraddr, &info, sizeof(info))) ++ if (copy_to_user(useraddr, &info, info_size)) + goto err_out; + + if (rule_buf) { +@@ -1095,12 +1115,12 @@ int dev_ethtool(struct net *net, struct + case ETHTOOL_GRXCLSRLCNT: + case ETHTOOL_GRXCLSRULE: + case ETHTOOL_GRXCLSRLALL: +- rc = ethtool_get_rxnfc(dev, useraddr); ++ rc = ethtool_get_rxnfc(dev, ethcmd, useraddr); + break; + case ETHTOOL_SRXFH: + case ETHTOOL_SRXCLSRLDEL: + case ETHTOOL_SRXCLSRLINS: +- rc = ethtool_set_rxnfc(dev, useraddr); ++ rc = ethtool_set_rxnfc(dev, ethcmd, useraddr); + break; + case ETHTOOL_GGRO: + rc = ethtool_get_gro(dev, useraddr); diff --git a/queue-2.6.33/series b/queue-2.6.33/series index 70a15a1bca2..8ec06f0c4cc 100644 --- a/queue-2.6.33/series +++ b/queue-2.6.33/series @@ -104,3 +104,4 @@ usb-adds-artisman-usb-dongle-to-list-of-quirky-devices.patch usb-sisusbvga-fix-for-usb-3.0.patch usb-add-quirk-for-broadcom-bt-dongle.patch usb-ftdi-add-support-for-the-rt-system-vx-7-radio-programming-cable.patch +ethtool-fix-potential-user-buffer-overflow-for-ethtool_-g-s-rxfh.patch