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:
parent
f7f07821ef
commit
76d3f5f676
@ -99,6 +99,7 @@
|
|||||||
give any guarantee of the above statement.
|
give any guarantee of the above statement.
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
/* $FreeBSD$ */
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------*/
|
/*----------------------------------------------------*/
|
||||||
@ -312,6 +313,7 @@ static void compressedStreamEOF ( void ) NORETURN;
|
|||||||
|
|
||||||
static void copyFileName ( Char*, Char* );
|
static void copyFileName ( Char*, Char* );
|
||||||
static void* myMalloc ( Int32 );
|
static void* myMalloc ( Int32 );
|
||||||
|
static int applySavedFileAttrToOutputFile ( int fd );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -457,6 +459,10 @@ void compressStream ( FILE *stream, FILE *zStream )
|
|||||||
ret = fflush ( zStream );
|
ret = fflush ( zStream );
|
||||||
if (ret == EOF) goto errhandler_io;
|
if (ret == EOF) goto errhandler_io;
|
||||||
if (zStream != stdout) {
|
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 );
|
ret = fclose ( zStream );
|
||||||
outputHandleJustInCase = NULL;
|
outputHandleJustInCase = NULL;
|
||||||
if (ret == EOF) goto errhandler_io;
|
if (ret == EOF) goto errhandler_io;
|
||||||
@ -569,6 +575,12 @@ Bool uncompressStream ( FILE *zStream, FILE *stream )
|
|||||||
|
|
||||||
closeok:
|
closeok:
|
||||||
if (ferror(zStream)) goto errhandler_io;
|
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 );
|
ret = fclose ( zStream );
|
||||||
if (ret == EOF) goto errhandler_io;
|
if (ret == EOF) goto errhandler_io;
|
||||||
|
|
||||||
@ -1129,7 +1141,7 @@ void saveInputFileMetaInfo ( Char *srcName )
|
|||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void applySavedMetaInfoToOutputFile ( Char *dstName )
|
void applySavedTimeInfoToOutputFile ( Char *dstName )
|
||||||
{
|
{
|
||||||
# if BZ_UNIX
|
# if BZ_UNIX
|
||||||
IntNative retVal;
|
IntNative retVal;
|
||||||
@ -1138,16 +1150,26 @@ void applySavedMetaInfoToOutputFile ( Char *dstName )
|
|||||||
uTimBuf.actime = fileMetaInfo.st_atime;
|
uTimBuf.actime = fileMetaInfo.st_atime;
|
||||||
uTimBuf.modtime = fileMetaInfo.st_mtime;
|
uTimBuf.modtime = fileMetaInfo.st_mtime;
|
||||||
|
|
||||||
retVal = chmod ( dstName, fileMetaInfo.st_mode );
|
|
||||||
ERROR_IF_NOT_ZERO ( retVal );
|
|
||||||
|
|
||||||
retVal = utime ( dstName, &uTimBuf );
|
retVal = utime ( dstName, &uTimBuf );
|
||||||
ERROR_IF_NOT_ZERO ( retVal );
|
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
|
/* chown() will in many cases return with EPERM, which can
|
||||||
be safely ignored.
|
be safely ignored.
|
||||||
*/
|
*/
|
||||||
|
return 0;
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1370,7 +1392,7 @@ void compress ( Char *name )
|
|||||||
|
|
||||||
/*--- If there was an I/O error, we won't get here. ---*/
|
/*--- If there was an I/O error, we won't get here. ---*/
|
||||||
if ( srcMode == SM_F2F ) {
|
if ( srcMode == SM_F2F ) {
|
||||||
applySavedMetaInfoToOutputFile ( outName );
|
applySavedTimeInfoToOutputFile ( outName );
|
||||||
deleteOutputOnInterrupt = False;
|
deleteOutputOnInterrupt = False;
|
||||||
if ( !keepInputFiles ) {
|
if ( !keepInputFiles ) {
|
||||||
IntNative retVal = remove ( inName );
|
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 there was an I/O error, we won't get here. ---*/
|
||||||
if ( magicNumberOK ) {
|
if ( magicNumberOK ) {
|
||||||
if ( srcMode == SM_F2F ) {
|
if ( srcMode == SM_F2F ) {
|
||||||
applySavedMetaInfoToOutputFile ( outName );
|
applySavedTimeInfoToOutputFile ( outName );
|
||||||
deleteOutputOnInterrupt = False;
|
deleteOutputOnInterrupt = False;
|
||||||
if ( !keepInputFiles ) {
|
if ( !keepInputFiles ) {
|
||||||
IntNative retVal = remove ( inName );
|
IntNative retVal = remove ( inName );
|
||||||
|
@ -189,9 +189,12 @@ struct table_entry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define IPFW_TABLES_MAX 128
|
#define IPFW_TABLES_MAX 128
|
||||||
static struct {
|
static struct ip_fw_table {
|
||||||
struct radix_node_head *rnh;
|
struct radix_node_head *rnh;
|
||||||
int modified;
|
int modified;
|
||||||
|
in_addr_t last_addr;
|
||||||
|
int last_match;
|
||||||
|
u_int32_t last_value;
|
||||||
} ipfw_tables[IPFW_TABLES_MAX];
|
} ipfw_tables[IPFW_TABLES_MAX];
|
||||||
|
|
||||||
static int fw_debug = 1;
|
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)
|
lookup_table(u_int16_t tbl, in_addr_t addr, u_int32_t *val)
|
||||||
{
|
{
|
||||||
struct radix_node_head *rnh;
|
struct radix_node_head *rnh;
|
||||||
|
struct ip_fw_table *table;
|
||||||
struct table_entry *ent;
|
struct table_entry *ent;
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
static in_addr_t last_addr;
|
int last_match;
|
||||||
static int last_tbl;
|
|
||||||
static int last_match;
|
|
||||||
static u_int32_t last_value;
|
|
||||||
|
|
||||||
if (tbl >= IPFW_TABLES_MAX)
|
if (tbl >= IPFW_TABLES_MAX)
|
||||||
return (0);
|
return (0);
|
||||||
if (tbl == last_tbl && addr == last_addr &&
|
table = &ipfw_tables[tbl];
|
||||||
!ipfw_tables[tbl].modified) {
|
rnh = table->rnh;
|
||||||
|
RADIX_NODE_HEAD_LOCK(rnh);
|
||||||
|
if (addr == table->last_addr && !table->modified) {
|
||||||
|
last_match = table->last_match;
|
||||||
if (last_match)
|
if (last_match)
|
||||||
*val = last_value;
|
*val = table->last_value;
|
||||||
|
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||||
return (last_match);
|
return (last_match);
|
||||||
}
|
}
|
||||||
rnh = ipfw_tables[tbl].rnh;
|
table->modified = 0;
|
||||||
sa.sin_len = 8;
|
sa.sin_len = 8;
|
||||||
sa.sin_addr.s_addr = addr;
|
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));
|
ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
|
||||||
RADIX_NODE_HEAD_UNLOCK(rnh);
|
table->last_addr = addr;
|
||||||
last_addr = addr;
|
|
||||||
last_tbl = tbl;
|
|
||||||
if (ent != NULL) {
|
if (ent != NULL) {
|
||||||
last_value = *val = ent->value;
|
table->last_value = *val = ent->value;
|
||||||
last_match = 1;
|
table->last_match = 1;
|
||||||
|
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
last_match = 0;
|
table->last_match = 0;
|
||||||
|
RADIX_NODE_HEAD_UNLOCK(rnh);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1082,7 +1082,7 @@ tcp_input(m, off0)
|
|||||||
* XXX this is traditional behavior, may need to be cleaned up.
|
* XXX this is traditional behavior, may need to be cleaned up.
|
||||||
*/
|
*/
|
||||||
tcp_dooptions(&to, optp, optlen, thflags & TH_SYN);
|
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) {
|
if (to.to_flags & TOF_SCALE) {
|
||||||
tp->t_flags |= TF_RCVD_SCALE;
|
tp->t_flags |= TF_RCVD_SCALE;
|
||||||
tp->requested_s_scale = to.to_requested_s_scale;
|
tp->requested_s_scale = to.to_requested_s_scale;
|
||||||
|
@ -1082,7 +1082,7 @@ tcp_input(m, off0)
|
|||||||
* XXX this is traditional behavior, may need to be cleaned up.
|
* XXX this is traditional behavior, may need to be cleaned up.
|
||||||
*/
|
*/
|
||||||
tcp_dooptions(&to, optp, optlen, thflags & TH_SYN);
|
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) {
|
if (to.to_flags & TOF_SCALE) {
|
||||||
tp->t_flags |= TF_RCVD_SCALE;
|
tp->t_flags |= TF_RCVD_SCALE;
|
||||||
tp->requested_s_scale = to.to_requested_s_scale;
|
tp->requested_s_scale = to.to_requested_s_scale;
|
||||||
|
Loading…
Reference in New Issue
Block a user