aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorWenwen Wang <wang6495@umn.edu>2018-10-09 08:15:38 -0500
committerDavid S. Miller <davem@davemloft.net>2018-10-15 21:37:01 -0700
commit2bb3207dbbd4d30e96dd0e1c8e013104193bd59c (patch)
tree78456187a2e91ef89a8ef0780dd793447e967ee7 /net
parentr8169: Enable MSI-X on RTL8106e (diff)
downloadlinux-dev-2bb3207dbbd4d30e96dd0e1c8e013104193bd59c.tar.xz
linux-dev-2bb3207dbbd4d30e96dd0e1c8e013104193bd59c.zip
ethtool: fix a missing-check bug
In ethtool_get_rxnfc(), the eth command 'cmd' is compared against 'ETHTOOL_GRXFH' to see whether it is necessary to adjust the variable 'info_size'. Then the whole structure of 'info' is copied from the user-space buffer 'useraddr' with 'info_size' bytes. In the following execution, 'info' may be copied again from the buffer 'useraddr' depending on the 'cmd' and the 'info.flow_type'. However, after these two copies, there is no check between 'cmd' and 'info.cmd'. In fact, 'cmd' is also copied from the buffer 'useraddr' in dev_ethtool(), which is the caller function of ethtool_get_rxnfc(). Given that 'useraddr' is in the user space, a malicious user can race to change the eth command in the buffer between these copies. By doing so, the attacker can supply inconsistent data and cause undefined behavior because in the following execution 'info' will be passed to ops->get_rxnfc(). This patch adds a necessary check on 'info.cmd' and 'cmd' to confirm that they are still same after the two copies in ethtool_get_rxnfc(). Otherwise, an error code EINVAL will be returned. Signed-off-by: Wenwen Wang <wang6495@umn.edu> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/ethtool.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 0762aaf8e964..192f2f76b7bd 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1015,6 +1015,9 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
return -EINVAL;
}
+ if (info.cmd != cmd)
+ return -EINVAL;
+
if (info.cmd == ETHTOOL_GRXCLSRLALL) {
if (info.rule_cnt > 0) {
if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))