Commit e5c6de66 authored by Vivien Didelot's avatar Vivien Didelot Committed by Greg Kroah-Hartman

ethtool: fix potential userspace buffer overflow

[ Upstream commit 0ee4e76937d69128a6a66861ba393ebdc2ffc8a2 ]

ethtool_get_regs() allocates a buffer of size ops->get_regs_len(),
and pass it to the kernel driver via ops->get_regs() for filling.

There is no restriction about what the kernel drivers can or cannot do
with the open ethtool_regs structure. They usually set regs->version
and ignore regs->len or set it to the same size as ops->get_regs_len().

But if userspace allocates a smaller buffer for the registers dump,
we would cause a userspace buffer overflow in the final copy_to_user()
call, which uses the regs.len value potentially reset by the driver.

To fix this, make this case obvious and store regs.len before calling
ops->get_regs(), to only copy as much data as requested by userspace,
up to the value returned by ops->get_regs_len().

While at it, remove the redundant check for non-null regbuf.
Signed-off-by: default avatarVivien Didelot <>
Reviewed-by: default avatarMichal Kubecek <>
Signed-off-by: default avatarDavid S. Miller <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent 8795708b
......@@ -893,13 +893,16 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
return -ENOMEM;
if (regs.len < reglen)
reglen = regs.len;
ops->get_regs(dev, &regs, regbuf);
ret = -EFAULT;
if (copy_to_user(useraddr, &regs, sizeof(regs)))
goto out;
useraddr += offsetof(struct ethtool_regs, data);
if (regbuf && copy_to_user(useraddr, regbuf, regs.len))
if (copy_to_user(useraddr, regbuf, reglen))
goto out;
ret = 0;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment