diff options
| author | Jan Engelhardt <jengelh@medozas.de> | 2010-02-24 12:35:37 -0500 |
|---|---|---|
| committer | Patrick McHardy <kaber@trash.net> | 2010-02-24 12:35:37 -0500 |
| commit | 6bdb331bc6910d1ccb74dc9852fc858c5916c927 (patch) | |
| tree | d77dd2df2d6d43ce25703ce8c9ecab0173c14a7f /net | |
| parent | dcea992aca82cb08b4674c4c783e325835408d1e (diff) | |
netfilter: xtables: optimize call flow around xt_ematch_foreach
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
| -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 3a7fc732b918..36edc7d5f284 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 1537e6bad5d9..c5a963e4b545 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 | ||
