diff options
author | csjp <csjp@FreeBSD.org> | 2006-01-20 05:35:27 +0000 |
---|---|---|
committer | csjp <csjp@FreeBSD.org> | 2006-01-20 05:35:27 +0000 |
commit | 789674670e39102ca2d71ce85d9f93840ab2e564 (patch) | |
tree | f7e6bc762621502a8be7ab4d574676b3e26f0411 /sys/netinet/ip_fw2.c | |
parent | 5f9b2961c344fae5d18e1938377ac1cd2fef24a5 (diff) | |
download | FreeBSD-src-789674670e39102ca2d71ce85d9f93840ab2e564.zip FreeBSD-src-789674670e39102ca2d71ce85d9f93840ab2e564.tar.gz |
- Change the return type for init_tables from void to int so we can propagate
errors from rn_inithead back to the ipfw initialization function.
- Check return value of rn_inithead for failure, if table allocation has
failed for any reason, free up any tables we have created and return ENOMEM
- In ipfw_init check the return value of init_tables and free up any mutexes or
UMA zones which may have been created.
- Assert that the supplied table is not NULL before attempting to dereference.
This fixes panics which were a result of invalid memory accesses due to failed
table allocation. This is an issue mainly because the R_Zalloc function is a
malloc(M_NOWAIT) wrapper, thus making it possible for allocations to fail.
Found by: Coverity Prevent (tm)
Coverity ID: CID79
MFC after: 1 week
Diffstat (limited to 'sys/netinet/ip_fw2.c')
-rw-r--r-- | sys/netinet/ip_fw2.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index ffc4993..79e0e2b 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -1695,15 +1695,6 @@ lookup_next_rule(struct ip_fw *me) return rule; } -static void -init_tables(struct ip_fw_chain *ch) -{ - int i; - - for (i = 0; i < IPFW_TABLES_MAX; i++) - rn_inithead((void **)&ch->tables[i], 32); -} - static int add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, uint8_t mlen, uint32_t value) @@ -1780,6 +1771,7 @@ flush_table(struct ip_fw_chain *ch, uint16_t tbl) if (tbl >= IPFW_TABLES_MAX) return (EINVAL); rnh = ch->tables[tbl]; + KASSERT(rnh != NULL, ("NULL IPFW table")); rnh->rnh_walktree(rnh, flush_table_entry, rnh); return (0); } @@ -1796,6 +1788,23 @@ flush_tables(struct ip_fw_chain *ch) } static int +init_tables(struct ip_fw_chain *ch) +{ + int i; + uint16_t j; + + for (i = 0; i < IPFW_TABLES_MAX; i++) { + if (!rn_inithead((void **)&ch->tables[i], 32)) { + for (j = 0; j < i; j++) { + (void) flush_table(ch, j); + } + return (ENOMEM); + } + } + return (0); +} + +static int lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, uint32_t *val) { @@ -4204,7 +4213,13 @@ ipfw_init(void) printf("limited to %d packets/entry by default\n", verbose_limit); - init_tables(&layer3_chain); + error = init_tables(&layer3_chain); + if (error) { + IPFW_DYN_LOCK_DESTROY(); + IPFW_LOCK_DESTROY(&layer3_chain); + uma_zdestroy(ipfw_dyn_rule_zone); + return (error); + } ip_fw_ctl_ptr = ipfw_ctl; ip_fw_chk_ptr = ipfw_chk; callout_reset(&ipfw_timeout, hz, ipfw_tick, NULL); |