aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@medozas.de>2009-07-18 09:22:30 -0400
committerJan Engelhardt <jengelh@medozas.de>2009-08-10 07:35:31 -0400
commite2fe35c17fed62d4ab5038fa9bc489e967ff8416 (patch)
tree84a4b0b688276b6788081f441984abd01d036b4d /net/ipv6
parent90e7d4ab5c8b0c4c2e00e4893977f6aeec0f18f1 (diff)
netfilter: xtables: check for standard verdicts in policies
This adds the second check that Rusty wanted to have a long time ago. :-) Base chain policies must have absolute verdicts that cease processing in the table, otherwise rule execution may continue in an unexpected spurious fashion (e.g. next chain that follows in memory). Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_tables.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index b0599b98d1b6..a5d0c27cc26f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -740,6 +740,21 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
740 return ret; 740 return ret;
741} 741}
742 742
743static bool check_underflow(struct ip6t_entry *e)
744{
745 const struct ip6t_entry_target *t;
746 unsigned int verdict;
747
748 if (!unconditional(&e->ipv6))
749 return false;
750 t = ip6t_get_target(e);
751 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
752 return false;
753 verdict = ((struct ip6t_standard_target *)t)->verdict;
754 verdict = -verdict - 1;
755 return verdict == NF_DROP || verdict == NF_ACCEPT;
756}
757
743static int 758static int
744check_entry_size_and_hooks(struct ip6t_entry *e, 759check_entry_size_and_hooks(struct ip6t_entry *e,
745 struct xt_table_info *newinfo, 760 struct xt_table_info *newinfo,
@@ -772,8 +787,10 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
772 if ((unsigned char *)e - base == hook_entries[h]) 787 if ((unsigned char *)e - base == hook_entries[h])
773 newinfo->hook_entry[h] = hook_entries[h]; 788 newinfo->hook_entry[h] = hook_entries[h];
774 if ((unsigned char *)e - base == underflows[h]) { 789 if ((unsigned char *)e - base == underflows[h]) {
775 if (!unconditional(&e->ipv6)) { 790 if (!check_underflow(e)) {
776 pr_err("Underflows must be unconditional\n"); 791 pr_err("Underflows must be unconditional and "
792 "use the STANDARD target with "
793 "ACCEPT/DROP\n");
777 return -EINVAL; 794 return -EINVAL;
778 } 795 }
779 newinfo->underflow[h] = underflows[h]; 796 newinfo->underflow[h] = underflows[h];