[NETFILTER]: {ip,ip6,arp}_tables: fix exponential worst-case search for loops
If we come to node we'd already marked as seen and it's not a part of path (i.e. we don't have a loop right there), we already know that it isn't a part of any loop, so we don't need to revisit it. That speeds the things up if some chain is refered to from several places and kills O(exp(table size)) worst-case behaviour (without sleeping, at that, so if you manage to self-LART that way, you are SOL for a long time)... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a96be24679
commit
e1b4b9f398
3 changed files with 9 additions and 6 deletions
|
@ -358,6 +358,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct arpt_standard_target *t
|
struct arpt_standard_target *t
|
||||||
= (void *)arpt_get_target(e);
|
= (void *)arpt_get_target(e);
|
||||||
|
int visited = e->comefrom & (1 << hook);
|
||||||
|
|
||||||
if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) {
|
if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) {
|
||||||
printk("arptables: loop hook %u pos %u %08X.\n",
|
printk("arptables: loop hook %u pos %u %08X.\n",
|
||||||
|
@ -368,11 +369,11 @@ static int mark_source_chains(struct xt_table_info *newinfo,
|
||||||
|= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
|
|= ((1 << hook) | (1 << NF_ARP_NUMHOOKS));
|
||||||
|
|
||||||
/* Unconditional return/END. */
|
/* Unconditional return/END. */
|
||||||
if (e->target_offset == sizeof(struct arpt_entry)
|
if ((e->target_offset == sizeof(struct arpt_entry)
|
||||||
&& (strcmp(t->target.u.user.name,
|
&& (strcmp(t->target.u.user.name,
|
||||||
ARPT_STANDARD_TARGET) == 0)
|
ARPT_STANDARD_TARGET) == 0)
|
||||||
&& t->verdict < 0
|
&& t->verdict < 0
|
||||||
&& unconditional(&e->arp)) {
|
&& unconditional(&e->arp)) || visited) {
|
||||||
unsigned int oldpos, size;
|
unsigned int oldpos, size;
|
||||||
|
|
||||||
if (t->verdict < -NF_MAX_VERDICT - 1) {
|
if (t->verdict < -NF_MAX_VERDICT - 1) {
|
||||||
|
|
|
@ -384,6 +384,7 @@ mark_source_chains(struct xt_table_info *newinfo,
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct ipt_standard_target *t
|
struct ipt_standard_target *t
|
||||||
= (void *)ipt_get_target(e);
|
= (void *)ipt_get_target(e);
|
||||||
|
int visited = e->comefrom & (1 << hook);
|
||||||
|
|
||||||
if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
|
if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
|
||||||
printk("iptables: loop hook %u pos %u %08X.\n",
|
printk("iptables: loop hook %u pos %u %08X.\n",
|
||||||
|
@ -394,11 +395,11 @@ mark_source_chains(struct xt_table_info *newinfo,
|
||||||
|= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
|
|= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
|
||||||
|
|
||||||
/* Unconditional return/END. */
|
/* Unconditional return/END. */
|
||||||
if (e->target_offset == sizeof(struct ipt_entry)
|
if ((e->target_offset == sizeof(struct ipt_entry)
|
||||||
&& (strcmp(t->target.u.user.name,
|
&& (strcmp(t->target.u.user.name,
|
||||||
IPT_STANDARD_TARGET) == 0)
|
IPT_STANDARD_TARGET) == 0)
|
||||||
&& t->verdict < 0
|
&& t->verdict < 0
|
||||||
&& unconditional(&e->ip)) {
|
&& unconditional(&e->ip)) || visited) {
|
||||||
unsigned int oldpos, size;
|
unsigned int oldpos, size;
|
||||||
|
|
||||||
if (t->verdict < -NF_MAX_VERDICT - 1) {
|
if (t->verdict < -NF_MAX_VERDICT - 1) {
|
||||||
|
|
|
@ -413,6 +413,7 @@ mark_source_chains(struct xt_table_info *newinfo,
|
||||||
unsigned int pos = newinfo->hook_entry[hook];
|
unsigned int pos = newinfo->hook_entry[hook];
|
||||||
struct ip6t_entry *e
|
struct ip6t_entry *e
|
||||||
= (struct ip6t_entry *)(entry0 + pos);
|
= (struct ip6t_entry *)(entry0 + pos);
|
||||||
|
int visited = e->comefrom & (1 << hook);
|
||||||
|
|
||||||
if (!(valid_hooks & (1 << hook)))
|
if (!(valid_hooks & (1 << hook)))
|
||||||
continue;
|
continue;
|
||||||
|
@ -433,11 +434,11 @@ mark_source_chains(struct xt_table_info *newinfo,
|
||||||
|= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
|
|= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
|
||||||
|
|
||||||
/* Unconditional return/END. */
|
/* Unconditional return/END. */
|
||||||
if (e->target_offset == sizeof(struct ip6t_entry)
|
if ((e->target_offset == sizeof(struct ip6t_entry)
|
||||||
&& (strcmp(t->target.u.user.name,
|
&& (strcmp(t->target.u.user.name,
|
||||||
IP6T_STANDARD_TARGET) == 0)
|
IP6T_STANDARD_TARGET) == 0)
|
||||||
&& t->verdict < 0
|
&& t->verdict < 0
|
||||||
&& unconditional(&e->ipv6)) {
|
&& unconditional(&e->ipv6)) || visited) {
|
||||||
unsigned int oldpos, size;
|
unsigned int oldpos, size;
|
||||||
|
|
||||||
if (t->verdict < -NF_MAX_VERDICT - 1) {
|
if (t->verdict < -NF_MAX_VERDICT - 1) {
|
||||||
|
|
Loading…
Reference in a new issue