aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/netfilter/ip6_tables.c129
1 files changed, 82 insertions, 47 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index b73e6b6d5546..655c221acd1a 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -607,11 +607,55 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
607} 607}
608 608
609static inline int 609static inline int
610check_match(struct ip6t_entry_match *m, 610check_entry(struct ip6t_entry *e, const char *name)
611 const char *name, 611{
612 const struct ip6t_ip6 *ipv6, 612 struct ip6t_entry_target *t;
613 unsigned int hookmask, 613
614 unsigned int *i) 614 if (!ip6_checkentry(&e->ipv6)) {
615 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
616 return -EINVAL;
617 }
618
619 if (e->target_offset + sizeof(struct ip6t_entry_target) >
620 e->next_offset)
621 return -EINVAL;
622
623 t = ip6t_get_target(e);
624 if (e->target_offset + t->u.target_size > e->next_offset)
625 return -EINVAL;
626
627 return 0;
628}
629
630static inline int check_match(struct ip6t_entry_match *m, const char *name,
631 const struct ip6t_ip6 *ipv6,
632 unsigned int hookmask, unsigned int *i)
633{
634 struct xt_match *match;
635 int ret;
636
637 match = m->u.kernel.match;
638 ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m),
639 name, hookmask, ipv6->proto,
640 ipv6->invflags & IP6T_INV_PROTO);
641 if (!ret && m->u.kernel.match->checkentry
642 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
643 hookmask)) {
644 duprintf("ip_tables: check failed for `%s'.\n",
645 m->u.kernel.match->name);
646 ret = -EINVAL;
647 }
648 if (!ret)
649 (*i)++;
650 return ret;
651}
652
653static inline int
654find_check_match(struct ip6t_entry_match *m,
655 const char *name,
656 const struct ip6t_ip6 *ipv6,
657 unsigned int hookmask,
658 unsigned int *i)
615{ 659{
616 struct xt_match *match; 660 struct xt_match *match;
617 int ret; 661 int ret;
@@ -620,86 +664,77 @@ check_match(struct ip6t_entry_match *m,
620 m->u.user.revision), 664 m->u.user.revision),
621 "ip6t_%s", m->u.user.name); 665 "ip6t_%s", m->u.user.name);
622 if (IS_ERR(match) || !match) { 666 if (IS_ERR(match) || !match) {
623 duprintf("check_match: `%s' not found\n", m->u.user.name); 667 duprintf("find_check_match: `%s' not found\n", m->u.user.name);
624 return match ? PTR_ERR(match) : -ENOENT; 668 return match ? PTR_ERR(match) : -ENOENT;
625 } 669 }
626 m->u.kernel.match = match; 670 m->u.kernel.match = match;
627 671
628 ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m), 672 ret = check_match(m, name, ipv6, hookmask, i);
629 name, hookmask, ipv6->proto,
630 ipv6->invflags & IP6T_INV_PROTO);
631 if (ret) 673 if (ret)
632 goto err; 674 goto err;
633 675
634 if (m->u.kernel.match->checkentry
635 && !m->u.kernel.match->checkentry(name, ipv6, match, m->data,
636 hookmask)) {
637 duprintf("ip_tables: check failed for `%s'.\n",
638 m->u.kernel.match->name);
639 ret = -EINVAL;
640 goto err;
641 }
642
643 (*i)++;
644 return 0; 676 return 0;
645err: 677err:
646 module_put(m->u.kernel.match->me); 678 module_put(m->u.kernel.match->me);
647 return ret; 679 return ret;
648} 680}
649 681
650static inline int 682static inline int check_target(struct ip6t_entry *e, const char *name)
651check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
652 unsigned int *i)
653{ 683{
654 struct ip6t_entry_target *t; 684 struct ip6t_entry_target *t;
655 struct xt_target *target; 685 struct xt_target *target;
656 int ret; 686 int ret;
657 unsigned int j;
658 687
659 if (!ip6_checkentry(&e->ipv6)) { 688 t = ip6t_get_target(e);
660 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 689 target = t->u.kernel.target;
661 return -EINVAL; 690 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t),
691 name, e->comefrom, e->ipv6.proto,
692 e->ipv6.invflags & IP6T_INV_PROTO);
693 if (!ret && t->u.kernel.target->checkentry
694 && !t->u.kernel.target->checkentry(name, e, target, t->data,
695 e->comefrom)) {
696 duprintf("ip_tables: check failed for `%s'.\n",
697 t->u.kernel.target->name);
698 ret = -EINVAL;
662 } 699 }
700 return ret;
701}
663 702
664 if (e->target_offset + sizeof(struct ip6t_entry_target) > 703static inline int
665 e->next_offset) 704find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
666 return -EINVAL; 705 unsigned int *i)
706{
707 struct ip6t_entry_target *t;
708 struct xt_target *target;
709 int ret;
710 unsigned int j;
711
712 ret = check_entry(e, name);
713 if (ret)
714 return ret;
667 715
668 j = 0; 716 j = 0;
669 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); 717 ret = IP6T_MATCH_ITERATE(e, find_check_match, name, &e->ipv6,
718 e->comefrom, &j);
670 if (ret != 0) 719 if (ret != 0)
671 goto cleanup_matches; 720 goto cleanup_matches;
672 721
673 t = ip6t_get_target(e); 722 t = ip6t_get_target(e);
674 ret = -EINVAL;
675 if (e->target_offset + t->u.target_size > e->next_offset)
676 goto cleanup_matches;
677 target = try_then_request_module(xt_find_target(AF_INET6, 723 target = try_then_request_module(xt_find_target(AF_INET6,
678 t->u.user.name, 724 t->u.user.name,
679 t->u.user.revision), 725 t->u.user.revision),
680 "ip6t_%s", t->u.user.name); 726 "ip6t_%s", t->u.user.name);
681 if (IS_ERR(target) || !target) { 727 if (IS_ERR(target) || !target) {
682 duprintf("check_entry: `%s' not found\n", t->u.user.name); 728 duprintf("find_check_entry: `%s' not found\n", t->u.user.name);
683 ret = target ? PTR_ERR(target) : -ENOENT; 729 ret = target ? PTR_ERR(target) : -ENOENT;
684 goto cleanup_matches; 730 goto cleanup_matches;
685 } 731 }
686 t->u.kernel.target = target; 732 t->u.kernel.target = target;
687 733
688 ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), 734 ret = check_target(e, name);
689 name, e->comefrom, e->ipv6.proto,
690 e->ipv6.invflags & IP6T_INV_PROTO);
691 if (ret) 735 if (ret)
692 goto err; 736 goto err;
693 737
694 if (t->u.kernel.target->checkentry
695 && !t->u.kernel.target->checkentry(name, e, target, t->data,
696 e->comefrom)) {
697 duprintf("ip_tables: check failed for `%s'.\n",
698 t->u.kernel.target->name);
699 ret = -EINVAL;
700 goto err;
701 }
702
703 (*i)++; 738 (*i)++;
704 return 0; 739 return 0;
705 err: 740 err:
@@ -834,7 +869,7 @@ translate_table(const char *name,
834 /* Finally, each sanity check must pass */ 869 /* Finally, each sanity check must pass */
835 i = 0; 870 i = 0;
836 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 871 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
837 check_entry, name, size, &i); 872 find_check_entry, name, size, &i);
838 873
839 if (ret != 0) { 874 if (ret != 0) {
840 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 875 IP6T_ENTRY_ITERATE(entry0, newinfo->size,