Home Home > GIT Browse
diff options
authorMichal Kubecek <mkubecek@suse.cz>2018-10-25 14:40:16 +0200
committerMichal Kubecek <mkubecek@suse.cz>2018-10-25 14:40:16 +0200
commiteb308cd8a0f3816e6ba88fb97de4efd958b6ebc1 (patch)
parent5201e63c911ac038471d97a7fcb521fa4c48ba0f (diff)
ethtool: fix a privilege escalation bug (bsc#1076830).
2 files changed, 73 insertions, 0 deletions
diff --git a/patches.fixes/ethtool-fix-a-privilege-escalation-bug.patch b/patches.fixes/ethtool-fix-a-privilege-escalation-bug.patch
new file mode 100644
index 0000000000..31bbff5670
--- /dev/null
+++ b/patches.fixes/ethtool-fix-a-privilege-escalation-bug.patch
@@ -0,0 +1,72 @@
+From: Wenwen Wang <wang6495@umn.edu>
+Date: Mon, 8 Oct 2018 10:49:35 -0500
+Subject: ethtool: fix a privilege escalation bug
+Patch-mainline: v4.19
+Git-commit: 58f5bbe331c566f49c9559568f982202a278aa78
+References: bsc#1076830
+In dev_ethtool(), the eth command 'ethcmd' is firstly copied from the
+use-space buffer 'useraddr' and checked to see whether it is
+ETHTOOL_PERQUEUE. If yes, the sub-command 'sub_cmd' is further copied from
+the user space. Otherwise, 'sub_cmd' is the same as 'ethcmd'. Next,
+according to 'sub_cmd', a permission check is enforced through the function
+ns_capable(). For example, the permission check is required if 'sub_cmd' is
+ETHTOOL_SCOALESCE, but it is not necessary if 'sub_cmd' is
+ETHTOOL_GCOALESCE, as suggested in the comment "Allow some commands to be
+done by anyone". The following execution invokes different handlers
+according to 'ethcmd'. Specifically, if 'ethcmd' is ETHTOOL_PERQUEUE,
+ethtool_set_per_queue() is called. In ethtool_set_per_queue(), the kernel
+object 'per_queue_opt' is copied again from the user-space buffer
+'useraddr' and 'per_queue_opt.sub_command' is used to determine which
+operation should be performed. Given that the buffer 'useraddr' is in the
+user space, a malicious user can race to change the sub-command between the
+two copies. In particular, the attacker can supply ETHTOOL_PERQUEUE and
+ETHTOOL_GCOALESCE to bypass the permission check in dev_ethtool(). Then
+before ethtool_set_per_queue() is called, the attacker changes
+ETHTOOL_GCOALESCE to ETHTOOL_SCOALESCE. In this way, the attacker can
+bypass the permission check and execute ETHTOOL_SCOALESCE.
+This patch enforces a check in ethtool_set_per_queue() after the second
+copy from 'useraddr'. If the sub-command is different from the one obtained
+in the first copy in dev_ethtool(), an error code EINVAL will be returned.
+Fixes: f38d138a7da6 ("net/ethtool: support set coalesce per queue")
+Signed-off-by: Wenwen Wang <wang6495@umn.edu>
+Reviewed-by: Michal Kubecek <mkubecek@suse.cz>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Kubecek <mkubecek@suse.cz>
+ net/core/ethtool.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -2431,13 +2431,17 @@ static int ethtool_set_per_queue_coalesce(struct net_device *dev,
+ return ret;
+ }
+-static int ethtool_set_per_queue(struct net_device *dev, void __user *useraddr)
++static int ethtool_set_per_queue(struct net_device *dev,
++ void __user *useraddr, u32 sub_cmd)
+ {
+ struct ethtool_per_queue_op per_queue_opt;
+ if (copy_from_user(&per_queue_opt, useraddr, sizeof(per_queue_opt)))
+ return -EFAULT;
++ if (per_queue_opt.sub_command != sub_cmd)
++ return -EINVAL;
+ switch (per_queue_opt.sub_command) {
+ return ethtool_get_per_queue_coalesce(dev, useraddr, &per_queue_opt);
+@@ -2811,7 +2815,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
+ rc = ethtool_get_phy_stats(dev, useraddr);
+ break;
+- rc = ethtool_set_per_queue(dev, useraddr);
++ rc = ethtool_set_per_queue(dev, useraddr, sub_cmd);
+ break;
+ rc = ethtool_get_link_ksettings(dev, useraddr);
diff --git a/series.conf b/series.conf
index 564c15039c..1afded114c 100644
--- a/series.conf
+++ b/series.conf
@@ -18037,6 +18037,7 @@
+ patches.fixes/ethtool-fix-a-privilege-escalation-bug.patch