bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
@ 2019-10-26  7:54 zhanglin
  2019-10-26 14:24 ` Dan Carpenter
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: zhanglin @ 2019-10-26  7:54 UTC (permalink / raw)
  To: davem
  Cc: ast, daniel, jakub.kicinski, hawk, john.fastabend, mkubecek,
	jiri, pablo, f.fainelli, maxime.chevallier, lirongqing,
	vivien.didelot, linyunsheng, natechancellor, arnd, dan.carpenter,
	netdev, linux-kernel, bpf, xue.zhihong, wang.yi59, jiang.xuexin,
	zhanglin

memset() the structure ethtool_wolinfo that has padded bytes
but the padded bytes have not been zeroed out.

Signed-off-by: zhanglin <zhang.lin16@zte.com.cn>
---
 net/core/ethtool.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index aeabc48..563a845 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
 
 static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
 {
-	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+	struct ethtool_wolinfo wol;
 
 	if (!dev->ethtool_ops->get_wol)
 		return -EOPNOTSUPP;
 
+	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
+	wol.cmd = ETHTOOL_GWOL;
 	dev->ethtool_ops->get_wol(dev, &wol);
 
 	if (copy_to_user(useraddr, &wol, sizeof(wol)))
-- 
2.15.2


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

* Re: [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-10-26  7:54 [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol() zhanglin
@ 2019-10-26 14:24 ` Dan Carpenter
  2019-10-26 15:52   ` Joe Perches
  2019-10-26 18:21 ` David Miller
  2019-10-26 19:40 ` Joe Perches
  2 siblings, 1 reply; 12+ messages in thread
From: Dan Carpenter @ 2019-10-26 14:24 UTC (permalink / raw)
  To: zhanglin
  Cc: davem, ast, daniel, jakub.kicinski, hawk, john.fastabend,
	mkubecek, jiri, pablo, f.fainelli, maxime.chevallier, lirongqing,
	vivien.didelot, linyunsheng, natechancellor, arnd, netdev,
	linux-kernel, bpf, xue.zhihong, wang.yi59, jiang.xuexin

On Sat, Oct 26, 2019 at 03:54:16PM +0800, zhanglin wrote:
> memset() the structure ethtool_wolinfo that has padded bytes
> but the padded bytes have not been zeroed out.
> 
> Signed-off-by: zhanglin <zhang.lin16@zte.com.cn>
> ---
>  net/core/ethtool.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> index aeabc48..563a845 100644
> --- a/net/core/ethtool.c
> +++ b/net/core/ethtool.c
> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
>  
>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
>  {
> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> +	struct ethtool_wolinfo wol;
>  

How did you detect that they weren't initialized?  Is this a KASAN
thing?

Most of the time GCC will zero out the padding bytes when you have an
initializer like this, but sometimes it just makes the intialization a
series of assignments which leaves the holes uninitialized.  I wish I
knew the rules so that I could check for it in Smatch.  Or even better,
I wish that there were an option to always zero the holes in this
situation...

regards,
dan carpenter


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

* Re: [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-10-26 14:24 ` Dan Carpenter
@ 2019-10-26 15:52   ` Joe Perches
  0 siblings, 0 replies; 12+ messages in thread
From: Joe Perches @ 2019-10-26 15:52 UTC (permalink / raw)
  To: Dan Carpenter, zhanglin
  Cc: davem, ast, daniel, jakub.kicinski, hawk, john.fastabend,
	mkubecek, jiri, pablo, f.fainelli, maxime.chevallier, lirongqing,
	vivien.didelot, linyunsheng, natechancellor, arnd, netdev,
	linux-kernel, bpf, xue.zhihong, wang.yi59, jiang.xuexin

On Sat, 2019-10-26 at 17:24 +0300, Dan Carpenter wrote:
> On Sat, Oct 26, 2019 at 03:54:16PM +0800, zhanglin wrote:
> > memset() the structure ethtool_wolinfo that has padded bytes
> > but the padded bytes have not been zeroed out.
[]
> > diff --git a/net/core/ethtool.c b/net/core/ethtool.c
[]
> > @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> >  
> >  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> >  {
> > -	struct ethtool_wolinf wol = { .cmd = ETHTOOL_GWOL };
> > +	struct ethtool_wolinfo wol;
> >  
> 
> How did you detect that they weren't initialized?  Is this a KASAN
> thing?
> 
> Most of the time GCC will zero out the padding bytes when you have an
> initializer like this, but sometimes it just makes the intialization a
> series of assignments which leaves the holes uninitialized.  I wish I
> knew the rules so that I could check for it in Smatch.  Or even better,
> I wish that there were an option to always zero the holes in this
> situation...

The standard doesn't specify what happens to the padding so
it's not just for gcc, it's compiler dependent.

So anything that's used in a copy_to_user with any possible
padding should either be zalloc'd or memset before assigned.

In this case:

include/uapi/linux/ethtool.h:#define SOPASS_MAX 6

and

include/uapi/linux/ethtool.h:struct ethtool_wolinfo {
include/uapi/linux/ethtool.h-   __u32   cmd;
include/uapi/linux/ethtool.h-   __u32   supported;
include/uapi/linux/ethtool.h-   __u32   wolopts;
include/uapi/linux/ethtool.h-   __u8    sopass[SOPASS_MAX];
include/uapi/linux/ethtool.h-};

so there's likely a couple bytes of trailing padding.



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

* Re: [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-10-26  7:54 [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol() zhanglin
  2019-10-26 14:24 ` Dan Carpenter
@ 2019-10-26 18:21 ` David Miller
  2019-10-26 19:40 ` Joe Perches
  2 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2019-10-26 18:21 UTC (permalink / raw)
  To: zhang.lin16
  Cc: ast, daniel, jakub.kicinski, hawk, john.fastabend, mkubecek,
	jiri, pablo, f.fainelli, maxime.chevallier, lirongqing,
	vivien.didelot, linyunsheng, natechancellor, arnd, dan.carpenter,
	netdev, linux-kernel, bpf, xue.zhihong, wang.yi59, jiang.xuexin

From: zhanglin <zhang.lin16@zte.com.cn>
Date: Sat, 26 Oct 2019 15:54:16 +0800

> memset() the structure ethtool_wolinfo that has padded bytes
> but the padded bytes have not been zeroed out.
> 
> Signed-off-by: zhanglin <zhang.lin16@zte.com.cn>

Applied and queued up for -stable.

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

* Re: [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-10-26  7:54 [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol() zhanglin
  2019-10-26 14:24 ` Dan Carpenter
  2019-10-26 18:21 ` David Miller
@ 2019-10-26 19:40 ` Joe Perches
  2019-10-26 20:17   ` [Cocci] " Julia Lawall
  2019-11-21 10:23   ` Enrico Weigelt, metux IT consult
  2 siblings, 2 replies; 12+ messages in thread
From: Joe Perches @ 2019-10-26 19:40 UTC (permalink / raw)
  To: zhanglin, davem, cocci, Andrew Morton, Thomas Gleixner, Linus Torvalds
  Cc: ast, daniel, jakub.kicinski, hawk, john.fastabend, mkubecek,
	jiri, pablo, f.fainelli, maxime.chevallier, lirongqing,
	vivien.didelot, linyunsheng, natechancellor, arnd, dan.carpenter,
	netdev, linux-kernel, bpf, xue.zhihong, wang.yi59, jiang.xuexin

On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> memset() the structure ethtool_wolinfo that has padded bytes
> but the padded bytes have not been zeroed out.
[]
> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
[]
> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
>  
>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
>  {
> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> +	struct ethtool_wolinfo wol;
>  
>  	if (!dev->ethtool_ops->get_wol)
>  		return -EOPNOTSUPP;
>  
> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> +	wol.cmd = ETHTOOL_GWOL;
>  	dev->ethtool_ops->get_wol(dev, &wol);
>  
>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))

It seems likely there are more of these.

Is there any way for coccinelle to find them?

There are ~4000 structs in include/uapi and
there are ~3000 uses of copy_to_user in the tree.

$ git grep -P '\bstruct\s+\w+\s*{' include/uapi/ | cut -f2 -d" "|sort|uniq|wc -l
3785
$ git grep -w copy_to_user|wc -l
2854

A trivial grep and manual search using:

$ git grep -B20 -w copy_to_user | grep -A20 -P '\bstruct\s+\w+\s*=\s*{'

shows at least 1 (I didn't look very hard and stopped after finding 1):

   include/uapi/linux/utsname.h:struct oldold_utsname {
   include/uapi/linux/utsname.h-   char sysname[9];
   include/uapi/linux/utsname.h-   char nodename[9];
   include/uapi/linux/utsname.h-   char release[9];
   include/uapi/linux/utsname.h-   char version[9];
   include/uapi/linux/utsname.h-   char machine[9];
   include/uapi/linux/utsname.h-};

and 

   kernel/sys.c-	struct oldold_utsname tmp = {};
   kernel/sys.c-
   kernel/sys.c-	if (!name)
   kernel/sys.c-		return -EFAULT;
   kernel/sys.c-
   kernel/sys.c-	down_read(&uts_sem);
   kernel/sys.c-	memcpy(&tmp.sysname, &utsname()->sysname, __OLD_UTS_LEN);
   kernel/sys.c-	memcpy(&tmp.nodename, &utsname()->nodename, __OLD_UTS_LEN);
   kernel/sys.c-	memcpy(&tmp.release, &utsname()->release, __OLD_UTS_LEN);
   kernel/sys.c-	memcpy(&tmp.version, &utsname()->version, __OLD_UTS_LEN);
   kernel/sys.c-	memcpy(&tmp.machine, &utsname()->machine, __OLD_UTS_LEN);
   kernel/sys.c-	up_read(&uts_sem);
   kernel/sys.c:	if (copy_to_user(name, &tmp, sizeof(tmp)))

where there is likely 3 bytes of padding after 45 bytes of data
in the struct.



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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-10-26 19:40 ` Joe Perches
@ 2019-10-26 20:17   ` Julia Lawall
  2019-11-21 10:23   ` Enrico Weigelt, metux IT consult
  1 sibling, 0 replies; 12+ messages in thread
From: Julia Lawall @ 2019-10-26 20:17 UTC (permalink / raw)
  To: Joe Perches
  Cc: zhanglin, davem, cocci, Andrew Morton, Thomas Gleixner,
	Linus Torvalds, mkubecek, jakub.kicinski, ast, jiang.xuexin,
	f.fainelli, daniel, john.fastabend, lirongqing,
	maxime.chevallier, vivien.didelot, dan.carpenter, wang.yi59,
	hawk, arnd, jiri, xue.zhihong, natechancellor, netdev,
	linux-kernel, linyunsheng, pablo, bpf



On Sat, 26 Oct 2019, Joe Perches wrote:

> On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> > memset() the structure ethtool_wolinfo that has padded bytes
> > but the padded bytes have not been zeroed out.
> []
> > diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> []
> > @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> >
> >  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> >  {
> > -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> > +	struct ethtool_wolinfo wol;
> >
> >  	if (!dev->ethtool_ops->get_wol)
> >  		return -EOPNOTSUPP;
> >
> > +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> > +	wol.cmd = ETHTOOL_GWOL;
> >  	dev->ethtool_ops->get_wol(dev, &wol);
> >
> >  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
>
> It seems likely there are more of these.
>
> Is there any way for coccinelle to find them?
>
> There are ~4000 structs in include/uapi and
> there are ~3000 uses of copy_to_user in the tree.
>
> $ git grep -P '\bstruct\s+\w+\s*{' include/uapi/ | cut -f2 -d" "|sort|uniq|wc -l
> 3785
> $ git grep -w copy_to_user|wc -l
> 2854
>
> A trivial grep and manual search using:
>
> $ git grep -B20 -w copy_to_user | grep -A20 -P '\bstruct\s+\w+\s*=\s*{'
>
> shows at least 1 (I didn't look very hard and stopped after finding 1):
>
>    include/uapi/linux/utsname.h:struct oldold_utsname {
>    include/uapi/linux/utsname.h-   char sysname[9];
>    include/uapi/linux/utsname.h-   char nodename[9];
>    include/uapi/linux/utsname.h-   char release[9];
>    include/uapi/linux/utsname.h-   char version[9];
>    include/uapi/linux/utsname.h-   char machine[9];
>    include/uapi/linux/utsname.h-};
>
> and
>
>    kernel/sys.c-	struct oldold_utsname tmp = {};
>    kernel/sys.c-
>    kernel/sys.c-	if (!name)
>    kernel/sys.c-		return -EFAULT;
>    kernel/sys.c-
>    kernel/sys.c-	down_read(&uts_sem);
>    kernel/sys.c-	memcpy(&tmp.sysname, &utsname()->sysname, __OLD_UTS_LEN);
>    kernel/sys.c-	memcpy(&tmp.nodename, &utsname()->nodename, __OLD_UTS_LEN);
>    kernel/sys.c-	memcpy(&tmp.release, &utsname()->release, __OLD_UTS_LEN);
>    kernel/sys.c-	memcpy(&tmp.version, &utsname()->version, __OLD_UTS_LEN);
>    kernel/sys.c-	memcpy(&tmp.machine, &utsname()->machine, __OLD_UTS_LEN);
>    kernel/sys.c-	up_read(&uts_sem);
>    kernel/sys.c:	if (copy_to_user(name, &tmp, sizeof(tmp)))
>
> where there is likely 3 bytes of padding after 45 bytes of data
> in the struct.

I looked into this at one point, but didn't get as far as generating
patches.  I think that the approach was roughly to collect the types of
the fields, and then generate code that would use BUILD_BUG_ON to complain
if the sum of the sizes was not the same as the size of the structure.
The problem was that I wasn't sure what was a real problem, nor what was
the best way to solve it.

julia

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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-10-26 19:40 ` Joe Perches
  2019-10-26 20:17   ` [Cocci] " Julia Lawall
@ 2019-11-21 10:23   ` Enrico Weigelt, metux IT consult
  2019-11-21 11:19     ` Michal Kubecek
  1 sibling, 1 reply; 12+ messages in thread
From: Enrico Weigelt, metux IT consult @ 2019-11-21 10:23 UTC (permalink / raw)
  To: Joe Perches, zhanglin, davem, cocci, Andrew Morton,
	Thomas Gleixner, Linus Torvalds
  Cc: mkubecek, jakub.kicinski, ast, jiang.xuexin, f.fainelli, daniel,
	john.fastabend, lirongqing, maxime.chevallier, vivien.didelot,
	dan.carpenter, wang.yi59, hawk, arnd, jiri, xue.zhihong,
	natechancellor, netdev, linux-kernel, linyunsheng, pablo, bpf

On 26.10.19 21:40, Joe Perches wrote:
> On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
>> memset() the structure ethtool_wolinfo that has padded bytes
>> but the padded bytes have not been zeroed out.
> []
>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> []
>> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
>>  
>>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
>>  {
>> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
>> +	struct ethtool_wolinfo wol;
>>  
>>  	if (!dev->ethtool_ops->get_wol)
>>  		return -EOPNOTSUPP;
>>  
>> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
>> +	wol.cmd = ETHTOOL_GWOL;
>>  	dev->ethtool_ops->get_wol(dev, &wol);
>>  
>>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
> 
> It seems likely there are more of these.
> 
> Is there any way for coccinelle to find them?

Just curios: is static struct initialization (on stack) something that
should be avoided ? I've been under the impression that static
initialization allows thinner code and gives the compiler better chance
for optimizations.


--mtx

---
Enrico Weigelt, metux IT consult
Free software and Linux embedded engineering
info@metux.net -- +49-151-27565287

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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-11-21 10:23   ` Enrico Weigelt, metux IT consult
@ 2019-11-21 11:19     ` Michal Kubecek
  2019-11-21 11:58       ` Julia Lawall
  2019-11-21 12:07       ` Dan Carpenter
  0 siblings, 2 replies; 12+ messages in thread
From: Michal Kubecek @ 2019-11-21 11:19 UTC (permalink / raw)
  To: Enrico Weigelt, metux IT consult
  Cc: Joe Perches, zhanglin, davem, cocci, Andrew Morton,
	Thomas Gleixner, Linus Torvalds, jakub.kicinski, ast,
	jiang.xuexin, f.fainelli, daniel, john.fastabend, lirongqing,
	maxime.chevallier, vivien.didelot, dan.carpenter, wang.yi59,
	hawk, arnd, jiri, xue.zhihong, natechancellor, netdev,
	linux-kernel, linyunsheng, pablo, bpf

On Thu, Nov 21, 2019 at 11:23:34AM +0100, Enrico Weigelt, metux IT consult wrote:
> On 26.10.19 21:40, Joe Perches wrote:
> > On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> >> memset() the structure ethtool_wolinfo that has padded bytes
> >> but the padded bytes have not been zeroed out.
> > []
> >> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> > []
> >> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> >>  
> >>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> >>  {
> >> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> >> +	struct ethtool_wolinfo wol;
> >>  
> >>  	if (!dev->ethtool_ops->get_wol)
> >>  		return -EOPNOTSUPP;
> >>  
> >> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> >> +	wol.cmd = ETHTOOL_GWOL;
> >>  	dev->ethtool_ops->get_wol(dev, &wol);
> >>  
> >>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
> > 
> > It seems likely there are more of these.
> > 
> > Is there any way for coccinelle to find them?
> 
> Just curios: is static struct initialization (on stack) something that
> should be avoided ? I've been under the impression that static
> initialization allows thinner code and gives the compiler better chance
> for optimizations.

Not in general. The (potential) problem here is that the structure has
padding and it is as a whole (i.e. including the padding) copied to
userspace. While I'm not aware of a compiler that wouldn't actually
initialize the whole data block including the padding in this case, the
C standard provides no guarantee about that so that to be sure we cannot
leak leftover kernel data to userspace, we need to explicitly initialize
the whole block.

If the structure is not going to be copied to userspace (or otherwise
exposed), using the initializer is fully sufficient and looks cleaner.

Michal Kubecek

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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-11-21 11:19     ` Michal Kubecek
@ 2019-11-21 11:58       ` Julia Lawall
  2019-11-21 12:07       ` Dan Carpenter
  1 sibling, 0 replies; 12+ messages in thread
From: Julia Lawall @ 2019-11-21 11:58 UTC (permalink / raw)
  To: Michal Kubecek
  Cc: Enrico Weigelt, metux IT consult, jakub.kicinski, ast,
	natechancellor, jiang.xuexin, cocci, f.fainelli, daniel,
	john.fastabend, lirongqing, maxime.chevallier, vivien.didelot,
	dan.carpenter, wang.yi59, hawk, arnd, jiri, xue.zhihong,
	zhanglin, Thomas Gleixner, bpf, netdev, linux-kernel,
	linyunsheng, pablo, Joe Perches, Andrew Morton, Linus Torvalds,
	davem



On Thu, 21 Nov 2019, Michal Kubecek wrote:

> On Thu, Nov 21, 2019 at 11:23:34AM +0100, Enrico Weigelt, metux IT consult wrote:
> > On 26.10.19 21:40, Joe Perches wrote:
> > > On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> > >> memset() the structure ethtool_wolinfo that has padded bytes
> > >> but the padded bytes have not been zeroed out.
> > > []
> > >> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> > > []
> > >> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> > >>
> > >>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> > >>  {
> > >> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> > >> +	struct ethtool_wolinfo wol;
> > >>
> > >>  	if (!dev->ethtool_ops->get_wol)
> > >>  		return -EOPNOTSUPP;
> > >>
> > >> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> > >> +	wol.cmd = ETHTOOL_GWOL;
> > >>  	dev->ethtool_ops->get_wol(dev, &wol);
> > >>
> > >>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
> > >
> > > It seems likely there are more of these.
> > >
> > > Is there any way for coccinelle to find them?
> >
> > Just curios: is static struct initialization (on stack) something that
> > should be avoided ? I've been under the impression that static
> > initialization allows thinner code and gives the compiler better chance
> > for optimizations.
>
> Not in general. The (potential) problem here is that the structure has
> padding and it is as a whole (i.e. including the padding) copied to
> userspace. While I'm not aware of a compiler that wouldn't actually
> initialize the whole data block including the padding in this case, the
> C standard provides no guarantee about that so that to be sure we cannot
> leak leftover kernel data to userspace, we need to explicitly initialize
> the whole block.

I'm not sure that it is likely that the compiler will do anything other
than ensure that all the fields are initialized.  Among the files that I
could compile, the only case with actual padding and no memset, memcpy,
copy_from_user or structure assignment that I could find was

drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c

There is the code struct drm_amdgpu_info_device dev_info = {};

but I couldn't see any thing in the assembly language that seemed to zero
the structure.  gcc probably thought its job was done because all fields
are subsequently initialized.  But the size of the structure does not seem
to be the same as the sum of the size of the fields.

The set of fields was collected with Coccinelle, which could be unreliable
for this task.

julia

>
> If the structure is not going to be copied to userspace (or otherwise
> exposed), using the initializer is fully sufficient and looks cleaner.
>
> Michal Kubecek
> _______________________________________________
> Cocci mailing list
> Cocci@systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
>

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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-11-21 11:19     ` Michal Kubecek
  2019-11-21 11:58       ` Julia Lawall
@ 2019-11-21 12:07       ` Dan Carpenter
  2019-11-21 13:38         ` Michal Kubecek
  1 sibling, 1 reply; 12+ messages in thread
From: Dan Carpenter @ 2019-11-21 12:07 UTC (permalink / raw)
  To: Michal Kubecek
  Cc: Enrico Weigelt, metux IT consult, Joe Perches, zhanglin, davem,
	cocci, Andrew Morton, Thomas Gleixner, Linus Torvalds,
	jakub.kicinski, ast, jiang.xuexin, f.fainelli, daniel,
	john.fastabend, lirongqing, maxime.chevallier, vivien.didelot,
	wang.yi59, hawk, arnd, jiri, xue.zhihong, natechancellor, netdev,
	linux-kernel, linyunsheng, pablo, bpf

On Thu, Nov 21, 2019 at 12:19:17PM +0100, Michal Kubecek wrote:
> On Thu, Nov 21, 2019 at 11:23:34AM +0100, Enrico Weigelt, metux IT consult wrote:
> > On 26.10.19 21:40, Joe Perches wrote:
> > > On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> > >> memset() the structure ethtool_wolinfo that has padded bytes
> > >> but the padded bytes have not been zeroed out.
> > > []
> > >> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> > > []
> > >> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> > >>  
> > >>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> > >>  {
> > >> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> > >> +	struct ethtool_wolinfo wol;
> > >>  
> > >>  	if (!dev->ethtool_ops->get_wol)
> > >>  		return -EOPNOTSUPP;
> > >>  
> > >> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> > >> +	wol.cmd = ETHTOOL_GWOL;
> > >>  	dev->ethtool_ops->get_wol(dev, &wol);
> > >>  
> > >>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
> > > 
> > > It seems likely there are more of these.
> > > 
> > > Is there any way for coccinelle to find them?
> > 
> > Just curios: is static struct initialization (on stack) something that
> > should be avoided ? I've been under the impression that static
> > initialization allows thinner code and gives the compiler better chance
> > for optimizations.
> 
> Not in general. The (potential) problem here is that the structure has
> padding and it is as a whole (i.e. including the padding) copied to
> userspace. While I'm not aware of a compiler that wouldn't actually
> initialize the whole data block including the padding in this case, the
> C standard provides no guarantee about that so that to be sure we cannot
> leak leftover kernel data to userspace, we need to explicitly initialize
> the whole block.

GCC will not always initialize the struct holes.  This patch fixes a
real bug that GCC on my system (v7.4)

regards,
dan carpenter


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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-11-21 12:07       ` Dan Carpenter
@ 2019-11-21 13:38         ` Michal Kubecek
  2019-11-21 20:40           ` Julia Lawall
  0 siblings, 1 reply; 12+ messages in thread
From: Michal Kubecek @ 2019-11-21 13:38 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Enrico Weigelt, metux IT consult, Joe Perches, zhanglin, davem,
	cocci, Andrew Morton, Thomas Gleixner, Linus Torvalds,
	jakub.kicinski, ast, jiang.xuexin, f.fainelli, daniel,
	john.fastabend, lirongqing, maxime.chevallier, vivien.didelot,
	wang.yi59, hawk, arnd, jiri, xue.zhihong, natechancellor, netdev,
	linux-kernel, linyunsheng, pablo, bpf

On Thu, Nov 21, 2019 at 03:07:33PM +0300, Dan Carpenter wrote:
> On Thu, Nov 21, 2019 at 12:19:17PM +0100, Michal Kubecek wrote:
> > On Thu, Nov 21, 2019 at 11:23:34AM +0100, Enrico Weigelt, metux IT consult wrote:
> > > On 26.10.19 21:40, Joe Perches wrote:
> > > > On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> > > >> memset() the structure ethtool_wolinfo that has padded bytes
> > > >> but the padded bytes have not been zeroed out.
> > > > []
> > > >> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> > > > []
> > > >> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> > > >>  
> > > >>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> > > >>  {
> > > >> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> > > >> +	struct ethtool_wolinfo wol;
> > > >>  
> > > >>  	if (!dev->ethtool_ops->get_wol)
> > > >>  		return -EOPNOTSUPP;
> > > >>  
> > > >> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> > > >> +	wol.cmd = ETHTOOL_GWOL;
> > > >>  	dev->ethtool_ops->get_wol(dev, &wol);
> > > >>  
> > > >>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
> > > > 
> > > > It seems likely there are more of these.
> > > > 
> > > > Is there any way for coccinelle to find them?
> > > 
> > > Just curios: is static struct initialization (on stack) something that
> > > should be avoided ? I've been under the impression that static
> > > initialization allows thinner code and gives the compiler better chance
> > > for optimizations.
> > 
> > Not in general. The (potential) problem here is that the structure has
> > padding and it is as a whole (i.e. including the padding) copied to
> > userspace. While I'm not aware of a compiler that wouldn't actually
> > initialize the whole data block including the padding in this case, the
> > C standard provides no guarantee about that so that to be sure we cannot
> > leak leftover kernel data to userspace, we need to explicitly initialize
> > the whole block.
> 
> GCC will not always initialize the struct holes.  This patch fixes a
> real bug that GCC on my system (v7.4)

Just checked (again) to be sure. No matter if the function is inlined or
not, gcc 7.4.1 initializes the structure by one movl (of 0x5) and two
movq (of 0x0), i.e. initializes all sizeof(struct ethtool_wolinfo) = 20
bytes including the padding.

One could certainly construct examples where a real life compiler would
only initialize the fields. That's why I said "in this case".

Michal Kubecek



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

* Re: [Cocci] [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol()
  2019-11-21 13:38         ` Michal Kubecek
@ 2019-11-21 20:40           ` Julia Lawall
  0 siblings, 0 replies; 12+ messages in thread
From: Julia Lawall @ 2019-11-21 20:40 UTC (permalink / raw)
  To: Michal Kubecek
  Cc: Dan Carpenter, jakub.kicinski, ast, natechancellor, jiang.xuexin,
	cocci, f.fainelli, daniel, john.fastabend, lirongqing,
	maxime.chevallier, vivien.didelot, pablo, wang.yi59, hawk, arnd,
	jiri, xue.zhihong, zhanglin, Thomas Gleixner, bpf, netdev,
	linux-kernel, linyunsheng, Joe Perches, Andrew Morton,
	Linus Torvalds, davem



On Thu, 21 Nov 2019, Michal Kubecek wrote:

> On Thu, Nov 21, 2019 at 03:07:33PM +0300, Dan Carpenter wrote:
> > On Thu, Nov 21, 2019 at 12:19:17PM +0100, Michal Kubecek wrote:
> > > On Thu, Nov 21, 2019 at 11:23:34AM +0100, Enrico Weigelt, metux IT consult wrote:
> > > > On 26.10.19 21:40, Joe Perches wrote:
> > > > > On Sat, 2019-10-26 at 15:54 +0800, zhanglin wrote:
> > > > >> memset() the structure ethtool_wolinfo that has padded bytes
> > > > >> but the padded bytes have not been zeroed out.
> > > > > []
> > > > >> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
> > > > > []
> > > > >> @@ -1471,11 +1471,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
> > > > >>
> > > > >>  static int ethtool_get_wol(struct net_device *dev, char __user *useraddr)
> > > > >>  {
> > > > >> -	struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
> > > > >> +	struct ethtool_wolinfo wol;
> > > > >>
> > > > >>  	if (!dev->ethtool_ops->get_wol)
> > > > >>  		return -EOPNOTSUPP;
> > > > >>
> > > > >> +	memset(&wol, 0, sizeof(struct ethtool_wolinfo));
> > > > >> +	wol.cmd = ETHTOOL_GWOL;
> > > > >>  	dev->ethtool_ops->get_wol(dev, &wol);
> > > > >>
> > > > >>  	if (copy_to_user(useraddr, &wol, sizeof(wol)))
> > > > >
> > > > > It seems likely there are more of these.
> > > > >
> > > > > Is there any way for coccinelle to find them?
> > > >
> > > > Just curios: is static struct initialization (on stack) something that
> > > > should be avoided ? I've been under the impression that static
> > > > initialization allows thinner code and gives the compiler better chance
> > > > for optimizations.
> > >
> > > Not in general. The (potential) problem here is that the structure has
> > > padding and it is as a whole (i.e. including the padding) copied to
> > > userspace. While I'm not aware of a compiler that wouldn't actually
> > > initialize the whole data block including the padding in this case, the
> > > C standard provides no guarantee about that so that to be sure we cannot
> > > leak leftover kernel data to userspace, we need to explicitly initialize
> > > the whole block.
> >
> > GCC will not always initialize the struct holes.  This patch fixes a
> > real bug that GCC on my system (v7.4)
>
> Just checked (again) to be sure. No matter if the function is inlined or
> not, gcc 7.4.1 initializes the structure by one movl (of 0x5) and two
> movq (of 0x0), i.e. initializes all sizeof(struct ethtool_wolinfo) = 20
> bytes including the padding.
>
> One could certainly construct examples where a real life compiler would
> only initialize the fields. That's why I said "in this case".

Looking again at the case that I mentioned, I see:

# drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c:691:          struct drm_amdgpu_info_device dev_info = {};
        call    __sanitizer_cov_trace_pc        #
        leaq    840(%rsp), %rdi #, tmp1126
        xorl    %eax, %eax      # tmp1127
        movl    $46, %ecx       #, tmp1128
        rep stosq

So I guess the rep stosq is doing the memset.

julia

>
> Michal Kubecek
>
>
> _______________________________________________
> Cocci mailing list
> Cocci@systeme.lip6.fr
> https://systeme.lip6.fr/mailman/listinfo/cocci
>

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

end of thread, other threads:[~2019-11-21 20:40 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-26  7:54 [PATCH] net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol() zhanglin
2019-10-26 14:24 ` Dan Carpenter
2019-10-26 15:52   ` Joe Perches
2019-10-26 18:21 ` David Miller
2019-10-26 19:40 ` Joe Perches
2019-10-26 20:17   ` [Cocci] " Julia Lawall
2019-11-21 10:23   ` Enrico Weigelt, metux IT consult
2019-11-21 11:19     ` Michal Kubecek
2019-11-21 11:58       ` Julia Lawall
2019-11-21 12:07       ` Dan Carpenter
2019-11-21 13:38         ` Michal Kubecek
2019-11-21 20:40           ` Julia Lawall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).