aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/arp_tables.c21
-rw-r--r--net/ipv4/netfilter/ip_tables.c21
-rw-r--r--net/ipv6/netfilter/ip6_tables.c21
3 files changed, 57 insertions, 6 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 064082dffafb..7bc11ffbb845 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -533,6 +533,21 @@ out:
533 return ret; 533 return ret;
534} 534}
535 535
536static bool check_underflow(struct arpt_entry *e)
537{
538 const struct arpt_entry_target *t;
539 unsigned int verdict;
540
541 if (!unconditional(&e->arp))
542 return false;
543 t = arpt_get_target(e);
544 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
545 return false;
546 verdict = ((struct arpt_standard_target *)t)->verdict;
547 verdict = -verdict - 1;
548 return verdict == NF_DROP || verdict == NF_ACCEPT;
549}
550
536static inline int check_entry_size_and_hooks(struct arpt_entry *e, 551static inline int check_entry_size_and_hooks(struct arpt_entry *e,
537 struct xt_table_info *newinfo, 552 struct xt_table_info *newinfo,
538 unsigned char *base, 553 unsigned char *base,
@@ -564,8 +579,10 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
564 if ((unsigned char *)e - base == hook_entries[h]) 579 if ((unsigned char *)e - base == hook_entries[h])
565 newinfo->hook_entry[h] = hook_entries[h]; 580 newinfo->hook_entry[h] = hook_entries[h];
566 if ((unsigned char *)e - base == underflows[h]) { 581 if ((unsigned char *)e - base == underflows[h]) {
567 if (!unconditional(&e->arp)) { 582 if (!check_underflow(e)) {
568 pr_err("Underflows must be unconditional\n"); 583 pr_err("Underflows must be unconditional and "
584 "use the STANDARD target with "
585 "ACCEPT/DROP\n");
569 return -EINVAL; 586 return -EINVAL;
570 } 587 }
571 newinfo->underflow[h] = underflows[h]; 588 newinfo->underflow[h] = underflows[h];
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 6e546d573d9c..0b43fd7ca04a 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -708,6 +708,21 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
708 return ret; 708 return ret;
709} 709}
710 710
711static bool check_underflow(struct ipt_entry *e)
712{
713 const struct ipt_entry_target *t;
714 unsigned int verdict;
715
716 if (!unconditional(&e->ip))
717 return false;
718 t = ipt_get_target(e);
719 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
720 return false;
721 verdict = ((struct ipt_standard_target *)t)->verdict;
722 verdict = -verdict - 1;
723 return verdict == NF_DROP || verdict == NF_ACCEPT;
724}
725
711static int 726static int
712check_entry_size_and_hooks(struct ipt_entry *e, 727check_entry_size_and_hooks(struct ipt_entry *e,
713 struct xt_table_info *newinfo, 728 struct xt_table_info *newinfo,
@@ -740,8 +755,10 @@ check_entry_size_and_hooks(struct ipt_entry *e,
740 if ((unsigned char *)e - base == hook_entries[h]) 755 if ((unsigned char *)e - base == hook_entries[h])
741 newinfo->hook_entry[h] = hook_entries[h]; 756 newinfo->hook_entry[h] = hook_entries[h];
742 if ((unsigned char *)e - base == underflows[h]) { 757 if ((unsigned char *)e - base == underflows[h]) {
743 if (!unconditional(&e->ip)) { 758 if (!check_underflow(e)) {
744 pr_err("Underflows must be unconditional\n"); 759 pr_err("Underflows must be unconditional and "
760 "use the STANDARD target with "
761 "ACCEPT/DROP\n");
745 return -EINVAL; 762 return -EINVAL;
746 } 763 }
747 newinfo->underflow[h] = underflows[h]; 764 newinfo->underflow[h] = underflows[h];
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];