diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 74ff56c322f4..1cd70683f2e2 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -575,6 +575,7 @@ check_match(struct ip6t_entry_match *m, | |||
575 | unsigned int *i) | 575 | unsigned int *i) |
576 | { | 576 | { |
577 | struct ip6t_match *match; | 577 | struct ip6t_match *match; |
578 | int ret; | ||
578 | 579 | ||
579 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, | 580 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, |
580 | m->u.user.revision), | 581 | m->u.user.revision), |
@@ -585,18 +586,27 @@ check_match(struct ip6t_entry_match *m, | |||
585 | } | 586 | } |
586 | m->u.kernel.match = match; | 587 | m->u.kernel.match = match; |
587 | 588 | ||
589 | ret = xt_check_match(match, AF_INET6, m->u.match_size - sizeof(*m), | ||
590 | name, hookmask, ipv6->proto, | ||
591 | ipv6->invflags & IP6T_INV_PROTO); | ||
592 | if (ret) | ||
593 | goto err; | ||
594 | |||
588 | if (m->u.kernel.match->checkentry | 595 | if (m->u.kernel.match->checkentry |
589 | && !m->u.kernel.match->checkentry(name, ipv6, m->data, | 596 | && !m->u.kernel.match->checkentry(name, ipv6, m->data, |
590 | m->u.match_size - sizeof(*m), | 597 | m->u.match_size - sizeof(*m), |
591 | hookmask)) { | 598 | hookmask)) { |
592 | module_put(m->u.kernel.match->me); | ||
593 | duprintf("ip_tables: check failed for `%s'.\n", | 599 | duprintf("ip_tables: check failed for `%s'.\n", |
594 | m->u.kernel.match->name); | 600 | m->u.kernel.match->name); |
595 | return -EINVAL; | 601 | ret = -EINVAL; |
602 | goto err; | ||
596 | } | 603 | } |
597 | 604 | ||
598 | (*i)++; | 605 | (*i)++; |
599 | return 0; | 606 | return 0; |
607 | err: | ||
608 | module_put(m->u.kernel.match->me); | ||
609 | return ret; | ||
600 | } | 610 | } |
601 | 611 | ||
602 | static struct ip6t_target ip6t_standard_target; | 612 | static struct ip6t_target ip6t_standard_target; |
@@ -632,6 +642,12 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
632 | } | 642 | } |
633 | t->u.kernel.target = target; | 643 | t->u.kernel.target = target; |
634 | 644 | ||
645 | ret = xt_check_target(target, AF_INET6, t->u.target_size - sizeof(*t), | ||
646 | name, e->comefrom, e->ipv6.proto, | ||
647 | e->ipv6.invflags & IP6T_INV_PROTO); | ||
648 | if (ret) | ||
649 | goto err; | ||
650 | |||
635 | if (t->u.kernel.target == &ip6t_standard_target) { | 651 | if (t->u.kernel.target == &ip6t_standard_target) { |
636 | if (!standard_check(t, size)) { | 652 | if (!standard_check(t, size)) { |
637 | ret = -EINVAL; | 653 | ret = -EINVAL; |
@@ -642,16 +658,16 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
642 | t->u.target_size | 658 | t->u.target_size |
643 | - sizeof(*t), | 659 | - sizeof(*t), |
644 | e->comefrom)) { | 660 | e->comefrom)) { |
645 | module_put(t->u.kernel.target->me); | ||
646 | duprintf("ip_tables: check failed for `%s'.\n", | 661 | duprintf("ip_tables: check failed for `%s'.\n", |
647 | t->u.kernel.target->name); | 662 | t->u.kernel.target->name); |
648 | ret = -EINVAL; | 663 | ret = -EINVAL; |
649 | goto cleanup_matches; | 664 | goto err; |
650 | } | 665 | } |
651 | 666 | ||
652 | (*i)++; | 667 | (*i)++; |
653 | return 0; | 668 | return 0; |
654 | 669 | err: | |
670 | module_put(t->u.kernel.target->me); | ||
655 | cleanup_matches: | 671 | cleanup_matches: |
656 | IP6T_MATCH_ITERATE(e, cleanup_match, &j); | 672 | IP6T_MATCH_ITERATE(e, cleanup_match, &j); |
657 | return ret; | 673 | return ret; |