|
@@ -321,8 +321,6 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
const struct net_device *out,
|
|
|
struct xt_table *table)
|
|
|
{
|
|
|
-#define tb_comefrom ((struct ipt_entry *)table_base)->comefrom
|
|
|
-
|
|
|
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
|
|
|
const struct iphdr *ip;
|
|
|
bool hotdrop = false;
|
|
@@ -330,7 +328,8 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
unsigned int verdict = NF_DROP;
|
|
|
const char *indev, *outdev;
|
|
|
const void *table_base;
|
|
|
- struct ipt_entry *e, *back;
|
|
|
+ struct ipt_entry *e, **jumpstack;
|
|
|
+ unsigned int *stackptr, origptr, cpu;
|
|
|
const struct xt_table_info *private;
|
|
|
struct xt_match_param mtpar;
|
|
|
struct xt_target_param tgpar;
|
|
@@ -356,19 +355,23 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
|
|
xt_info_rdlock_bh();
|
|
|
private = table->private;
|
|
|
- table_base = private->entries[smp_processor_id()];
|
|
|
+ cpu = smp_processor_id();
|
|
|
+ table_base = private->entries[cpu];
|
|
|
+ jumpstack = (struct ipt_entry **)private->jumpstack[cpu];
|
|
|
+ stackptr = &private->stackptr[cpu];
|
|
|
+ origptr = *stackptr;
|
|
|
|
|
|
e = get_entry(table_base, private->hook_entry[hook]);
|
|
|
|
|
|
- /* For return from builtin chain */
|
|
|
- back = get_entry(table_base, private->underflow[hook]);
|
|
|
+ pr_devel("Entering %s(hook %u); sp at %u (UF %p)\n",
|
|
|
+ table->name, hook, origptr,
|
|
|
+ get_entry(table_base, private->underflow[hook]));
|
|
|
|
|
|
do {
|
|
|
const struct ipt_entry_target *t;
|
|
|
const struct xt_entry_match *ematch;
|
|
|
|
|
|
IP_NF_ASSERT(e);
|
|
|
- IP_NF_ASSERT(back);
|
|
|
if (!ip_packet_match(ip, indev, outdev,
|
|
|
&e->ip, mtpar.fragoff)) {
|
|
|
no_match:
|
|
@@ -403,17 +406,28 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
verdict = (unsigned)(-v) - 1;
|
|
|
break;
|
|
|
}
|
|
|
- e = back;
|
|
|
- back = get_entry(table_base, back->comefrom);
|
|
|
+ if (*stackptr == 0) {
|
|
|
+ e = get_entry(table_base,
|
|
|
+ private->underflow[hook]);
|
|
|
+ pr_devel("Underflow (this is normal) "
|
|
|
+ "to %p\n", e);
|
|
|
+ } else {
|
|
|
+ e = jumpstack[--*stackptr];
|
|
|
+ pr_devel("Pulled %p out from pos %u\n",
|
|
|
+ e, *stackptr);
|
|
|
+ e = ipt_next_entry(e);
|
|
|
+ }
|
|
|
continue;
|
|
|
}
|
|
|
if (table_base + v != ipt_next_entry(e) &&
|
|
|
!(e->ip.flags & IPT_F_GOTO)) {
|
|
|
- /* Save old back ptr in next entry */
|
|
|
- struct ipt_entry *next = ipt_next_entry(e);
|
|
|
- next->comefrom = (void *)back - table_base;
|
|
|
- /* set back pointer to next entry */
|
|
|
- back = next;
|
|
|
+ if (*stackptr >= private->stacksize) {
|
|
|
+ verdict = NF_DROP;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ jumpstack[(*stackptr)++] = e;
|
|
|
+ pr_devel("Pushed %p into pos %u\n",
|
|
|
+ e, *stackptr - 1);
|
|
|
}
|
|
|
|
|
|
e = get_entry(table_base, v);
|
|
@@ -426,18 +440,7 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
tgpar.targinfo = t->data;
|
|
|
|
|
|
|
|
|
-#ifdef CONFIG_NETFILTER_DEBUG
|
|
|
- tb_comefrom = 0xeeeeeeec;
|
|
|
-#endif
|
|
|
verdict = t->u.kernel.target->target(skb, &tgpar);
|
|
|
-#ifdef CONFIG_NETFILTER_DEBUG
|
|
|
- if (tb_comefrom != 0xeeeeeeec && verdict == IPT_CONTINUE) {
|
|
|
- printk("Target %s reentered!\n",
|
|
|
- t->u.kernel.target->name);
|
|
|
- verdict = NF_DROP;
|
|
|
- }
|
|
|
- tb_comefrom = 0x57acc001;
|
|
|
-#endif
|
|
|
/* Target might have changed stuff. */
|
|
|
ip = ip_hdr(skb);
|
|
|
if (verdict == IPT_CONTINUE)
|
|
@@ -447,7 +450,9 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
break;
|
|
|
} while (!hotdrop);
|
|
|
xt_info_rdunlock_bh();
|
|
|
-
|
|
|
+ pr_devel("Exiting %s; resetting sp from %u to %u\n",
|
|
|
+ __func__, *stackptr, origptr);
|
|
|
+ *stackptr = origptr;
|
|
|
#ifdef DEBUG_ALLOW_ALL
|
|
|
return NF_ACCEPT;
|
|
|
#else
|
|
@@ -455,8 +460,6 @@ ipt_do_table(struct sk_buff *skb,
|
|
|
return NF_DROP;
|
|
|
else return verdict;
|
|
|
#endif
|
|
|
-
|
|
|
-#undef tb_comefrom
|
|
|
}
|
|
|
|
|
|
/* Figures out from what hook each rule can be called: returns 0 if
|
|
@@ -838,6 +841,9 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
|
++i;
|
|
|
+ if (strcmp(ipt_get_target(iter)->u.user.name,
|
|
|
+ XT_ERROR_TARGET) == 0)
|
|
|
+ ++newinfo->stacksize;
|
|
|
}
|
|
|
|
|
|
if (i != repl->num_entries) {
|
|
@@ -2086,8 +2092,7 @@ struct xt_table *ipt_register_table(struct net *net,
|
|
|
{
|
|
|
int ret;
|
|
|
struct xt_table_info *newinfo;
|
|
|
- struct xt_table_info bootstrap
|
|
|
- = { 0, 0, 0, { 0 }, { 0 }, { } };
|
|
|
+ struct xt_table_info bootstrap = {0};
|
|
|
void *loc_cpu_entry;
|
|
|
struct xt_table *new_table;
|
|
|
|