fix fragment cache security hole
This commit is contained in:
parent
ec984a04ad
commit
0b6031033d
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_frag.c,v 1.22 2001/03/26 06:13:13 mike Exp $ */
|
||||
/* $NetBSD: ip_frag.c,v 1.23 2001/04/06 15:32:40 darrenr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1993-2000 by Darren Reed.
|
||||
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
#if !defined(lint)
|
||||
#if defined(__NetBSD__)
|
||||
static const char rcsid[] = "$NetBSD: ip_frag.c,v 1.22 2001/03/26 06:13:13 mike Exp $";
|
||||
static const char rcsid[] = "$NetBSD: ip_frag.c,v 1.23 2001/04/06 15:32:40 darrenr Exp $";
|
||||
#else
|
||||
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-2000 Darren Reed";
|
||||
static const char rcsid[] = "@(#)Id: ip_frag.c,v 2.10.2.7 2000/11/27 10:26:56 darrenr Exp";
|
||||
|
@ -147,12 +147,15 @@ fr_info_t *fin;
|
|||
u_int pass;
|
||||
ipfr_t *table[];
|
||||
{
|
||||
ipfr_t **fp, *fra, frag;
|
||||
u_int idx;
|
||||
ipfr_t **fp, *fra, frag;
|
||||
u_int idx, off;
|
||||
|
||||
if (ipfr_inuse >= IPFT_SIZE)
|
||||
return NULL;
|
||||
|
||||
if (!(fin->fin_fi.fi_fl & FI_FRAG))
|
||||
return NULL;
|
||||
|
||||
frag.ipfr_p = ip->ip_p;
|
||||
idx = ip->ip_p;
|
||||
frag.ipfr_id = ip->ip_id;
|
||||
|
@ -206,7 +209,10 @@ ipfr_t *table[];
|
|||
/*
|
||||
* Compute the offset of the expected start of the next packet.
|
||||
*/
|
||||
fra->ipfr_off = (ip->ip_off & IP_OFFMASK) + (fin->fin_dlen >> 3);
|
||||
off = ip->ip_off & IP_OFFMASK;
|
||||
if (!off)
|
||||
fra->ipfr_seen0 = 1;
|
||||
fra->ipfr_off = off + (fin->fin_dlen >> 3);
|
||||
ATOMIC_INCL(ipfr_stats.ifs_new);
|
||||
ATOMIC_INC32(ipfr_inuse);
|
||||
return fra;
|
||||
|
@ -262,6 +268,9 @@ ipfr_t *table[];
|
|||
ipfr_t *f, frag;
|
||||
u_int idx;
|
||||
|
||||
if (!(fin->fin_fi.fi_fl & FI_FRAG))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* For fragments, we record protocol, packet id, TOS and both IP#'s
|
||||
* (these should all be the same for all fragments of a packet).
|
||||
|
@ -289,6 +298,19 @@ ipfr_t *table[];
|
|||
IPFR_CMPSZ)) {
|
||||
u_short atoff, off;
|
||||
|
||||
/*
|
||||
* XXX - We really need to be guarding against the
|
||||
* retransmission of (src,dst,id,offset-range) here
|
||||
* because a fragmented packet is never resent with
|
||||
* the same IP ID#.
|
||||
*/
|
||||
off = ip->ip_off & IP_OFFMASK;
|
||||
if (f->ipfr_seen0) {
|
||||
if (!off || (fin->fin_fi.fi_fl & FI_SHORT))
|
||||
continue;
|
||||
} else if (!off)
|
||||
f->ipfr_seen0 = 1;
|
||||
|
||||
if (f != table[idx]) {
|
||||
/*
|
||||
* move fragment info. to the top of the list
|
||||
|
@ -301,7 +323,6 @@ ipfr_t *table[];
|
|||
f->ipfr_prev = NULL;
|
||||
table[idx] = f;
|
||||
}
|
||||
off = ip->ip_off & IP_OFFMASK;
|
||||
atoff = off + (fin->fin_dlen >> 3);
|
||||
/*
|
||||
* If we've follwed the fragments, and this is the
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_frag.h,v 1.15 2001/03/26 06:13:13 mike Exp $ */
|
||||
/* $NetBSD: ip_frag.h,v 1.16 2001/04/06 15:32:40 darrenr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1993-2000 by Darren Reed.
|
||||
|
@ -26,7 +26,8 @@ typedef struct ipfr {
|
|||
u_char ipfr_p;
|
||||
u_char ipfr_tos;
|
||||
u_short ipfr_off;
|
||||
u_short ipfr_ttl;
|
||||
u_char ipfr_ttl;
|
||||
u_char ipfr_seen0;
|
||||
frentry_t *ipfr_rule;
|
||||
} ipfr_t;
|
||||
|
||||
|
@ -42,7 +43,8 @@ typedef struct ipfrstat {
|
|||
struct ipfr **ifs_nattab;
|
||||
} ipfrstat_t;
|
||||
|
||||
#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1)
|
||||
#define IPFR_CMPSZ (offsetof(ipfr_t, ipfr_off) - \
|
||||
offsetof(ipfr_t, ipfr_src))
|
||||
|
||||
extern int fr_ipfrttl;
|
||||
extern int fr_frag_lock;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_nat.c,v 1.38 2001/03/26 06:13:13 mike Exp $ */
|
||||
/* $NetBSD: ip_nat.c,v 1.39 2001/04/06 15:32:41 darrenr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995-2000 by Darren Reed.
|
||||
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
#if !defined(lint)
|
||||
#if defined(__NetBSD__)
|
||||
static const char rcsid[] = "$NetBSD: ip_nat.c,v 1.38 2001/03/26 06:13:13 mike Exp $";
|
||||
static const char rcsid[] = "$NetBSD: ip_nat.c,v 1.39 2001/04/06 15:32:41 darrenr Exp $";
|
||||
#else
|
||||
static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed";
|
||||
static const char rcsid[] = "@(#)Id: ip_nat.c,v 2.37.2.32 2001/01/10 06:19:11 darrenr Exp";
|
||||
|
@ -2282,7 +2282,8 @@ maskloop:
|
|||
*/
|
||||
if (nat) {
|
||||
np = nat->nat_ptr;
|
||||
if (natadd && fin->fin_fi.fi_fl & FI_FRAG)
|
||||
if (natadd && (fin->fin_fi.fi_fl & FI_FRAG) &&
|
||||
np && (np->in_flags & IPN_FRAG))
|
||||
ipfr_nat_newfrag(ip, fin, 0, nat);
|
||||
MUTEX_ENTER(&nat->nat_lock);
|
||||
nat->nat_age = fr_defnatage;
|
||||
|
@ -2487,7 +2488,8 @@ maskloop:
|
|||
if (nat) {
|
||||
np = nat->nat_ptr;
|
||||
fin->fin_fr = nat->nat_fr;
|
||||
if (natadd && fin->fin_fi.fi_fl & FI_FRAG)
|
||||
if (natadd && (fin->fin_fi.fi_fl & FI_FRAG) &&
|
||||
np && (np->in_flags & IPN_FRAG))
|
||||
ipfr_nat_newfrag(ip, fin, 0, nat);
|
||||
if ((np->in_apr != NULL) && (np->in_dport == 0 ||
|
||||
(tcp != NULL && sport == np->in_dport))) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_nat.h,v 1.22 2001/03/26 06:13:13 mike Exp $ */
|
||||
/* $NetBSD: ip_nat.h,v 1.23 2001/04/06 15:32:41 darrenr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995-2000 by Darren Reed.
|
||||
|
@ -228,6 +228,7 @@ typedef struct natstat {
|
|||
#define IPN_ROUNDR 0x100
|
||||
#define IPN_NOTSRC 0x080000
|
||||
#define IPN_NOTDST 0x100000
|
||||
#define IPN_FRAG 0x200000
|
||||
|
||||
|
||||
typedef struct natlog {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_state.c,v 1.29 2001/03/26 06:13:14 mike Exp $ */
|
||||
/* $NetBSD: ip_state.c,v 1.30 2001/04/06 15:32:41 darrenr Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995-2000 by Darren Reed.
|
||||
|
@ -9,7 +9,7 @@
|
|||
*/
|
||||
#if !defined(lint)
|
||||
#if defined(__NetBSD__)
|
||||
static const char rcsid[] = "$NetBSD: ip_state.c,v 1.29 2001/03/26 06:13:14 mike Exp $";
|
||||
static const char rcsid[] = "$NetBSD: ip_state.c,v 1.30 2001/04/06 15:32:41 darrenr Exp $";
|
||||
#else
|
||||
static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
|
||||
static const char rcsid[] = "@(#)Id: ip_state.c,v 2.30.2.28 2001/01/08 14:04:46 darrenr Exp";
|
||||
|
@ -690,7 +690,7 @@ u_int flags;
|
|||
#endif
|
||||
RWLOCK_EXIT(&ipf_state);
|
||||
fin->fin_rev = IP6NEQ(is->is_dst, fin->fin_fi.fi_dst);
|
||||
if (fin->fin_fi.fi_fl & FI_FRAG)
|
||||
if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
|
||||
ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
|
||||
return is;
|
||||
}
|
||||
|
@ -1347,7 +1347,7 @@ retry_tcpudp:
|
|||
fr_delstate(is);
|
||||
#endif
|
||||
RWLOCK_EXIT(&ipf_state);
|
||||
if (fin->fin_fi.fi_fl & FI_FRAG)
|
||||
if ((fin->fin_fi.fi_fl & FI_FRAG) && (pass & FR_KEEPFRAG))
|
||||
ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE);
|
||||
return fr;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue