Patchwork [1/4] netfilter: ipset: fix timeout value overflow bug

login
register
mail settings
Submitter Pablo Neira
Date May 14, 2012, 2:36 p.m.
Message ID <20120514143635.GA12992@1984>
Download mbox | patch
Permalink /patch/159029/
State Not Applicable
Headers show

Comments

Pablo Neira - May 14, 2012, 2:36 p.m.
On Mon, May 14, 2012 at 03:19:49PM +0100, David Laight wrote:
>  
> > --- a/include/linux/netfilter/ipset/ip_set_timeout.h
> > +++ b/include/linux/netfilter/ipset/ip_set_timeout.h
> > @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb)
> >  {
> >  	unsigned int timeout = ip_set_get_h32(tb);
> >  
> > +	/* Normalize to fit into jiffies */
> > +	if (timeout > UINT_MAX/1000)
> > +		timeout = UINT_MAX/1000;
> > +
> 
> Doesn't that rather assume that HZ is 1000 ?

Indeed. I overlooked that. Thanks David.

New patch attached fixing this. I've rebased my tree.

@Jozsef: BTW, why do we have

include/linux/netfilter/ipset/ip_set_timeout.h

living under include/linux ?

All definitions are private to the kernel. Why not moving that header
(and other similar) to include/net ?
Eric Dumazet - May 14, 2012, 2:47 p.m.
On Mon, 2012-05-14 at 16:36 +0200, Pablo Neira Ayuso wrote:
> On Mon, May 14, 2012 at 03:19:49PM +0100, David Laight wrote:
> >  
> > > --- a/include/linux/netfilter/ipset/ip_set_timeout.h
> > > +++ b/include/linux/netfilter/ipset/ip_set_timeout.h
> > > @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb)
> > >  {
> > >  	unsigned int timeout = ip_set_get_h32(tb);
> > >  
> > > +	/* Normalize to fit into jiffies */
> > > +	if (timeout > UINT_MAX/1000)
> > > +		timeout = UINT_MAX/1000;
> > > +
> > 
> > Doesn't that rather assume that HZ is 1000 ?
> 
> Indeed. I overlooked that. Thanks David.

I dont think so.

1000 here is really MSEC_PER_SEC

(All occurrences should be changed in this file)


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jozsef Kadlecsik - May 14, 2012, 5:45 p.m.
On Mon, 14 May 2012, Eric Dumazet wrote:

> On Mon, 2012-05-14 at 16:36 +0200, Pablo Neira Ayuso wrote:
> > On Mon, May 14, 2012 at 03:19:49PM +0100, David Laight wrote:
> > >  
> > > > --- a/include/linux/netfilter/ipset/ip_set_timeout.h
> > > > +++ b/include/linux/netfilter/ipset/ip_set_timeout.h
> > > > @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb)
> > > >  {
> > > >  	unsigned int timeout = ip_set_get_h32(tb);
> > > >  
> > > > +	/* Normalize to fit into jiffies */
> > > > +	if (timeout > UINT_MAX/1000)
> > > > +		timeout = UINT_MAX/1000;
> > > > +
> > > 
> > > Doesn't that rather assume that HZ is 1000 ?
> > 
> > Indeed. I overlooked that. Thanks David.
> 
> I dont think so.
> 
> 1000 here is really MSEC_PER_SEC
> 
> (All occurrences should be changed in this file)

Yes, exactly. Pablo, shall I produce a little patch or could you change 
1000 to MSEC_PER_SEC?

Best regards, 
Jozsef
-
E-mail  : kadlec@blackhole.kfki.hu, kadlecsik.jozsef@wigner.mta.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : Wigner Research Centre for Physics, Hungarian Academy of Sciences
          H-1525 Budapest 114, POB. 49, Hungary
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pablo Neira - May 14, 2012, 7 p.m.
On Mon, May 14, 2012 at 07:45:07PM +0200, Jozsef Kadlecsik wrote:
> On Mon, 14 May 2012, Eric Dumazet wrote:
> 
> > On Mon, 2012-05-14 at 16:36 +0200, Pablo Neira Ayuso wrote:
> > > On Mon, May 14, 2012 at 03:19:49PM +0100, David Laight wrote:
> > > >  
> > > > > --- a/include/linux/netfilter/ipset/ip_set_timeout.h
> > > > > +++ b/include/linux/netfilter/ipset/ip_set_timeout.h
> > > > > @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb)
> > > > >  {
> > > > >  	unsigned int timeout = ip_set_get_h32(tb);
> > > > >  
> > > > > +	/* Normalize to fit into jiffies */
> > > > > +	if (timeout > UINT_MAX/1000)
> > > > > +		timeout = UINT_MAX/1000;
> > > > > +
> > > > 
> > > > Doesn't that rather assume that HZ is 1000 ?
> > > 
> > > Indeed. I overlooked that. Thanks David.
> > 
> > I dont think so.
> > 
> > 1000 here is really MSEC_PER_SEC
> > 
> > (All occurrences should be changed in this file)
> 
> Yes, exactly. Pablo, shall I produce a little patch or could you change 
> 1000 to MSEC_PER_SEC?

I'll mangle this myself. No need to send a new patch.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Laight - May 15, 2012, 8:21 a.m.
> -----Original Message-----
> From: Eric Dumazet [mailto:eric.dumazet@gmail.com] 
> Sent: 14 May 2012 15:47
> To: Pablo Neira Ayuso
> Cc: David Laight; netfilter-devel@vger.kernel.org; 
> davem@davemloft.net; netdev@vger.kernel.org; Jozsef Kadlecsik
> Subject: Re: [PATCH 1/4] netfilter: ipset: fix timeout value 
> overflow bug
> 
> On Mon, 2012-05-14 at 16:36 +0200, Pablo Neira Ayuso wrote:
> > On Mon, May 14, 2012 at 03:19:49PM +0100, David Laight wrote:
> > >  
> > > > --- a/include/linux/netfilter/ipset/ip_set_timeout.h
> > > > +++ b/include/linux/netfilter/ipset/ip_set_timeout.h
> > > > @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb)
> > > >  {
> > > >  	unsigned int timeout = ip_set_get_h32(tb);
> > > >  
> > > > +	/* Normalize to fit into jiffies */
> > > > +	if (timeout > UINT_MAX/1000)
> > > > +		timeout = UINT_MAX/1000;
> > > > +
> > > 
> > > Doesn't that rather assume that HZ is 1000 ?
> > 
> > Indeed. I overlooked that. Thanks David.
> 
> I dont think so.
> 
> 1000 here is really MSEC_PER_SEC

I was just reading the comment above - which seemed to imply
the purpose of the code was to ensure the timeout wouldn't
exceeded 2^32 jiffies.

I tend to use variable names for timeouts/timestamps that
include the units - can make it more obvious when a divisor
is absent - and makes it more obvious what the literal
constants are converying beween.
After all, the number of milliseconds in a second isn't
subject to change :-)

	David


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

From bcb0e955ae5ea5acb1b59fb59e4fcb1c8364994d Mon Sep 17 00:00:00 2001
From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Date: Mon, 7 May 2012 02:35:44 +0000
Subject: [PATCH] netfilter: ipset: fix timeout value overflow bug

Large timeout parameters could result wrong timeout values due to
an overflow at msec to jiffies conversion (reported by Andreas Herz)

[ This patch was mangled by Pablo Neira Ayuso since David Laight notices
  that we were using hardcode 1000 instead of HZ to calculate the timeout ]

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/ipset/ip_set_timeout.h |    4 ++++
 net/netfilter/xt_set.c                         |   15 +++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
index 4792320..40a85b1 100644
--- a/include/linux/netfilter/ipset/ip_set_timeout.h
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -30,6 +30,10 @@  ip_set_timeout_uget(struct nlattr *tb)
 {
 	unsigned int timeout = ip_set_get_h32(tb);
 
+	/* Normalize to fit into jiffies */
+	if (timeout > UINT_MAX/HZ)
+		timeout = UINT_MAX/HZ;
+
 	/* Userspace supplied TIMEOUT parameter: adjust crazy size */
 	return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
 }
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index 0ec8138..15275e9 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -44,6 +44,14 @@  const struct ip_set_adt_opt n = {	\
 	.cmdflags = cfs,		\
 	.timeout = t,			\
 }
+#define ADT_MOPT(n, f, d, fs, cfs, t)	\
+struct ip_set_adt_opt n = {		\
+	.family	= f,			\
+	.dim = d,			\
+	.flags = fs,			\
+	.cmdflags = cfs,		\
+	.timeout = t,			\
+}
 
 /* Revision 0 interface: backward compatible with netfilter/iptables */
 
@@ -296,11 +304,14 @@  static unsigned int
 set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
 {
 	const struct xt_set_info_target_v2 *info = par->targinfo;
-	ADT_OPT(add_opt, par->family, info->add_set.dim,
-		info->add_set.flags, info->flags, info->timeout);
+	ADT_MOPT(add_opt, par->family, info->add_set.dim,
+		 info->add_set.flags, info->flags, info->timeout);
 	ADT_OPT(del_opt, par->family, info->del_set.dim,
 		info->del_set.flags, 0, UINT_MAX);
 
+	/* Normalize to fit into jiffies */
+	if (add_opt.timeout > UINT_MAX/HZ)
+		add_opt.timeout = UINT_MAX/HZ;
 	if (info->add_set.index != IPSET_INVALID_ID)
 		ip_set_add(info->add_set.index, skb, par, &add_opt);
 	if (info->del_set.index != IPSET_INVALID_ID)
-- 
1.7.10