All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next] ethtool: copy reglen to userspace
@ 2019-05-28 20:58 Vivien Didelot
  2019-05-30  5:17 ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: Vivien Didelot @ 2019-05-28 20:58 UTC (permalink / raw)
  To: netdev
  Cc: linux-kernel, kernel, Vivien Didelot, David S. Miller, linville,
	f.fainelli

ethtool_get_regs() allocates a buffer of size reglen obtained from
ops->get_regs_len(), thus only this value must be used when copying
the buffer back to userspace. Also no need to check regbuf twice.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
---
 net/core/ethtool.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 4a593853cbf2..f3369f31d93a 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1338,38 +1338,38 @@ static noinline_for_stack int ethtool_set_rxfh(struct net_device *dev,
 static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_regs regs;
 	const struct ethtool_ops *ops = dev->ethtool_ops;
 	void *regbuf;
 	int reglen, ret;
 
 	if (!ops->get_regs || !ops->get_regs_len)
 		return -EOPNOTSUPP;
 
 	if (copy_from_user(&regs, useraddr, sizeof(regs)))
 		return -EFAULT;
 
 	reglen = ops->get_regs_len(dev);
 	if (reglen <= 0)
 		return reglen;
 
 	if (regs.len > reglen)
 		regs.len = reglen;
 
 	regbuf = vzalloc(reglen);
 	if (!regbuf)
 		return -ENOMEM;
 
 	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;
 
  out:
 	vfree(regbuf);
 	return ret;
 }
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] ethtool: copy reglen to userspace
  2019-05-28 20:58 [PATCH net-next] ethtool: copy reglen to userspace Vivien Didelot
@ 2019-05-30  5:17 ` David Miller
  2019-05-30  6:48   ` Michal Kubecek
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2019-05-30  5:17 UTC (permalink / raw)
  To: vivien.didelot; +Cc: netdev, linux-kernel, kernel, linville, f.fainelli

From: Vivien Didelot <vivien.didelot@gmail.com>
Date: Tue, 28 May 2019 16:58:48 -0400

> ethtool_get_regs() allocates a buffer of size reglen obtained from
> ops->get_regs_len(), thus only this value must be used when copying
> the buffer back to userspace. Also no need to check regbuf twice.
> 
> Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>

Hmmm, can't regs.len be modified by the driver potentially?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] ethtool: copy reglen to userspace
  2019-05-30  5:17 ` David Miller
@ 2019-05-30  6:48   ` Michal Kubecek
  2019-05-30  8:27     ` Michal Kubecek
  0 siblings, 1 reply; 6+ messages in thread
From: Michal Kubecek @ 2019-05-30  6:48 UTC (permalink / raw)
  To: netdev
  Cc: David Miller, vivien.didelot, linux-kernel, kernel, linville, f.fainelli

On Wed, May 29, 2019 at 10:17:44PM -0700, David Miller wrote:
> From: Vivien Didelot <vivien.didelot@gmail.com>
> Date: Tue, 28 May 2019 16:58:48 -0400
> 
> > ethtool_get_regs() allocates a buffer of size reglen obtained from
> > ops->get_regs_len(), thus only this value must be used when copying
> > the buffer back to userspace. Also no need to check regbuf twice.
> > 
> > Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
> 
> Hmmm, can't regs.len be modified by the driver potentially?

The driver certainly shouldn't raise it as that could result in kernel
writing past the buffer provided by userspace. (I'll check some drivers
to see if they truncate the dump or return an error if regs.len from
userspace is insufficient.) And lowering it would be also wrong as that
would mean dump would be shorter than what ops->get_regs_len() returned.

Michal Kubecek

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] ethtool: copy reglen to userspace
  2019-05-30  6:48   ` Michal Kubecek
@ 2019-05-30  8:27     ` Michal Kubecek
  2019-05-30 18:26       ` David Miller
  0 siblings, 1 reply; 6+ messages in thread
From: Michal Kubecek @ 2019-05-30  8:27 UTC (permalink / raw)
  To: netdev
  Cc: David Miller, vivien.didelot, linux-kernel, kernel, linville, f.fainelli

On Thu, May 30, 2019 at 08:48:48AM +0200, Michal Kubecek wrote:
> On Wed, May 29, 2019 at 10:17:44PM -0700, David Miller wrote:
> > From: Vivien Didelot <vivien.didelot@gmail.com>
> > Date: Tue, 28 May 2019 16:58:48 -0400
> > 
> > > ethtool_get_regs() allocates a buffer of size reglen obtained from
> > > ops->get_regs_len(), thus only this value must be used when copying
> > > the buffer back to userspace. Also no need to check regbuf twice.
> > > 
> > > Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
> > 
> > Hmmm, can't regs.len be modified by the driver potentially?
> 
> The driver certainly shouldn't raise it as that could result in kernel
> writing past the buffer provided by userspace. (I'll check some drivers
> to see if they truncate the dump or return an error if regs.len from
> userspace is insufficient.) And lowering it would be also wrong as that
> would mean dump would be shorter than what ops->get_regs_len() returned.

I looked around a bit. First of all, the driver cannot actually return
error as ethtool_ops::get_regs() returns void. Most drivers do not touch
regs->len and only fill data and possibly regs->version which is fine.

There are few drivers which modify regs->len:

  s2io_ethtool_gdrvinfo()	neterion/s2io
  vxge_ethtool_gregs()		neterion/vxge
  ixgb_get_regs()		intel/ixgb
  emac_get_regs_len()		qualcomm/emac
  ql_get_regs()			qlogic/qlge
  axienet_ethtools_get_regs()	xilinx/axienet

All of these set regs->len to the same value as ->get_regs_len() returns
(ixgb does it in rather fragile way). This means that if userspace
passes insufficient buffer size, current code would write pass that
buffer; but proposed patch would make things worse as with it, kernel
would always write past the userspace buffer in such case.

Note: ieee80211_get_regs() in net/mac80211/ethtool.c also sets regs->len
but it always sets it to 0 which is also what ->get_regs_len() returns
so that it does not actually modify the value.

I believe this should be handled by ethtool_get_regs(), either by
returning an error or by only copying data up to original regs.len
passed by userspace. The former seems more correct but broken userspace
software would suddenly start to fail where it "used to work". The
latter would be closer to current behaviour but it would mean that
broken userspace software might nerver notice there is something wrong.

Michal Kubecek

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] ethtool: copy reglen to userspace
  2019-05-30  8:27     ` Michal Kubecek
@ 2019-05-30 18:26       ` David Miller
  2019-05-30 23:38         ` Vivien Didelot
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2019-05-30 18:26 UTC (permalink / raw)
  To: mkubecek
  Cc: netdev, vivien.didelot, linux-kernel, kernel, linville, f.fainelli

From: Michal Kubecek <mkubecek@suse.cz>
Date: Thu, 30 May 2019 10:27:22 +0200

> I believe this should be handled by ethtool_get_regs(), either by
> returning an error or by only copying data up to original regs.len
> passed by userspace. The former seems more correct but broken userspace
> software would suddenly start to fail where it "used to work". The
> latter would be closer to current behaviour but it would mean that
> broken userspace software might nerver notice there is something wrong.

I therefore think we need to meticulously fixup all of these adjustments
of regs.len before adjusting the copy call here in generic ethtool.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net-next] ethtool: copy reglen to userspace
  2019-05-30 18:26       ` David Miller
@ 2019-05-30 23:38         ` Vivien Didelot
  0 siblings, 0 replies; 6+ messages in thread
From: Vivien Didelot @ 2019-05-30 23:38 UTC (permalink / raw)
  To: David Miller; +Cc: mkubecek, netdev, linux-kernel, kernel, linville, f.fainelli

Hi Michal, David,

On Thu, 30 May 2019 11:26:30 -0700 (PDT), David Miller <davem@davemloft.net> wrote:
> From: Michal Kubecek <mkubecek@suse.cz>
> Date: Thu, 30 May 2019 10:27:22 +0200
> 
> > I believe this should be handled by ethtool_get_regs(), either by
> > returning an error or by only copying data up to original regs.len
> > passed by userspace. The former seems more correct but broken userspace
> > software would suddenly start to fail where it "used to work". The
> > latter would be closer to current behaviour but it would mean that
> > broken userspace software might nerver notice there is something wrong.
> 
> I therefore think we need to meticulously fixup all of these adjustments
> of regs.len before adjusting the copy call here in generic ethtool.

Indeed there are cases where userspace may allocate a smaller buffer
(even though there's no way for the kernel to ensure the size that
was really allocated, but well...).

The kernel must still allocates a buffer of size ops->get_regs_len()
and pass it to the driver. It's OK if the kernel driver messes with
regs->len, since it's an open structure. Software may actually make
use of it. However the kernel must use the original regs->len passed
by userspace (up to ops->get_regs_len()) when copying the data.

I'm sending a new patch right away.


Thanks,
Vivien

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-05-30 23:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-28 20:58 [PATCH net-next] ethtool: copy reglen to userspace Vivien Didelot
2019-05-30  5:17 ` David Miller
2019-05-30  6:48   ` Michal Kubecek
2019-05-30  8:27     ` Michal Kubecek
2019-05-30 18:26       ` David Miller
2019-05-30 23:38         ` Vivien Didelot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.