summaryrefslogtreecommitdiffstats
path: root/kernel/linux2.5/net/bridge/netfilter/ebtables.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/linux2.5/net/bridge/netfilter/ebtables.c')
-rw-r--r--kernel/linux2.5/net/bridge/netfilter/ebtables.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/kernel/linux2.5/net/bridge/netfilter/ebtables.c b/kernel/linux2.5/net/bridge/netfilter/ebtables.c
index e297900..8729898 100644
--- a/kernel/linux2.5/net/bridge/netfilter/ebtables.c
+++ b/kernel/linux2.5/net/bridge/netfilter/ebtables.c
@@ -175,6 +175,10 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
char *base;
struct ebt_table_info *private = table->private;
+ /* FIXME: Push down to extensions --RR */
+ if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0)
+ return NF_DROP;
+
read_lock_bh(&table->lock);
cb_base = COUNTER_BASE(private->counters, private->nentries,
smp_processor_id());
@@ -969,8 +973,10 @@ static int do_replace(void *user, unsigned int len)
goto free_counterstmp;
t = find_table_lock(tmp.name, &ret, &ebt_mutex);
- if (!t)
+ if (!t) {
+ ret = -ENOENT;
goto free_iterate;
+ }
/* the table doesn't like it */
if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
@@ -984,6 +990,12 @@ static int do_replace(void *user, unsigned int len)
/* we have the mutex lock, so no danger in reading this pointer */
table = t->private;
+ /* make sure the table can only be rmmod'ed if it contains no rules */
+ if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
+ ret = -ENOENT;
+ goto free_unlock;
+ } else if (table->nentries && !newinfo->nentries)
+ module_put(t->me);
/* we need an atomic snapshot of the counters */
write_lock_bh(&t->lock);
if (tmp.num_counters)
@@ -1168,6 +1180,11 @@ int ebt_register_table(struct ebt_table *table)
goto free_unlock;
}
+ /* Hold a reference count if the chains aren't empty */
+ if (newinfo->nentries && !try_module_get(table->me)) {
+ ret = -ENOENT;
+ goto free_unlock;
+ }
list_prepend(&ebt_tables, table);
up(&ebt_mutex);
return 0;
@@ -1196,8 +1213,6 @@ void ebt_unregister_table(struct ebt_table *table)
down(&ebt_mutex);
LIST_DELETE(&ebt_tables, table);
up(&ebt_mutex);
- EBT_ENTRY_ITERATE(table->private->entries,
- table->private->entries_size, ebt_cleanup_entry, NULL);
if (table->private->entries)
vfree(table->private->entries);
if (table->private->chainstack) {