diff options
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 93 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 93 |
2 files changed, 62 insertions, 124 deletions
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3a7fc732b91..36edc7d5f28 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -572,14 +572,10 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
572 | return 1; | 572 | return 1; |
573 | } | 573 | } |
574 | 574 | ||
575 | static int | 575 | static void cleanup_match(struct ipt_entry_match *m, struct net *net) |
576 | cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) | ||
577 | { | 576 | { |
578 | struct xt_mtdtor_param par; | 577 | struct xt_mtdtor_param par; |
579 | 578 | ||
580 | if (i && (*i)-- == 0) | ||
581 | return 1; | ||
582 | |||
583 | par.net = net; | 579 | par.net = net; |
584 | par.match = m->u.kernel.match; | 580 | par.match = m->u.kernel.match; |
585 | par.matchinfo = m->data; | 581 | par.matchinfo = m->data; |
@@ -587,7 +583,6 @@ cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i) | |||
587 | if (par.match->destroy != NULL) | 583 | if (par.match->destroy != NULL) |
588 | par.match->destroy(&par); | 584 | par.match->destroy(&par); |
589 | module_put(par.match->me); | 585 | module_put(par.match->me); |
590 | return 0; | ||
591 | } | 586 | } |
592 | 587 | ||
593 | static int | 588 | static int |
@@ -612,8 +607,7 @@ check_entry(const struct ipt_entry *e, const char *name) | |||
612 | } | 607 | } |
613 | 608 | ||
614 | static int | 609 | static int |
615 | check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | 610 | check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) |
616 | unsigned int *i) | ||
617 | { | 611 | { |
618 | const struct ipt_ip *ip = par->entryinfo; | 612 | const struct ipt_ip *ip = par->entryinfo; |
619 | int ret; | 613 | int ret; |
@@ -628,13 +622,11 @@ check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | |||
628 | par.match->name); | 622 | par.match->name); |
629 | return ret; | 623 | return ret; |
630 | } | 624 | } |
631 | ++*i; | ||
632 | return 0; | 625 | return 0; |
633 | } | 626 | } |
634 | 627 | ||
635 | static int | 628 | static int |
636 | find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | 629 | find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par) |
637 | unsigned int *i) | ||
638 | { | 630 | { |
639 | struct xt_match *match; | 631 | struct xt_match *match; |
640 | int ret; | 632 | int ret; |
@@ -648,7 +640,7 @@ find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par, | |||
648 | } | 640 | } |
649 | m->u.kernel.match = match; | 641 | m->u.kernel.match = match; |
650 | 642 | ||
651 | ret = check_match(m, par, i); | 643 | ret = check_match(m, par); |
652 | if (ret) | 644 | if (ret) |
653 | goto err; | 645 | goto err; |
654 | 646 | ||
@@ -704,12 +696,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, | |||
704 | mtpar.hook_mask = e->comefrom; | 696 | mtpar.hook_mask = e->comefrom; |
705 | mtpar.family = NFPROTO_IPV4; | 697 | mtpar.family = NFPROTO_IPV4; |
706 | xt_ematch_foreach(ematch, e) { | 698 | xt_ematch_foreach(ematch, e) { |
707 | ret = find_check_match(ematch, &mtpar, &j); | 699 | ret = find_check_match(ematch, &mtpar); |
708 | if (ret != 0) | 700 | if (ret != 0) |
709 | break; | 701 | goto cleanup_matches; |
702 | ++j; | ||
710 | } | 703 | } |
711 | if (ret != 0) | ||
712 | goto cleanup_matches; | ||
713 | 704 | ||
714 | t = ipt_get_target(e); | 705 | t = ipt_get_target(e); |
715 | target = try_then_request_module(xt_find_target(AF_INET, | 706 | target = try_then_request_module(xt_find_target(AF_INET, |
@@ -730,9 +721,11 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name, | |||
730 | err: | 721 | err: |
731 | module_put(t->u.kernel.target->me); | 722 | module_put(t->u.kernel.target->me); |
732 | cleanup_matches: | 723 | cleanup_matches: |
733 | xt_ematch_foreach(ematch, e) | 724 | xt_ematch_foreach(ematch, e) { |
734 | if (cleanup_match(ematch, net, &j) != 0) | 725 | if (j-- == 0) |
735 | break; | 726 | break; |
727 | cleanup_match(ematch, net); | ||
728 | } | ||
736 | return ret; | 729 | return ret; |
737 | } | 730 | } |
738 | 731 | ||
@@ -807,8 +800,7 @@ cleanup_entry(struct ipt_entry *e, struct net *net) | |||
807 | 800 | ||
808 | /* Cleanup all matches */ | 801 | /* Cleanup all matches */ |
809 | xt_ematch_foreach(ematch, e) | 802 | xt_ematch_foreach(ematch, e) |
810 | if (cleanup_match(ematch, net, NULL) != 0) | 803 | cleanup_match(ematch, net); |
811 | break; | ||
812 | t = ipt_get_target(e); | 804 | t = ipt_get_target(e); |
813 | 805 | ||
814 | par.net = net; | 806 | par.net = net; |
@@ -1064,13 +1056,6 @@ static int compat_standard_to_user(void __user *dst, const void *src) | |||
1064 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; | 1056 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; |
1065 | } | 1057 | } |
1066 | 1058 | ||
1067 | static inline int | ||
1068 | compat_calc_match(const struct ipt_entry_match *m, int *size) | ||
1069 | { | ||
1070 | *size += xt_compat_match_offset(m->u.kernel.match); | ||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | static int compat_calc_entry(const struct ipt_entry *e, | 1059 | static int compat_calc_entry(const struct ipt_entry *e, |
1075 | const struct xt_table_info *info, | 1060 | const struct xt_table_info *info, |
1076 | const void *base, struct xt_table_info *newinfo) | 1061 | const void *base, struct xt_table_info *newinfo) |
@@ -1083,8 +1068,7 @@ static int compat_calc_entry(const struct ipt_entry *e, | |||
1083 | off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); | 1068 | off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); |
1084 | entry_offset = (void *)e - base; | 1069 | entry_offset = (void *)e - base; |
1085 | xt_ematch_foreach(ematch, e) | 1070 | xt_ematch_foreach(ematch, e) |
1086 | if (compat_calc_match(ematch, &off) != 0) | 1071 | off += xt_compat_match_offset(ematch->u.kernel.match); |
1087 | break; | ||
1088 | t = ipt_get_target_c(e); | 1072 | t = ipt_get_target_c(e); |
1089 | off += xt_compat_target_offset(t->u.kernel.target); | 1073 | off += xt_compat_target_offset(t->u.kernel.target); |
1090 | newinfo->size -= off; | 1074 | newinfo->size -= off; |
@@ -1475,11 +1459,9 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr, | |||
1475 | xt_ematch_foreach(ematch, e) { | 1459 | xt_ematch_foreach(ematch, e) { |
1476 | ret = xt_compat_match_to_user(ematch, dstptr, size); | 1460 | ret = xt_compat_match_to_user(ematch, dstptr, size); |
1477 | if (ret != 0) | 1461 | if (ret != 0) |
1478 | break; | 1462 | return ret; |
1479 | } | 1463 | } |
1480 | target_offset = e->target_offset - (origsize - *size); | 1464 | target_offset = e->target_offset - (origsize - *size); |
1481 | if (ret) | ||
1482 | return ret; | ||
1483 | t = ipt_get_target(e); | 1465 | t = ipt_get_target(e); |
1484 | ret = xt_compat_target_to_user(t, dstptr, size); | 1466 | ret = xt_compat_target_to_user(t, dstptr, size); |
1485 | if (ret) | 1467 | if (ret) |
@@ -1496,7 +1478,7 @@ compat_find_calc_match(struct ipt_entry_match *m, | |||
1496 | const char *name, | 1478 | const char *name, |
1497 | const struct ipt_ip *ip, | 1479 | const struct ipt_ip *ip, |
1498 | unsigned int hookmask, | 1480 | unsigned int hookmask, |
1499 | int *size, unsigned int *i) | 1481 | int *size) |
1500 | { | 1482 | { |
1501 | struct xt_match *match; | 1483 | struct xt_match *match; |
1502 | 1484 | ||
@@ -1510,18 +1492,6 @@ compat_find_calc_match(struct ipt_entry_match *m, | |||
1510 | } | 1492 | } |
1511 | m->u.kernel.match = match; | 1493 | m->u.kernel.match = match; |
1512 | *size += xt_compat_match_offset(match); | 1494 | *size += xt_compat_match_offset(match); |
1513 | |||
1514 | (*i)++; | ||
1515 | return 0; | ||
1516 | } | ||
1517 | |||
1518 | static int | ||
1519 | compat_release_match(struct ipt_entry_match *m, unsigned int *i) | ||
1520 | { | ||
1521 | if (i && (*i)-- == 0) | ||
1522 | return 1; | ||
1523 | |||
1524 | module_put(m->u.kernel.match->me); | ||
1525 | return 0; | 1495 | return 0; |
1526 | } | 1496 | } |
1527 | 1497 | ||
@@ -1532,8 +1502,7 @@ static void compat_release_entry(struct compat_ipt_entry *e) | |||
1532 | 1502 | ||
1533 | /* Cleanup all matches */ | 1503 | /* Cleanup all matches */ |
1534 | xt_ematch_foreach(ematch, e) | 1504 | xt_ematch_foreach(ematch, e) |
1535 | if (compat_release_match(ematch, NULL) != 0) | 1505 | module_put(ematch->u.kernel.match->me); |
1536 | break; | ||
1537 | t = compat_ipt_get_target(e); | 1506 | t = compat_ipt_get_target(e); |
1538 | module_put(t->u.kernel.target->me); | 1507 | module_put(t->u.kernel.target->me); |
1539 | } | 1508 | } |
@@ -1579,12 +1548,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |||
1579 | j = 0; | 1548 | j = 0; |
1580 | xt_ematch_foreach(ematch, e) { | 1549 | xt_ematch_foreach(ematch, e) { |
1581 | ret = compat_find_calc_match(ematch, name, | 1550 | ret = compat_find_calc_match(ematch, name, |
1582 | &e->ip, e->comefrom, &off, &j); | 1551 | &e->ip, e->comefrom, &off); |
1583 | if (ret != 0) | 1552 | if (ret != 0) |
1584 | break; | 1553 | goto release_matches; |
1554 | ++j; | ||
1585 | } | 1555 | } |
1586 | if (ret != 0) | ||
1587 | goto release_matches; | ||
1588 | 1556 | ||
1589 | t = compat_ipt_get_target(e); | 1557 | t = compat_ipt_get_target(e); |
1590 | target = try_then_request_module(xt_find_target(AF_INET, | 1558 | target = try_then_request_module(xt_find_target(AF_INET, |
@@ -1621,9 +1589,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |||
1621 | out: | 1589 | out: |
1622 | module_put(t->u.kernel.target->me); | 1590 | module_put(t->u.kernel.target->me); |
1623 | release_matches: | 1591 | release_matches: |
1624 | xt_ematch_foreach(ematch, e) | 1592 | xt_ematch_foreach(ematch, e) { |
1625 | if (compat_release_match(ematch, &j) != 0) | 1593 | if (j-- == 0) |
1626 | break; | 1594 | break; |
1595 | module_put(ematch->u.kernel.match->me); | ||
1596 | } | ||
1627 | return ret; | 1597 | return ret; |
1628 | } | 1598 | } |
1629 | 1599 | ||
@@ -1651,10 +1621,8 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, | |||
1651 | xt_ematch_foreach(ematch, e) { | 1621 | xt_ematch_foreach(ematch, e) { |
1652 | ret = xt_compat_match_from_user(ematch, dstptr, size); | 1622 | ret = xt_compat_match_from_user(ematch, dstptr, size); |
1653 | if (ret != 0) | 1623 | if (ret != 0) |
1654 | break; | 1624 | return ret; |
1655 | } | 1625 | } |
1656 | if (ret) | ||
1657 | return ret; | ||
1658 | de->target_offset = e->target_offset - (origsize - *size); | 1626 | de->target_offset = e->target_offset - (origsize - *size); |
1659 | t = compat_ipt_get_target(e); | 1627 | t = compat_ipt_get_target(e); |
1660 | target = t->u.kernel.target; | 1628 | target = t->u.kernel.target; |
@@ -1685,12 +1653,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) | |||
1685 | mtpar.hook_mask = e->comefrom; | 1653 | mtpar.hook_mask = e->comefrom; |
1686 | mtpar.family = NFPROTO_IPV4; | 1654 | mtpar.family = NFPROTO_IPV4; |
1687 | xt_ematch_foreach(ematch, e) { | 1655 | xt_ematch_foreach(ematch, e) { |
1688 | ret = check_match(ematch, &mtpar, &j); | 1656 | ret = check_match(ematch, &mtpar); |
1689 | if (ret != 0) | 1657 | if (ret != 0) |
1690 | break; | 1658 | goto cleanup_matches; |
1659 | ++j; | ||
1691 | } | 1660 | } |
1692 | if (ret) | ||
1693 | goto cleanup_matches; | ||
1694 | 1661 | ||
1695 | ret = check_target(e, net, name); | 1662 | ret = check_target(e, net, name); |
1696 | if (ret) | 1663 | if (ret) |
@@ -1698,9 +1665,11 @@ compat_check_entry(struct ipt_entry *e, struct net *net, const char *name) | |||
1698 | return 0; | 1665 | return 0; |
1699 | 1666 | ||
1700 | cleanup_matches: | 1667 | cleanup_matches: |
1701 | xt_ematch_foreach(ematch, e) | 1668 | xt_ematch_foreach(ematch, e) { |
1702 | if (cleanup_match(ematch, net, &j) != 0) | 1669 | if (j-- == 0) |
1703 | break; | 1670 | break; |
1671 | cleanup_match(ematch, net); | ||
1672 | } | ||
1704 | return ret; | 1673 | return ret; |
1705 | } | 1674 | } |
1706 | 1675 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1537e6bad5d..c5a963e4b54 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -603,14 +603,10 @@ mark_source_chains(const struct xt_table_info *newinfo, | |||
603 | return 1; | 603 | return 1; |
604 | } | 604 | } |
605 | 605 | ||
606 | static int | 606 | static void cleanup_match(struct ip6t_entry_match *m, struct net *net) |
607 | cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) | ||
608 | { | 607 | { |
609 | struct xt_mtdtor_param par; | 608 | struct xt_mtdtor_param par; |
610 | 609 | ||
611 | if (i && (*i)-- == 0) | ||
612 | return 1; | ||
613 | |||
614 | par.net = net; | 610 | par.net = net; |
615 | par.match = m->u.kernel.match; | 611 | par.match = m->u.kernel.match; |
616 | par.matchinfo = m->data; | 612 | par.matchinfo = m->data; |
@@ -618,7 +614,6 @@ cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i) | |||
618 | if (par.match->destroy != NULL) | 614 | if (par.match->destroy != NULL) |
619 | par.match->destroy(&par); | 615 | par.match->destroy(&par); |
620 | module_put(par.match->me); | 616 | module_put(par.match->me); |
621 | return 0; | ||
622 | } | 617 | } |
623 | 618 | ||
624 | static int | 619 | static int |
@@ -642,8 +637,7 @@ check_entry(const struct ip6t_entry *e, const char *name) | |||
642 | return 0; | 637 | return 0; |
643 | } | 638 | } |
644 | 639 | ||
645 | static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | 640 | static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) |
646 | unsigned int *i) | ||
647 | { | 641 | { |
648 | const struct ip6t_ip6 *ipv6 = par->entryinfo; | 642 | const struct ip6t_ip6 *ipv6 = par->entryinfo; |
649 | int ret; | 643 | int ret; |
@@ -658,13 +652,11 @@ static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | |||
658 | par.match->name); | 652 | par.match->name); |
659 | return ret; | 653 | return ret; |
660 | } | 654 | } |
661 | ++*i; | ||
662 | return 0; | 655 | return 0; |
663 | } | 656 | } |
664 | 657 | ||
665 | static int | 658 | static int |
666 | find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | 659 | find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par) |
667 | unsigned int *i) | ||
668 | { | 660 | { |
669 | struct xt_match *match; | 661 | struct xt_match *match; |
670 | int ret; | 662 | int ret; |
@@ -678,7 +670,7 @@ find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par, | |||
678 | } | 670 | } |
679 | m->u.kernel.match = match; | 671 | m->u.kernel.match = match; |
680 | 672 | ||
681 | ret = check_match(m, par, i); | 673 | ret = check_match(m, par); |
682 | if (ret) | 674 | if (ret) |
683 | goto err; | 675 | goto err; |
684 | 676 | ||
@@ -735,12 +727,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
735 | mtpar.hook_mask = e->comefrom; | 727 | mtpar.hook_mask = e->comefrom; |
736 | mtpar.family = NFPROTO_IPV6; | 728 | mtpar.family = NFPROTO_IPV6; |
737 | xt_ematch_foreach(ematch, e) { | 729 | xt_ematch_foreach(ematch, e) { |
738 | ret = find_check_match(ematch, &mtpar, &j); | 730 | ret = find_check_match(ematch, &mtpar); |
739 | if (ret != 0) | 731 | if (ret != 0) |
740 | break; | 732 | goto cleanup_matches; |
733 | ++j; | ||
741 | } | 734 | } |
742 | if (ret != 0) | ||
743 | goto cleanup_matches; | ||
744 | 735 | ||
745 | t = ip6t_get_target(e); | 736 | t = ip6t_get_target(e); |
746 | target = try_then_request_module(xt_find_target(AF_INET6, | 737 | target = try_then_request_module(xt_find_target(AF_INET6, |
@@ -761,9 +752,11 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
761 | err: | 752 | err: |
762 | module_put(t->u.kernel.target->me); | 753 | module_put(t->u.kernel.target->me); |
763 | cleanup_matches: | 754 | cleanup_matches: |
764 | xt_ematch_foreach(ematch, e) | 755 | xt_ematch_foreach(ematch, e) { |
765 | if (cleanup_match(ematch, net, &j) != 0) | 756 | if (j-- == 0) |
766 | break; | 757 | break; |
758 | cleanup_match(ematch, net); | ||
759 | } | ||
767 | return ret; | 760 | return ret; |
768 | } | 761 | } |
769 | 762 | ||
@@ -837,8 +830,7 @@ static void cleanup_entry(struct ip6t_entry *e, struct net *net) | |||
837 | 830 | ||
838 | /* Cleanup all matches */ | 831 | /* Cleanup all matches */ |
839 | xt_ematch_foreach(ematch, e) | 832 | xt_ematch_foreach(ematch, e) |
840 | if (cleanup_match(ematch, net, NULL) != 0) | 833 | cleanup_match(ematch, net); |
841 | break; | ||
842 | t = ip6t_get_target(e); | 834 | t = ip6t_get_target(e); |
843 | 835 | ||
844 | par.net = net; | 836 | par.net = net; |
@@ -1094,13 +1086,6 @@ static int compat_standard_to_user(void __user *dst, const void *src) | |||
1094 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; | 1086 | return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; |
1095 | } | 1087 | } |
1096 | 1088 | ||
1097 | static inline int | ||
1098 | compat_calc_match(const struct ip6t_entry_match *m, int *size) | ||
1099 | { | ||
1100 | *size += xt_compat_match_offset(m->u.kernel.match); | ||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | static int compat_calc_entry(const struct ip6t_entry *e, | 1089 | static int compat_calc_entry(const struct ip6t_entry *e, |
1105 | const struct xt_table_info *info, | 1090 | const struct xt_table_info *info, |
1106 | const void *base, struct xt_table_info *newinfo) | 1091 | const void *base, struct xt_table_info *newinfo) |
@@ -1113,8 +1098,7 @@ static int compat_calc_entry(const struct ip6t_entry *e, | |||
1113 | off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); | 1098 | off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); |
1114 | entry_offset = (void *)e - base; | 1099 | entry_offset = (void *)e - base; |
1115 | xt_ematch_foreach(ematch, e) | 1100 | xt_ematch_foreach(ematch, e) |
1116 | if (compat_calc_match(ematch, &off) != 0) | 1101 | off += xt_compat_match_offset(ematch->u.kernel.match); |
1117 | break; | ||
1118 | t = ip6t_get_target_c(e); | 1102 | t = ip6t_get_target_c(e); |
1119 | off += xt_compat_target_offset(t->u.kernel.target); | 1103 | off += xt_compat_target_offset(t->u.kernel.target); |
1120 | newinfo->size -= off; | 1104 | newinfo->size -= off; |
@@ -1508,11 +1492,9 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | |||
1508 | xt_ematch_foreach(ematch, e) { | 1492 | xt_ematch_foreach(ematch, e) { |
1509 | ret = xt_compat_match_to_user(ematch, dstptr, size); | 1493 | ret = xt_compat_match_to_user(ematch, dstptr, size); |
1510 | if (ret != 0) | 1494 | if (ret != 0) |
1511 | break; | 1495 | return ret; |
1512 | } | 1496 | } |
1513 | target_offset = e->target_offset - (origsize - *size); | 1497 | target_offset = e->target_offset - (origsize - *size); |
1514 | if (ret) | ||
1515 | return ret; | ||
1516 | t = ip6t_get_target(e); | 1498 | t = ip6t_get_target(e); |
1517 | ret = xt_compat_target_to_user(t, dstptr, size); | 1499 | ret = xt_compat_target_to_user(t, dstptr, size); |
1518 | if (ret) | 1500 | if (ret) |
@@ -1529,7 +1511,7 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1529 | const char *name, | 1511 | const char *name, |
1530 | const struct ip6t_ip6 *ipv6, | 1512 | const struct ip6t_ip6 *ipv6, |
1531 | unsigned int hookmask, | 1513 | unsigned int hookmask, |
1532 | int *size, unsigned int *i) | 1514 | int *size) |
1533 | { | 1515 | { |
1534 | struct xt_match *match; | 1516 | struct xt_match *match; |
1535 | 1517 | ||
@@ -1543,18 +1525,6 @@ compat_find_calc_match(struct ip6t_entry_match *m, | |||
1543 | } | 1525 | } |
1544 | m->u.kernel.match = match; | 1526 | m->u.kernel.match = match; |
1545 | *size += xt_compat_match_offset(match); | 1527 | *size += xt_compat_match_offset(match); |
1546 | |||
1547 | (*i)++; | ||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | static int | ||
1552 | compat_release_match(struct ip6t_entry_match *m, unsigned int *i) | ||
1553 | { | ||
1554 | if (i && (*i)-- == 0) | ||
1555 | return 1; | ||
1556 | |||
1557 | module_put(m->u.kernel.match->me); | ||
1558 | return 0; | 1528 | return 0; |
1559 | } | 1529 | } |
1560 | 1530 | ||
@@ -1565,8 +1535,7 @@ static void compat_release_entry(struct compat_ip6t_entry *e) | |||
1565 | 1535 | ||
1566 | /* Cleanup all matches */ | 1536 | /* Cleanup all matches */ |
1567 | xt_ematch_foreach(ematch, e) | 1537 | xt_ematch_foreach(ematch, e) |
1568 | if (compat_release_match(ematch, NULL) != 0) | 1538 | module_put(ematch->u.kernel.match->me); |
1569 | break; | ||
1570 | t = compat_ip6t_get_target(e); | 1539 | t = compat_ip6t_get_target(e); |
1571 | module_put(t->u.kernel.target->me); | 1540 | module_put(t->u.kernel.target->me); |
1572 | } | 1541 | } |
@@ -1612,12 +1581,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1612 | j = 0; | 1581 | j = 0; |
1613 | xt_ematch_foreach(ematch, e) { | 1582 | xt_ematch_foreach(ematch, e) { |
1614 | ret = compat_find_calc_match(ematch, name, | 1583 | ret = compat_find_calc_match(ematch, name, |
1615 | &e->ipv6, e->comefrom, &off, &j); | 1584 | &e->ipv6, e->comefrom, &off); |
1616 | if (ret != 0) | 1585 | if (ret != 0) |
1617 | break; | 1586 | goto release_matches; |
1587 | ++j; | ||
1618 | } | 1588 | } |
1619 | if (ret != 0) | ||
1620 | goto release_matches; | ||
1621 | 1589 | ||
1622 | t = compat_ip6t_get_target(e); | 1590 | t = compat_ip6t_get_target(e); |
1623 | target = try_then_request_module(xt_find_target(AF_INET6, | 1591 | target = try_then_request_module(xt_find_target(AF_INET6, |
@@ -1654,9 +1622,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1654 | out: | 1622 | out: |
1655 | module_put(t->u.kernel.target->me); | 1623 | module_put(t->u.kernel.target->me); |
1656 | release_matches: | 1624 | release_matches: |
1657 | xt_ematch_foreach(ematch, e) | 1625 | xt_ematch_foreach(ematch, e) { |
1658 | if (compat_release_match(ematch, &j) != 0) | 1626 | if (j-- == 0) |
1659 | break; | 1627 | break; |
1628 | module_put(ematch->u.kernel.match->me); | ||
1629 | } | ||
1660 | return ret; | 1630 | return ret; |
1661 | } | 1631 | } |
1662 | 1632 | ||
@@ -1684,10 +1654,8 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1684 | xt_ematch_foreach(ematch, e) { | 1654 | xt_ematch_foreach(ematch, e) { |
1685 | ret = xt_compat_match_from_user(ematch, dstptr, size); | 1655 | ret = xt_compat_match_from_user(ematch, dstptr, size); |
1686 | if (ret != 0) | 1656 | if (ret != 0) |
1687 | break; | 1657 | return ret; |
1688 | } | 1658 | } |
1689 | if (ret) | ||
1690 | return ret; | ||
1691 | de->target_offset = e->target_offset - (origsize - *size); | 1659 | de->target_offset = e->target_offset - (origsize - *size); |
1692 | t = compat_ip6t_get_target(e); | 1660 | t = compat_ip6t_get_target(e); |
1693 | target = t->u.kernel.target; | 1661 | target = t->u.kernel.target; |
@@ -1718,12 +1686,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, | |||
1718 | mtpar.hook_mask = e->comefrom; | 1686 | mtpar.hook_mask = e->comefrom; |
1719 | mtpar.family = NFPROTO_IPV6; | 1687 | mtpar.family = NFPROTO_IPV6; |
1720 | xt_ematch_foreach(ematch, e) { | 1688 | xt_ematch_foreach(ematch, e) { |
1721 | ret = check_match(ematch, &mtpar, &j); | 1689 | ret = check_match(ematch, &mtpar); |
1722 | if (ret != 0) | 1690 | if (ret != 0) |
1723 | break; | 1691 | goto cleanup_matches; |
1692 | ++j; | ||
1724 | } | 1693 | } |
1725 | if (ret) | ||
1726 | goto cleanup_matches; | ||
1727 | 1694 | ||
1728 | ret = check_target(e, net, name); | 1695 | ret = check_target(e, net, name); |
1729 | if (ret) | 1696 | if (ret) |
@@ -1731,9 +1698,11 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, | |||
1731 | return 0; | 1698 | return 0; |
1732 | 1699 | ||
1733 | cleanup_matches: | 1700 | cleanup_matches: |
1734 | xt_ematch_foreach(ematch, e) | 1701 | xt_ematch_foreach(ematch, e) { |
1735 | if (cleanup_match(ematch, net, &j) != 0) | 1702 | if (j-- == 0) |
1736 | break; | 1703 | break; |
1704 | cleanup_match(ematch, net); | ||
1705 | } | ||
1737 | return ret; | 1706 | return ret; |
1738 | } | 1707 | } |
1739 | 1708 | ||