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 /sys/netinet/ip_fw2.c | |
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
Diffstat (limited to 'sys/netinet/ip_fw2.c')
-rw-r--r-- | sys/netinet/ip_fw2.c | 37 |
1 files changed, 20 insertions, 17 deletions
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); } |