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
This commit is contained in:
Simon L. B. Nielsen 2005-06-29 21:36:49 +00:00
parent 49808fa4fc
commit 0a389eab22
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147666
4 changed files with 51 additions and 26 deletions

View File

@ -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
}
retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
static
int applySavedFileAttrToOutputFile ( int fd )
{
# if BZ_UNIX
IntNative retVal;
retVal = fchmod ( fd, fileMetaInfo.st_mode );
if (retVal != 0)
return retVal;
(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 );

View File

@ -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);
}

View File

@ -1082,7 +1082,7 @@ tcp_input(m, off0)
* 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;

View File

@ -1082,7 +1082,7 @@ tcp_input(m, off0)
* 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;