All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] netfilter: properly initialize xt_table_info structure
@ 2018-05-17  8:44 Greg Kroah-Hartman
  2018-05-17  8:59 ` Michal Kubecek
  0 siblings, 1 reply; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-17  8:44 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
  Cc: netfilter-devel, coreteam, netdev

When allocating a xt_table_info structure, we should be clearing out the
full amount of memory that was allocated, not just the "header" of the
structure.  Otherwise odd values could be passed to userspace, which is
not a good thing.

Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/netfilter/x_tables.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index cb7cb300c3bc..a300e8252bb6 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1187,7 +1187,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
 	if (!info)
 		return NULL;
 
-	memset(info, 0, sizeof(*info));
+	memset(info, 0, sz);
 	info->size = size;
 	return info;
 }
-- 
2.17.0

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

* Re: [PATCH] netfilter: properly initialize xt_table_info structure
  2018-05-17  8:44 [PATCH] netfilter: properly initialize xt_table_info structure Greg Kroah-Hartman
@ 2018-05-17  8:59 ` Michal Kubecek
  2018-05-17  9:29   ` Greg Kroah-Hartman
  2018-05-17  9:34   ` [PATCH v2] " Greg Kroah-Hartman
  0 siblings, 2 replies; 19+ messages in thread
From: Michal Kubecek @ 2018-05-17  8:59 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
	netfilter-devel, coreteam, netdev

On Thu, May 17, 2018 at 10:44:42AM +0200, Greg Kroah-Hartman wrote:
> When allocating a xt_table_info structure, we should be clearing out the
> full amount of memory that was allocated, not just the "header" of the
> structure.  Otherwise odd values could be passed to userspace, which is
> not a good thing.
> 
> Cc: stable <stable@vger.kernel.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  net/netfilter/x_tables.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index cb7cb300c3bc..a300e8252bb6 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -1187,7 +1187,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
>  	if (!info)
>  		return NULL;
>  
> -	memset(info, 0, sizeof(*info));
> +	memset(info, 0, sz);
>  	info->size = size;
>  	return info;
>  }
> -- 
> 2.17.0
> 

Or we can replace kvmalloc() by kvzalloc() and remove the memset().

Michal Kubecek

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

* Re: [PATCH] netfilter: properly initialize xt_table_info structure
  2018-05-17  8:59 ` Michal Kubecek
@ 2018-05-17  9:29   ` Greg Kroah-Hartman
  2018-05-17  9:34   ` [PATCH v2] " Greg Kroah-Hartman
  1 sibling, 0 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-17  9:29 UTC (permalink / raw)
  To: Michal Kubecek
  Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
	netfilter-devel, coreteam, netdev

On Thu, May 17, 2018 at 10:59:51AM +0200, Michal Kubecek wrote:
> On Thu, May 17, 2018 at 10:44:42AM +0200, Greg Kroah-Hartman wrote:
> > When allocating a xt_table_info structure, we should be clearing out the
> > full amount of memory that was allocated, not just the "header" of the
> > structure.  Otherwise odd values could be passed to userspace, which is
> > not a good thing.
> > 
> > Cc: stable <stable@vger.kernel.org>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > ---
> >  net/netfilter/x_tables.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> > index cb7cb300c3bc..a300e8252bb6 100644
> > --- a/net/netfilter/x_tables.c
> > +++ b/net/netfilter/x_tables.c
> > @@ -1187,7 +1187,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
> >  	if (!info)
> >  		return NULL;
> >  
> > -	memset(info, 0, sizeof(*info));
> > +	memset(info, 0, sz);
> >  	info->size = size;
> >  	return info;
> >  }
> > -- 
> > 2.17.0
> > 
> 
> Or we can replace kvmalloc() by kvzalloc() and remove the memset().

That works for me too, either is sufficient to solve the problem.

Let me go respin this, less lines of code is always better :)

thanks,

greg k-h

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

* [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-17  8:59 ` Michal Kubecek
  2018-05-17  9:29   ` Greg Kroah-Hartman
@ 2018-05-17  9:34   ` Greg Kroah-Hartman
  2018-05-17  9:55     ` Eric Dumazet
  1 sibling, 1 reply; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-17  9:34 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
  Cc: Michal Kubecek, netfilter-devel, coreteam, netdev

When allocating a xt_table_info structure, we should be clearing out the
full amount of memory that was allocated, not just the "header" of the
structure.  Otherwise odd values could be passed to userspace, which is
not a good thing.

Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
v2: use kvzalloc instead of kvmalloc/memset pair, as suggested by Michal Kubecek

 net/netfilter/x_tables.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index cb7cb300c3bc..cd22bb9b66f3 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
 	 * than shoot all processes down before realizing there is nothing
 	 * more to reclaim.
 	 */
-	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
+	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
 	if (!info)
 		return NULL;
 
-	memset(info, 0, sizeof(*info));
 	info->size = size;
 	return info;
 }
-- 
2.17.0

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-17  9:34   ` [PATCH v2] " Greg Kroah-Hartman
@ 2018-05-17  9:55     ` Eric Dumazet
  2018-05-17 10:09       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 19+ messages in thread
From: Eric Dumazet @ 2018-05-17  9:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Pablo Neira Ayuso, Jozsef Kadlecsik,
	Florian Westphal
  Cc: Michal Kubecek, netfilter-devel, coreteam, netdev



On 05/17/2018 02:34 AM, Greg Kroah-Hartman wrote:
> When allocating a xt_table_info structure, we should be clearing out the
> full amount of memory that was allocated, not just the "header" of the
> structure.  Otherwise odd values could be passed to userspace, which is
> not a good thing.
> 
> Cc: stable <stable@vger.kernel.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
> v2: use kvzalloc instead of kvmalloc/memset pair, as suggested by Michal Kubecek
> 
>  net/netfilter/x_tables.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index cb7cb300c3bc..cd22bb9b66f3 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
>  	 * than shoot all processes down before realizing there is nothing
>  	 * more to reclaim.
>  	 */
> -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
>  	if (!info)
>  		return NULL;
>  
> -	memset(info, 0, sizeof(*info));
>  	info->size = size;
>  	return info;
>  }
> 

I am curious, what particular path does not later overwrite the whole zone ?

Do not get me wrong, this is not fast path, but these blobs can be huge.

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-17  9:55     ` Eric Dumazet
@ 2018-05-17 10:09       ` Greg Kroah-Hartman
  2018-05-17 10:42         ` Jan Engelhardt
  0 siblings, 1 reply; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-17 10:09 UTC (permalink / raw)
  To: Eric Dumazet, Greg Hackmann
  Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
	Michal Kubecek, netfilter-devel, coreteam, netdev

On Thu, May 17, 2018 at 02:55:42AM -0700, Eric Dumazet wrote:
> 
> 
> On 05/17/2018 02:34 AM, Greg Kroah-Hartman wrote:
> > When allocating a xt_table_info structure, we should be clearing out the
> > full amount of memory that was allocated, not just the "header" of the
> > structure.  Otherwise odd values could be passed to userspace, which is
> > not a good thing.
> > 
> > Cc: stable <stable@vger.kernel.org>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > ---
> > v2: use kvzalloc instead of kvmalloc/memset pair, as suggested by Michal Kubecek
> > 
> >  net/netfilter/x_tables.c | 3 +--
> >  1 file changed, 1 insertion(+), 2 deletions(-)
> > 
> > diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> > index cb7cb300c3bc..cd22bb9b66f3 100644
> > --- a/net/netfilter/x_tables.c
> > +++ b/net/netfilter/x_tables.c
> > @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
> >  	 * than shoot all processes down before realizing there is nothing
> >  	 * more to reclaim.
> >  	 */
> > -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> >  	if (!info)
> >  		return NULL;
> >  
> > -	memset(info, 0, sizeof(*info));
> >  	info->size = size;
> >  	return info;
> >  }
> > 
> 
> I am curious, what particular path does not later overwrite the whole zone ?

The path back was long, adding Greg Hackman who helped to debug this to
the To: to confirm that I got this correct...

In do_ipt_get_ctl, the IPT_SO_GET_ENTRIES: option uses a len value that
can be larger than the size of the structure itself.

Then the data is copied to userspace in copy_entries_to_user() for ipv4
and v6, and that's where the "bad data" was noticed (a researcher was
using a kernel patch to determine what the data was)

Greg, that's the correct path here, right?

> Do not get me wrong, this is not fast path, but these blobs can be huge.

Yeah, I bet, but for "normal" cases the size should be small and all
should be fine.

thanks,

greg k-h

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-17 10:09       ` Greg Kroah-Hartman
@ 2018-05-17 10:42         ` Jan Engelhardt
  2018-05-17 13:20           ` Greg Kroah-Hartman
  0 siblings, 1 reply; 19+ messages in thread
From: Jan Engelhardt @ 2018-05-17 10:42 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	Florian Westphal, Michal Kubecek, netfilter-devel, coreteam,
	netdev


On Thursday 2018-05-17 12:09, Greg Kroah-Hartman wrote:
>> > --- a/net/netfilter/x_tables.c
>> > +++ b/net/netfilter/x_tables.c
>> > @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
>> >  	 * than shoot all processes down before realizing there is nothing
>> >  	 * more to reclaim.
>> >  	 */
>> > -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
>> > +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
>> >  	if (!info)
>> >  		return NULL;
>>
>> I am curious, what particular path does not later overwrite the whole zone ?
>
>In do_ipt_get_ctl, the IPT_SO_GET_ENTRIES: option uses a len value that
>can be larger than the size of the structure itself.
>
>Then the data is copied to userspace in copy_entries_to_user() for ipv4
>and v6, and that's where the "bad data"

If the kernel incorrectly copies more bytes than it should, isn't that
a sign that may be going going past the end of the info buffer?
(And thus, zeroing won't truly fix the issue)

And if the kernel copies too few (because it just does not have more
data than userspace is requesting), what remains in the user buffer
is the garbage that originally was there.

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-17 10:42         ` Jan Engelhardt
@ 2018-05-17 13:20           ` Greg Kroah-Hartman
  2018-05-18  9:27             ` Florian Westphal
  0 siblings, 1 reply; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-17 13:20 UTC (permalink / raw)
  To: Jan Engelhardt
  Cc: Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	Florian Westphal, Michal Kubecek, netfilter-devel, coreteam,
	netdev

On Thu, May 17, 2018 at 12:42:00PM +0200, Jan Engelhardt wrote:
> 
> On Thursday 2018-05-17 12:09, Greg Kroah-Hartman wrote:
> >> > --- a/net/netfilter/x_tables.c
> >> > +++ b/net/netfilter/x_tables.c
> >> > @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
> >> >  	 * than shoot all processes down before realizing there is nothing
> >> >  	 * more to reclaim.
> >> >  	 */
> >> > -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> >> > +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> >> >  	if (!info)
> >> >  		return NULL;
> >>
> >> I am curious, what particular path does not later overwrite the whole zone ?
> >
> >In do_ipt_get_ctl, the IPT_SO_GET_ENTRIES: option uses a len value that
> >can be larger than the size of the structure itself.
> >
> >Then the data is copied to userspace in copy_entries_to_user() for ipv4
> >and v6, and that's where the "bad data"
> 
> If the kernel incorrectly copies more bytes than it should, isn't that
> a sign that may be going going past the end of the info buffer?
> (And thus, zeroing won't truly fix the issue)

No, the buffer size is correct, we just aren't filling up the whole
buffer as the data requested is smaller than the buffer size.

thanks,

greg k-h

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-17 13:20           ` Greg Kroah-Hartman
@ 2018-05-18  9:27             ` Florian Westphal
  2018-05-18 11:04               ` Greg Kroah-Hartman
  2018-05-26 14:54               ` Greg Kroah-Hartman
  0 siblings, 2 replies; 19+ messages in thread
From: Florian Westphal @ 2018-05-18  9:27 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Jan Engelhardt, Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso,
	Jozsef Kadlecsik, Florian Westphal, Michal Kubecek,
	netfilter-devel, coreteam, netdev

Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> On Thu, May 17, 2018 at 12:42:00PM +0200, Jan Engelhardt wrote:
> > 
> > On Thursday 2018-05-17 12:09, Greg Kroah-Hartman wrote:
> > >> > --- a/net/netfilter/x_tables.c
> > >> > +++ b/net/netfilter/x_tables.c
> > >> > @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
> > >> >  	 * than shoot all processes down before realizing there is nothing
> > >> >  	 * more to reclaim.
> > >> >  	 */
> > >> > -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > >> > +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > >> >  	if (!info)
> > >> >  		return NULL;
> > >>
> > >> I am curious, what particular path does not later overwrite the whole zone ?
> > >
> > >In do_ipt_get_ctl, the IPT_SO_GET_ENTRIES: option uses a len value that
> > >can be larger than the size of the structure itself.
> > >
> > >Then the data is copied to userspace in copy_entries_to_user() for ipv4
> > >and v6, and that's where the "bad data"
> > 
> > If the kernel incorrectly copies more bytes than it should, isn't that
> > a sign that may be going going past the end of the info buffer?
> > (And thus, zeroing won't truly fix the issue)
> 
> No, the buffer size is correct, we just aren't filling up the whole
> buffer as the data requested is smaller than the buffer size.

I have no objections to the patch but I'd like to understand what
problem its fixing.

Normal pattern is:
newinfo = xt_alloc_table_info(tmp.size);
copy_from_user(newinfo->entries, user + sizeof(tmp), tmp.size);

So inital value of the rule blob area should not matter.

Furthermore, when copying the rule blob back to userspace,
the kernel is not supposed to copy any padding back to userspace either,
since commit f32815d21d4d8287336fb9cef4d2d9e0866214c2 only the
user-relevant parts should be copied (some matches and targets allocate
kernel-private data such as pointers, and we did use to leak such pointer
values back to userspace).

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-18  9:27             ` Florian Westphal
@ 2018-05-18 11:04               ` Greg Kroah-Hartman
  2018-05-26 14:54               ` Greg Kroah-Hartman
  1 sibling, 0 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-18 11:04 UTC (permalink / raw)
  To: Florian Westphal
  Cc: Jan Engelhardt, Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso,
	Jozsef Kadlecsik, Michal Kubecek, netfilter-devel, coreteam,
	netdev

On Fri, May 18, 2018 at 11:27:56AM +0200, Florian Westphal wrote:
> Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> > On Thu, May 17, 2018 at 12:42:00PM +0200, Jan Engelhardt wrote:
> > > 
> > > On Thursday 2018-05-17 12:09, Greg Kroah-Hartman wrote:
> > > >> > --- a/net/netfilter/x_tables.c
> > > >> > +++ b/net/netfilter/x_tables.c
> > > >> > @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
> > > >> >  	 * than shoot all processes down before realizing there is nothing
> > > >> >  	 * more to reclaim.
> > > >> >  	 */
> > > >> > -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > > >> > +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > > >> >  	if (!info)
> > > >> >  		return NULL;
> > > >>
> > > >> I am curious, what particular path does not later overwrite the whole zone ?
> > > >
> > > >In do_ipt_get_ctl, the IPT_SO_GET_ENTRIES: option uses a len value that
> > > >can be larger than the size of the structure itself.
> > > >
> > > >Then the data is copied to userspace in copy_entries_to_user() for ipv4
> > > >and v6, and that's where the "bad data"
> > > 
> > > If the kernel incorrectly copies more bytes than it should, isn't that
> > > a sign that may be going going past the end of the info buffer?
> > > (And thus, zeroing won't truly fix the issue)
> > 
> > No, the buffer size is correct, we just aren't filling up the whole
> > buffer as the data requested is smaller than the buffer size.
> 
> I have no objections to the patch but I'd like to understand what
> problem its fixing.
> 
> Normal pattern is:
> newinfo = xt_alloc_table_info(tmp.size);
> copy_from_user(newinfo->entries, user + sizeof(tmp), tmp.size);
> 
> So inital value of the rule blob area should not matter.
> 
> Furthermore, when copying the rule blob back to userspace,
> the kernel is not supposed to copy any padding back to userspace either,
> since commit f32815d21d4d8287336fb9cef4d2d9e0866214c2 only the
> user-relevant parts should be copied (some matches and targets allocate
> kernel-private data such as pointers, and we did use to leak such pointer
> values back to userspace).

Ah, fun, commit f32815d21d4d ("xtables: add xt_match, xt_target and data
copy_to_user functions") showed up in 4.11 and this was reported in 4.4 :(

However, the "bad" code path seems to be from the IPT_SO_GET_ENTRIES
request, which does not look to use the new functions provided in
f32815d21d4d, or am I mistaken?

Let me go work on a reproducer for this to make it a lot more obvious
what is happening, and if it is still even an issue after f32815d21d4d
is applied to a kernel.  Sorry for not providing that in the first
place...

thanks,

greg k-h

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-18  9:27             ` Florian Westphal
  2018-05-18 11:04               ` Greg Kroah-Hartman
@ 2018-05-26 14:54               ` Greg Kroah-Hartman
       [not found]                 ` <CANZU63WyNL4qUJx2eS3gokPMBJLn5=C4-bnOSEF5trX3jGngUA@mail.gmail.com>
  1 sibling, 1 reply; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-26 14:54 UTC (permalink / raw)
  To: Florian Westphal, Peter Pi
  Cc: Jan Engelhardt, Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso,
	Jozsef Kadlecsik, Michal Kubecek, netfilter-devel, coreteam,
	netdev

On Fri, May 18, 2018 at 11:27:56AM +0200, Florian Westphal wrote:
> Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> > On Thu, May 17, 2018 at 12:42:00PM +0200, Jan Engelhardt wrote:
> > > 
> > > On Thursday 2018-05-17 12:09, Greg Kroah-Hartman wrote:
> > > >> > --- a/net/netfilter/x_tables.c
> > > >> > +++ b/net/netfilter/x_tables.c
> > > >> > @@ -1183,11 +1183,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
> > > >> >  	 * than shoot all processes down before realizing there is nothing
> > > >> >  	 * more to reclaim.
> > > >> >  	 */
> > > >> > -	info = kvmalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > > >> > +	info = kvzalloc(sz, GFP_KERNEL | __GFP_NORETRY);
> > > >> >  	if (!info)
> > > >> >  		return NULL;
> > > >>
> > > >> I am curious, what particular path does not later overwrite the whole zone ?
> > > >
> > > >In do_ipt_get_ctl, the IPT_SO_GET_ENTRIES: option uses a len value that
> > > >can be larger than the size of the structure itself.
> > > >
> > > >Then the data is copied to userspace in copy_entries_to_user() for ipv4
> > > >and v6, and that's where the "bad data"
> > > 
> > > If the kernel incorrectly copies more bytes than it should, isn't that
> > > a sign that may be going going past the end of the info buffer?
> > > (And thus, zeroing won't truly fix the issue)
> > 
> > No, the buffer size is correct, we just aren't filling up the whole
> > buffer as the data requested is smaller than the buffer size.
> 
> I have no objections to the patch but I'd like to understand what
> problem its fixing.
> 
> Normal pattern is:
> newinfo = xt_alloc_table_info(tmp.size);
> copy_from_user(newinfo->entries, user + sizeof(tmp), tmp.size);
> 
> So inital value of the rule blob area should not matter.
> 
> Furthermore, when copying the rule blob back to userspace,
> the kernel is not supposed to copy any padding back to userspace either,
> since commit f32815d21d4d8287336fb9cef4d2d9e0866214c2 only the
> user-relevant parts should be copied (some matches and targets allocate
> kernel-private data such as pointers, and we did use to leak such pointer
> values back to userspace).

Adding Peter to this thread, as he originally reported this issue to
Google back in February.

Peter, I know you reported this against the 4.4 kernel tree, but since
then, commit f32815d21d4d ("xtables: add xt_match, xt_target and data
copy_to_user functions") has been added to the kernel in release 4.11.
In digging through this crazy code path, I think the issue is still
there, but can not verify it for sure.

Is there any way you can run your tests on the 4.14 or newer kernel tree
to see if this issue really is fixed or not?

thanks,

greg k-h

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
       [not found]                 ` <CANZU63WyNL4qUJx2eS3gokPMBJLn5=C4-bnOSEF5trX3jGngUA@mail.gmail.com>
@ 2018-05-31  8:24                   ` Florian Westphal
  2018-05-31  8:51                     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 19+ messages in thread
From: Florian Westphal @ 2018-05-31  8:24 UTC (permalink / raw)
  To: peter pi
  Cc: Greg Kroah-Hartman, Florian Westphal, Jan Engelhardt,
	Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	Michal Kubecek, netfilter-devel, coreteam, netdev

peter pi <tiangangpi@gmail.com> wrote:
> Hi Greg, I applied this patch on 4.4 and tested it on my Pixel 2, it seems
> the problem still exists,

What is the problem exactly?

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-31  8:24                   ` Florian Westphal
@ 2018-05-31  8:51                     ` Greg Kroah-Hartman
  2018-05-31  9:07                       ` Florian Westphal
       [not found]                       ` <CANZU63VE7fWNL+PJrLp7-5PBS6R6RQPvhw2QgqAK8NhX4uQc9Q@mail.gmail.com>
  0 siblings, 2 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-31  8:51 UTC (permalink / raw)
  To: Florian Westphal
  Cc: peter pi, Jan Engelhardt, Eric Dumazet, Greg Hackmann,
	Pablo Neira Ayuso, Jozsef Kadlecsik, Michal Kubecek,
	netfilter-devel, coreteam, netdev

On Thu, May 31, 2018 at 10:24:36AM +0200, Florian Westphal wrote:
> peter pi <tiangangpi@gmail.com> wrote:
> > Hi Greg, I applied this patch on 4.4 and tested it on my Pixel 2, it seems
> > the problem still exists,
> 
> What is the problem exactly?

The problem is that kernel data is being sent to userspace due to an
uncleared buffer that was allocated and then copied to userspace.  This
can be reproduced by dumping the current set of iptables rules.  Peter
had an example reproducing script that he used to specifically show
this.  Peter, can you provide that?

I thought that initializing this buffer to zero would solve the problem,
but I guess I cleared the wrong buffer :(

thanks,

greg k-h

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-31  8:51                     ` Greg Kroah-Hartman
@ 2018-05-31  9:07                       ` Florian Westphal
  2018-05-31 10:11                         ` Greg Kroah-Hartman
       [not found]                       ` <CANZU63VE7fWNL+PJrLp7-5PBS6R6RQPvhw2QgqAK8NhX4uQc9Q@mail.gmail.com>
  1 sibling, 1 reply; 19+ messages in thread
From: Florian Westphal @ 2018-05-31  9:07 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Florian Westphal, peter pi, Jan Engelhardt, Eric Dumazet,
	Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	Michal Kubecek, netfilter-devel, coreteam, netdev

Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> On Thu, May 31, 2018 at 10:24:36AM +0200, Florian Westphal wrote:
> > peter pi <tiangangpi@gmail.com> wrote:
> > > Hi Greg, I applied this patch on 4.4 and tested it on my Pixel 2, it seems
> > > the problem still exists,
> > 
> > What is the problem exactly?
> 
> The problem is that kernel data is being sent to userspace due to an
> uncleared buffer that was allocated and then copied to userspace.  This
> can be reproduced by dumping the current set of iptables rules.  Peter
> had an example reproducing script that he used to specifically show
> this.  Peter, can you provide that?
> 
> I thought that initializing this buffer to zero would solve the problem,
> but I guess I cleared the wrong buffer :(

Never mind, this test was on 4.4 not 4.14.

But even on 4.14 i don't see how zeroing a buffer that will
be filled via copy_from_user would help.

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-31  9:07                       ` Florian Westphal
@ 2018-05-31 10:11                         ` Greg Kroah-Hartman
  0 siblings, 0 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-31 10:11 UTC (permalink / raw)
  To: Florian Westphal
  Cc: peter pi, Jan Engelhardt, Eric Dumazet, Greg Hackmann,
	Pablo Neira Ayuso, Jozsef Kadlecsik, Michal Kubecek,
	netfilter-devel, coreteam, netdev

On Thu, May 31, 2018 at 11:07:58AM +0200, Florian Westphal wrote:
> Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
> > On Thu, May 31, 2018 at 10:24:36AM +0200, Florian Westphal wrote:
> > > peter pi <tiangangpi@gmail.com> wrote:
> > > > Hi Greg, I applied this patch on 4.4 and tested it on my Pixel 2, it seems
> > > > the problem still exists,
> > > 
> > > What is the problem exactly?
> > 
> > The problem is that kernel data is being sent to userspace due to an
> > uncleared buffer that was allocated and then copied to userspace.  This
> > can be reproduced by dumping the current set of iptables rules.  Peter
> > had an example reproducing script that he used to specifically show
> > this.  Peter, can you provide that?
> > 
> > I thought that initializing this buffer to zero would solve the problem,
> > but I guess I cleared the wrong buffer :(
> 
> Never mind, this test was on 4.4 not 4.14.
> 
> But even on 4.14 i don't see how zeroing a buffer that will
> be filled via copy_from_user would help.

It should be copy_to_user() :)

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
       [not found]                       ` <CANZU63VE7fWNL+PJrLp7-5PBS6R6RQPvhw2QgqAK8NhX4uQc9Q@mail.gmail.com>
@ 2018-05-31 11:23                         ` Greg Kroah-Hartman
  2018-05-31 11:32                         ` Michal Kubecek
  1 sibling, 0 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-31 11:23 UTC (permalink / raw)
  To: peter pi
  Cc: Florian Westphal, Jan Engelhardt, Eric Dumazet, Greg Hackmann,
	Pablo Neira Ayuso, Jozsef Kadlecsik, Michal Kubecek,
	netfilter-devel, coreteam, netdev

On Thu, May 31, 2018 at 05:40:40PM +0800, peter pi wrote:
> Hi Greg,
> 
> My test method is very simple:
> 1, In copy_to_user, add a function call like my_examine(from, n) to check
> every 8 bytes. There is an kernel function called  virt_addr_valid which
> can check if the value is a address value.
> 2, Print a kernel log when there is a leak detected in function my_examine
> 3, Run iptables-save or ip6tables-save in shell, it will hit the kernel
> code path of the problem
> 
> 
> Because my test code is specified for Pixel 2, so I think you can write the
> test code yourself just about 10 lines code

Any chance you can test this on a more modern kernel, like 4.14 or
newer on a normal system?

thanks,

greg k-h

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
       [not found]                       ` <CANZU63VE7fWNL+PJrLp7-5PBS6R6RQPvhw2QgqAK8NhX4uQc9Q@mail.gmail.com>
  2018-05-31 11:23                         ` Greg Kroah-Hartman
@ 2018-05-31 11:32                         ` Michal Kubecek
  2018-05-31 11:55                           ` Michal Kubecek
  1 sibling, 1 reply; 19+ messages in thread
From: Michal Kubecek @ 2018-05-31 11:32 UTC (permalink / raw)
  To: peter pi
  Cc: Greg Kroah-Hartman, Florian Westphal, Jan Engelhardt,
	Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	netfilter-devel, coreteam, netdev

On Thu, May 31, 2018 at 05:40:40PM +0800, peter pi wrote:
> 
> My test method is very simple:
> 1, In copy_to_user, add a function call like my_examine(from, n) to check
> every 8 bytes. There is an kernel function called  virt_addr_valid which
> can check if the value is a address value.
> 2, Print a kernel log when there is a leak detected in function my_examine
> 3, Run iptables-save or ip6tables-save in shell, it will hit the kernel
> code path of the problem

I think I start to understand the problem. IPT_SO_GET_ENTRIES leads to
calling copy_entries_to_user() which copies the entries as they are to
user provided buffer. It also copies instances of struct xt_entry_match
and struct xt_entry_target which contain kernel pointers. We then
rewrite them with match/target name for userspace but the layout looks
(on x86_64) like this

/* offset    |  size */  type = struct xt_entry_match {
/*    0      |    32 */    union {
/*                32 */        struct {
/*    0      |     2 */            __u16 match_size;
/*    2      |    29 */            char name[29];
/*   31      |     1 */            __u8 revision;

                                   /* total size (bytes):   32 */
                               } user;
/*                16 */        struct {
/*    0      |     2 */            __u16 match_size;
/* XXX  6-byte hole  */
/*    8      |     8 */            struct xt_match *match;

                                   /* total size (bytes):   16 */
                               } kernel;
/*                 2 */        __u16 match_size;

                               /* total size (bytes):   32 */
                           } u;
/*   32      |     0 */    unsigned char data[];

                           /* total size (bytes):   32 */
                         }


so that if match name is no longer than five characters (which is often
the case), writing to .u.user.name leaves .u.kernel.match untouched. The
same problem exists in struct xt_entry_target.

Unless there are other kernel pointers leaked, the solution should be
simple: explicitly zero the copy of .u.kernel.match (.u.kernel.target)
before we copy the name. I haven't checked yet if compat_ code path
suffers from the same problem.

Michal Kubecek

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-31 11:32                         ` Michal Kubecek
@ 2018-05-31 11:55                           ` Michal Kubecek
  2018-05-31 16:25                             ` Greg Kroah-Hartman
  0 siblings, 1 reply; 19+ messages in thread
From: Michal Kubecek @ 2018-05-31 11:55 UTC (permalink / raw)
  To: peter pi
  Cc: Greg Kroah-Hartman, Florian Westphal, Jan Engelhardt,
	Eric Dumazet, Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	netfilter-devel, coreteam, netdev

On Thu, May 31, 2018 at 01:32:16PM +0200, Michal Kubecek wrote:
> I think I start to understand the problem. IPT_SO_GET_ENTRIES leads to
> calling copy_entries_to_user() which copies the entries as they are to
> user provided buffer. It also copies instances of struct xt_entry_match
> and struct xt_entry_target which contain kernel pointers. We then
> rewrite them with match/target name for userspace but the layout looks
> (on x86_64) like this
> 
> /* offset    |  size */  type = struct xt_entry_match {
> /*    0      |    32 */    union {
> /*                32 */        struct {
> /*    0      |     2 */            __u16 match_size;
> /*    2      |    29 */            char name[29];
> /*   31      |     1 */            __u8 revision;
> 
>                                    /* total size (bytes):   32 */
>                                } user;
> /*                16 */        struct {
> /*    0      |     2 */            __u16 match_size;
> /* XXX  6-byte hole  */
> /*    8      |     8 */            struct xt_match *match;
> 
>                                    /* total size (bytes):   16 */
>                                } kernel;
> /*                 2 */        __u16 match_size;
> 
>                                /* total size (bytes):   32 */
>                            } u;
> /*   32      |     0 */    unsigned char data[];
> 
>                            /* total size (bytes):   32 */
>                          }
> 
> 
> so that if match name is no longer than five characters (which is often
> the case), writing to .u.user.name leaves .u.kernel.match untouched. The
> same problem exists in struct xt_entry_target.

And this should no longer happen since the series

 f32815d21d4d ("xtables: add xt_match, xt_target and data copy_to_user functions")
 f77bc5b23fb1 ("iptables: use match, target and data copy_to_user helpers")
 e47ddb2c4691 ("ip6tables: use match, target and data copy_to_user helpers")
 244b531bee2b ("arptables: use match, target and data copy_to_user helpers")
 b5040f6c33a5 ("ebtables: use match, target and data copy_to_user helpers")
 4915f7bbc402 ("xtables: use match, target and data copy_to_user helpers in compat")
 ec2318904965 ("xtables: extend matches and targets with .usersize")

changed the logic in 4.11-rc1.

Michal Kubecek

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

* Re: [PATCH v2] netfilter: properly initialize xt_table_info structure
  2018-05-31 11:55                           ` Michal Kubecek
@ 2018-05-31 16:25                             ` Greg Kroah-Hartman
  0 siblings, 0 replies; 19+ messages in thread
From: Greg Kroah-Hartman @ 2018-05-31 16:25 UTC (permalink / raw)
  To: Michal Kubecek
  Cc: peter pi, Florian Westphal, Jan Engelhardt, Eric Dumazet,
	Greg Hackmann, Pablo Neira Ayuso, Jozsef Kadlecsik,
	netfilter-devel, coreteam, netdev

On Thu, May 31, 2018 at 01:55:57PM +0200, Michal Kubecek wrote:
> On Thu, May 31, 2018 at 01:32:16PM +0200, Michal Kubecek wrote:
> > I think I start to understand the problem. IPT_SO_GET_ENTRIES leads to
> > calling copy_entries_to_user() which copies the entries as they are to
> > user provided buffer. It also copies instances of struct xt_entry_match
> > and struct xt_entry_target which contain kernel pointers. We then
> > rewrite them with match/target name for userspace but the layout looks
> > (on x86_64) like this
> > 
> > /* offset    |  size */  type = struct xt_entry_match {
> > /*    0      |    32 */    union {
> > /*                32 */        struct {
> > /*    0      |     2 */            __u16 match_size;
> > /*    2      |    29 */            char name[29];
> > /*   31      |     1 */            __u8 revision;
> > 
> >                                    /* total size (bytes):   32 */
> >                                } user;
> > /*                16 */        struct {
> > /*    0      |     2 */            __u16 match_size;
> > /* XXX  6-byte hole  */
> > /*    8      |     8 */            struct xt_match *match;
> > 
> >                                    /* total size (bytes):   16 */
> >                                } kernel;
> > /*                 2 */        __u16 match_size;
> > 
> >                                /* total size (bytes):   32 */
> >                            } u;
> > /*   32      |     0 */    unsigned char data[];
> > 
> >                            /* total size (bytes):   32 */
> >                          }
> > 
> > 
> > so that if match name is no longer than five characters (which is often
> > the case), writing to .u.user.name leaves .u.kernel.match untouched. The
> > same problem exists in struct xt_entry_target.
> 
> And this should no longer happen since the series
> 
>  f32815d21d4d ("xtables: add xt_match, xt_target and data copy_to_user functions")
>  f77bc5b23fb1 ("iptables: use match, target and data copy_to_user helpers")
>  e47ddb2c4691 ("ip6tables: use match, target and data copy_to_user helpers")
>  244b531bee2b ("arptables: use match, target and data copy_to_user helpers")
>  b5040f6c33a5 ("ebtables: use match, target and data copy_to_user helpers")
>  4915f7bbc402 ("xtables: use match, target and data copy_to_user helpers in compat")
>  ec2318904965 ("xtables: extend matches and targets with .usersize")
> 
> changed the logic in 4.11-rc1.

Thank you so much for the detailed description.  And sorry for digging
up this old issue.  Peter, if you could verify that you do not see this
issue on a kernel newer than 4.11, that would be wonderful.

Michal, do you think it is worth backporting those commits to the 4.9.y
and 4.4.y stable kernels to remove this problem there?

thanks,

greg k-h

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

end of thread, other threads:[~2018-05-31 16:25 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-17  8:44 [PATCH] netfilter: properly initialize xt_table_info structure Greg Kroah-Hartman
2018-05-17  8:59 ` Michal Kubecek
2018-05-17  9:29   ` Greg Kroah-Hartman
2018-05-17  9:34   ` [PATCH v2] " Greg Kroah-Hartman
2018-05-17  9:55     ` Eric Dumazet
2018-05-17 10:09       ` Greg Kroah-Hartman
2018-05-17 10:42         ` Jan Engelhardt
2018-05-17 13:20           ` Greg Kroah-Hartman
2018-05-18  9:27             ` Florian Westphal
2018-05-18 11:04               ` Greg Kroah-Hartman
2018-05-26 14:54               ` Greg Kroah-Hartman
     [not found]                 ` <CANZU63WyNL4qUJx2eS3gokPMBJLn5=C4-bnOSEF5trX3jGngUA@mail.gmail.com>
2018-05-31  8:24                   ` Florian Westphal
2018-05-31  8:51                     ` Greg Kroah-Hartman
2018-05-31  9:07                       ` Florian Westphal
2018-05-31 10:11                         ` Greg Kroah-Hartman
     [not found]                       ` <CANZU63VE7fWNL+PJrLp7-5PBS6R6RQPvhw2QgqAK8NhX4uQc9Q@mail.gmail.com>
2018-05-31 11:23                         ` Greg Kroah-Hartman
2018-05-31 11:32                         ` Michal Kubecek
2018-05-31 11:55                           ` Michal Kubecek
2018-05-31 16:25                             ` Greg Kroah-Hartman

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.