1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-12 09:58:36 +00:00

fix security hole created by fragment cache

This commit is contained in:
Darren Reed 2001-04-06 15:52:28 +00:00
parent 207ef320ab
commit 454a43c1f1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75262
5 changed files with 36 additions and 10 deletions

View File

@ -141,12 +141,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;
@ -200,7 +203,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;
@ -256,6 +262,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).
@ -283,6 +292,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
@ -295,7 +317,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

View File

@ -25,7 +25,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;
@ -41,7 +42,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;

View File

@ -2283,7 +2283,8 @@ fr_info_t *fin;
*/
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;
@ -2488,7 +2489,8 @@ fr_info_t *fin;
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))) {

View File

@ -227,6 +227,7 @@ typedef struct natstat {
#define IPN_ROUNDR 0x100
#define IPN_NOTSRC 0x080000
#define IPN_NOTDST 0x100000
#define IPN_FRAG 0x200000
typedef struct natlog {

View File

@ -688,7 +688,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;
}
@ -1345,7 +1345,7 @@ fr_info_t *fin;
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;
}