diff options
author | simon <simon@FreeBSD.org> | 2005-06-29 21:36:49 +0000 |
---|---|---|
committer | simon <simon@FreeBSD.org> | 2005-06-29 21:36:49 +0000 |
commit | 76d3f5f6768a9a26b12823a0d37fda4d373ac9f6 (patch) | |
tree | 0d01d80ed5ef7635e6b3d562c88fc976ed1c28b5 | |
parent | f7f07821efbf38ac8511c86aecb6c412b4a115f7 (diff) | |
download | FreeBSD-src-76d3f5f6768a9a26b12823a0d37fda4d373ac9f6.zip FreeBSD-src-76d3f5f6768a9a26b12823a0d37fda4d373ac9f6.tar.gz |
Fix ipfw packet matching errors with address tables.
The ipfw tables lookup code caches the result of the last query. The
kernel may process multiple packets concurrently, performing several
concurrent table lookups. Due to an insufficient locking, a cached
result can become corrupted that could cause some addresses to be
incorrectly matched against a lookup table.
Submitted by: ru
Reviewed by: csjp, mlaier
Security: CAN-2005-2019
Security: FreeBSD-SA-05:13.ipfw
Correct bzip2 permission race condition vulnerability.
Obtained from: Steve Grubb via RedHat
Security: CAN-2005-0953
Security: FreeBSD-SA-05:14.bzip2
Approved by: obrien
Correct TCP connection stall denial of service vulnerability.
A TCP packets with the SYN flag set is accepted for established
connections, allowing an attacker to overwrite certain TCP options.
Submitted by: Noritoshi Demizu
Reviewed by: andre, Mohan Srinivasan
Security: CAN-2005-2068
Security: FreeBSD-SA-05:15.tcp
Approved by: re (security blanket), cperciva
-rw-r--r-- | contrib/bzip2/bzip2.c | 36 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 37 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 2 |
4 files changed, 51 insertions, 26 deletions
diff --git a/contrib/bzip2/bzip2.c b/contrib/bzip2/bzip2.c index 79f87a5..5164e23 100644 --- a/contrib/bzip2/bzip2.c +++ b/contrib/bzip2/bzip2.c @@ -99,6 +99,7 @@ give any guarantee of the above statement. --*/ +/* $FreeBSD$ */ /*----------------------------------------------------*/ @@ -312,6 +313,7 @@ static void compressedStreamEOF ( void ) NORETURN; static void copyFileName ( Char*, Char* ); static void* myMalloc ( Int32 ); +static int applySavedFileAttrToOutputFile ( int fd ); @@ -457,6 +459,10 @@ void compressStream ( FILE *stream, FILE *zStream ) ret = fflush ( zStream ); if (ret == EOF) goto errhandler_io; if (zStream != stdout) { + int fd = fileno ( zStream ); + if (fd < 0) goto errhandler_io; + ret = applySavedFileAttrToOutputFile ( fd ); + if (ret != 0) goto errhandler_io; ret = fclose ( zStream ); outputHandleJustInCase = NULL; if (ret == EOF) goto errhandler_io; @@ -569,6 +575,12 @@ Bool uncompressStream ( FILE *zStream, FILE *stream ) closeok: if (ferror(zStream)) goto errhandler_io; + if ( stream != stdout) { + int fd = fileno ( stream ); + if (fd < 0) goto errhandler_io; + ret = applySavedFileAttrToOutputFile ( fd ); + if (ret != 0) goto errhandler_io; + } ret = fclose ( zStream ); if (ret == EOF) goto errhandler_io; @@ -1129,7 +1141,7 @@ void saveInputFileMetaInfo ( Char *srcName ) static -void applySavedMetaInfoToOutputFile ( Char *dstName ) +void applySavedTimeInfoToOutputFile ( Char *dstName ) { # if BZ_UNIX IntNative retVal; @@ -1138,16 +1150,26 @@ void applySavedMetaInfoToOutputFile ( Char *dstName ) uTimBuf.actime = fileMetaInfo.st_atime; uTimBuf.modtime = fileMetaInfo.st_mtime; - retVal = chmod ( dstName, fileMetaInfo.st_mode ); - ERROR_IF_NOT_ZERO ( retVal ); - retVal = utime ( dstName, &uTimBuf ); ERROR_IF_NOT_ZERO ( retVal ); +# endif +} + +static +int applySavedFileAttrToOutputFile ( int fd ) +{ +# if BZ_UNIX + IntNative retVal; + + retVal = fchmod ( fd, fileMetaInfo.st_mode ); + if (retVal != 0) + return retVal; - retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid ); + (void) fchown ( fd, fileMetaInfo.st_uid, fileMetaInfo.st_gid ); /* chown() will in many cases return with EPERM, which can be safely ignored. */ + return 0; # endif } @@ -1370,7 +1392,7 @@ void compress ( Char *name ) /*--- If there was an I/O error, we won't get here. ---*/ if ( srcMode == SM_F2F ) { - applySavedMetaInfoToOutputFile ( outName ); + applySavedTimeInfoToOutputFile ( outName ); deleteOutputOnInterrupt = False; if ( !keepInputFiles ) { IntNative retVal = remove ( inName ); @@ -1548,7 +1570,7 @@ void uncompress ( Char *name ) /*--- If there was an I/O error, we won't get here. ---*/ if ( magicNumberOK ) { if ( srcMode == SM_F2F ) { - applySavedMetaInfoToOutputFile ( outName ); + applySavedTimeInfoToOutputFile ( outName ); deleteOutputOnInterrupt = False; if ( !keepInputFiles ) { IntNative retVal = remove ( inName ); diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 3ad2932..85eb962 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -189,9 +189,12 @@ struct table_entry { }; #define IPFW_TABLES_MAX 128 -static struct { +static struct ip_fw_table { struct radix_node_head *rnh; int modified; + in_addr_t last_addr; + int last_match; + u_int32_t last_value; } ipfw_tables[IPFW_TABLES_MAX]; static int fw_debug = 1; @@ -1647,36 +1650,36 @@ static int lookup_table(u_int16_t tbl, in_addr_t addr, u_int32_t *val) { struct radix_node_head *rnh; + struct ip_fw_table *table; struct table_entry *ent; struct sockaddr_in sa; - static in_addr_t last_addr; - static int last_tbl; - static int last_match; - static u_int32_t last_value; + int last_match; if (tbl >= IPFW_TABLES_MAX) return (0); - if (tbl == last_tbl && addr == last_addr && - !ipfw_tables[tbl].modified) { + table = &ipfw_tables[tbl]; + rnh = table->rnh; + RADIX_NODE_HEAD_LOCK(rnh); + if (addr == table->last_addr && !table->modified) { + last_match = table->last_match; if (last_match) - *val = last_value; + *val = table->last_value; + RADIX_NODE_HEAD_UNLOCK(rnh); return (last_match); } - rnh = ipfw_tables[tbl].rnh; + table->modified = 0; sa.sin_len = 8; sa.sin_addr.s_addr = addr; - RADIX_NODE_HEAD_LOCK(rnh); - ipfw_tables[tbl].modified = 0; ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh)); - RADIX_NODE_HEAD_UNLOCK(rnh); - last_addr = addr; - last_tbl = tbl; + table->last_addr = addr; if (ent != NULL) { - last_value = *val = ent->value; - last_match = 1; + table->last_value = *val = ent->value; + table->last_match = 1; + RADIX_NODE_HEAD_UNLOCK(rnh); return (1); } - last_match = 0; + table->last_match = 0; + RADIX_NODE_HEAD_UNLOCK(rnh); return (0); } diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 6762232..b6c2812 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1082,7 +1082,7 @@ after_listen: * XXX this is traditional behavior, may need to be cleaned up. */ tcp_dooptions(&to, optp, optlen, thflags & TH_SYN); - if (thflags & TH_SYN) { + if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) { if (to.to_flags & TOF_SCALE) { tp->t_flags |= TF_RCVD_SCALE; tp->requested_s_scale = to.to_requested_s_scale; diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 6762232..b6c2812 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -1082,7 +1082,7 @@ after_listen: * XXX this is traditional behavior, may need to be cleaned up. */ tcp_dooptions(&to, optp, optlen, thflags & TH_SYN); - if (thflags & TH_SYN) { + if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) { if (to.to_flags & TOF_SCALE) { tp->t_flags |= TF_RCVD_SCALE; tp->requested_s_scale = to.to_requested_s_scale; |