* [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 related [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).