[PATCH] xt_recent: Fix buffer overflow

Colin Ian King colin.king at canonical.com
Fri Feb 19 14:20:59 UTC 2010


On Fri, 2010-02-19 at 12:42 +0200, Amit Kucheria wrote:
> On 10 Feb 18, Tim Gardner wrote:
> > If this looks right, then I'll send it upstream, and it should be a
> > pre-stable patch.
> > 
> > rtg
> > -- 
> > Tim Gardner tim.gardner at canonical.com
> 
> > From 478a6cbbd7646c78370da48677e99cc602076dd7 Mon Sep 17 00:00:00 2001
> > From: Tim Gardner <tim.gardner at canonical.com>
> > Date: Thu, 18 Feb 2010 20:04:51 -0700
> > Subject: [PATCH] xt_recent: Fix buffer overflow
> > 
> > e->index overflows e->stamps[] every ip_pkt_list_tot
> > packets.
> > 
> > Consider the case when ip_pkt_list_tot==1; the first packet received is stored
> > in e->stamps[0] and e->index is initialized to 1. The next received packet
> > timestamp is then stored at e->stamps[1] in recent_entry_update(),
> > a buffer overflow because the maximum e->stamps[] index is 0.
> > 
> > Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
> > Cc: stable at kernel.org
> > ---
> >  net/netfilter/xt_recent.c |    2 +-
> >  1 files changed, 1 insertions(+), 1 deletions(-)
> > 
> > diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
> > index fc70a49..1bb0d6c 100644
> > --- a/net/netfilter/xt_recent.c
> > +++ b/net/netfilter/xt_recent.c
> > @@ -173,10 +173,10 @@ recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr,
> >  
> >  static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
> >  {
> > +	e->index %= ip_pkt_list_tot;
> >  	e->stamps[e->index++] = jiffies;
> >  	if (e->index > e->nstamps)
> >  		e->nstamps = e->index;
> > -	e->index %= ip_pkt_list_tot;
> >  	list_move_tail(&e->lru_list, &t->lru_list);
> >  }
> >  
> > -- 
> > 1.6.2.4
> > 
> 
> This is a little more tricky I thought.
> 
> A brief look at the code tells me that e->stamps[] is supposed to store
> 'ip_pkt_list_tot' number of timestamps according to,
> 
> 	e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot,
> 			    GFP_ATOMIC);
> 
> And e->index is the index into the next slot to store a timestamp in. Is that
> correct?
> 
> So, won't the kmalloc above actually assign 2 'unsigned longs' when
> ip_pkt_list_tot == 1, one due to sizeof(*e), the other due to
> sizeof(e->stamps[0]) * ip_pkt_list_tot ? If so, the original code is doing
> the right thing - of not letting index overflow for the _next_ call to
> recent_entry_update().

Not sure I'm with you on that Amit.  The struct contains a zero sized
array stamps[] - this array is exactly zero bytes in size. So the
kmalloc allocates just ip_pkt_list_tot number of unsigned longs.  Hence
when ip_pkt_list_tot == 1, only 1 unsigned long is allocated.

I like stefan's recommendations of:
 
e->stamps[e->index] = jiffies;
e->index = (e->index + 1) % ip_pkt_list_tot;

Colin
> 
> /Amit
> 
> -- 
> ----------------------------------------------------------------------
> Amit Kucheria, Kernel Engineer || amit.kucheria at canonical.com
> ----------------------------------------------------------------------
> 






More information about the kernel-team mailing list