diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 179 |
1 files changed, 61 insertions, 118 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 23926e38d36b..b7e27c19c7ab 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -710,7 +710,7 @@ static int check_target(struct ip6t_entry *e, struct net *net, const char *name) | |||
710 | 710 | ||
711 | static int | 711 | static int |
712 | find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | 712 | find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, |
713 | unsigned int size, unsigned int *i) | 713 | unsigned int size) |
714 | { | 714 | { |
715 | struct ip6t_entry_target *t; | 715 | struct ip6t_entry_target *t; |
716 | struct xt_target *target; | 716 | struct xt_target *target; |
@@ -747,8 +747,6 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name, | |||
747 | ret = check_target(e, net, name); | 747 | ret = check_target(e, net, name); |
748 | if (ret) | 748 | if (ret) |
749 | goto err; | 749 | goto err; |
750 | |||
751 | (*i)++; | ||
752 | return 0; | 750 | return 0; |
753 | err: | 751 | err: |
754 | module_put(t->u.kernel.target->me); | 752 | module_put(t->u.kernel.target->me); |
@@ -779,8 +777,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
779 | const unsigned char *limit, | 777 | const unsigned char *limit, |
780 | const unsigned int *hook_entries, | 778 | const unsigned int *hook_entries, |
781 | const unsigned int *underflows, | 779 | const unsigned int *underflows, |
782 | unsigned int valid_hooks, | 780 | unsigned int valid_hooks) |
783 | unsigned int *i) | ||
784 | { | 781 | { |
785 | unsigned int h; | 782 | unsigned int h; |
786 | 783 | ||
@@ -817,20 +814,14 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
817 | /* Clear counters and comefrom */ | 814 | /* Clear counters and comefrom */ |
818 | e->counters = ((struct xt_counters) { 0, 0 }); | 815 | e->counters = ((struct xt_counters) { 0, 0 }); |
819 | e->comefrom = 0; | 816 | e->comefrom = 0; |
820 | |||
821 | (*i)++; | ||
822 | return 0; | 817 | return 0; |
823 | } | 818 | } |
824 | 819 | ||
825 | static int | 820 | static void cleanup_entry(struct ip6t_entry *e, struct net *net) |
826 | cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) | ||
827 | { | 821 | { |
828 | struct xt_tgdtor_param par; | 822 | struct xt_tgdtor_param par; |
829 | struct ip6t_entry_target *t; | 823 | struct ip6t_entry_target *t; |
830 | 824 | ||
831 | if (i && (*i)-- == 0) | ||
832 | return 1; | ||
833 | |||
834 | /* Cleanup all matches */ | 825 | /* Cleanup all matches */ |
835 | IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); | 826 | IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL); |
836 | t = ip6t_get_target(e); | 827 | t = ip6t_get_target(e); |
@@ -842,7 +833,6 @@ cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i) | |||
842 | if (par.target->destroy != NULL) | 833 | if (par.target->destroy != NULL) |
843 | par.target->destroy(&par); | 834 | par.target->destroy(&par); |
844 | module_put(par.target->me); | 835 | module_put(par.target->me); |
845 | return 0; | ||
846 | } | 836 | } |
847 | 837 | ||
848 | /* Checks and translates the user-supplied table segment (held in | 838 | /* Checks and translates the user-supplied table segment (held in |
@@ -876,13 +866,11 @@ translate_table(struct net *net, | |||
876 | /* Walk through entries, checking offsets. */ | 866 | /* Walk through entries, checking offsets. */ |
877 | xt_entry_foreach(iter, entry0, newinfo->size) { | 867 | xt_entry_foreach(iter, entry0, newinfo->size) { |
878 | ret = check_entry_size_and_hooks(iter, newinfo, entry0, | 868 | ret = check_entry_size_and_hooks(iter, newinfo, entry0, |
879 | entry0 + size, hook_entries, underflows, | 869 | entry0 + size, hook_entries, underflows, valid_hooks); |
880 | valid_hooks, &i); | ||
881 | if (ret != 0) | 870 | if (ret != 0) |
882 | break; | 871 | return ret; |
872 | ++i; | ||
883 | } | 873 | } |
884 | if (ret != 0) | ||
885 | return ret; | ||
886 | 874 | ||
887 | if (i != number) { | 875 | if (i != number) { |
888 | duprintf("translate_table: %u not %u entries\n", | 876 | duprintf("translate_table: %u not %u entries\n", |
@@ -913,15 +901,18 @@ translate_table(struct net *net, | |||
913 | /* Finally, each sanity check must pass */ | 901 | /* Finally, each sanity check must pass */ |
914 | i = 0; | 902 | i = 0; |
915 | xt_entry_foreach(iter, entry0, newinfo->size) { | 903 | xt_entry_foreach(iter, entry0, newinfo->size) { |
916 | ret = find_check_entry(iter, net, name, size, &i); | 904 | ret = find_check_entry(iter, net, name, size); |
917 | if (ret != 0) | 905 | if (ret != 0) |
918 | break; | 906 | break; |
907 | ++i; | ||
919 | } | 908 | } |
920 | 909 | ||
921 | if (ret != 0) { | 910 | if (ret != 0) { |
922 | xt_entry_foreach(iter, entry0, newinfo->size) | 911 | xt_entry_foreach(iter, entry0, newinfo->size) { |
923 | if (cleanup_entry(iter, net, &i) != 0) | 912 | if (i-- == 0) |
924 | break; | 913 | break; |
914 | cleanup_entry(iter, net); | ||
915 | } | ||
925 | return ret; | 916 | return ret; |
926 | } | 917 | } |
927 | 918 | ||
@@ -934,29 +925,6 @@ translate_table(struct net *net, | |||
934 | return ret; | 925 | return ret; |
935 | } | 926 | } |
936 | 927 | ||
937 | /* Gets counters. */ | ||
938 | static inline int | ||
939 | add_entry_to_counter(const struct ip6t_entry *e, | ||
940 | struct xt_counters total[], | ||
941 | unsigned int *i) | ||
942 | { | ||
943 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | ||
944 | |||
945 | (*i)++; | ||
946 | return 0; | ||
947 | } | ||
948 | |||
949 | static inline int | ||
950 | set_entry_to_counter(const struct ip6t_entry *e, | ||
951 | struct ip6t_counters total[], | ||
952 | unsigned int *i) | ||
953 | { | ||
954 | SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | ||
955 | |||
956 | (*i)++; | ||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static void | 928 | static void |
961 | get_counters(const struct xt_table_info *t, | 929 | get_counters(const struct xt_table_info *t, |
962 | struct xt_counters counters[]) | 930 | struct xt_counters counters[]) |
@@ -977,18 +945,22 @@ get_counters(const struct xt_table_info *t, | |||
977 | curcpu = smp_processor_id(); | 945 | curcpu = smp_processor_id(); |
978 | 946 | ||
979 | i = 0; | 947 | i = 0; |
980 | xt_entry_foreach(iter, t->entries[curcpu], t->size) | 948 | xt_entry_foreach(iter, t->entries[curcpu], t->size) { |
981 | if (set_entry_to_counter(iter, counters, &i) != 0) | 949 | SET_COUNTER(counters[i], iter->counters.bcnt, |
982 | break; | 950 | iter->counters.pcnt); |
951 | ++i; | ||
952 | } | ||
983 | 953 | ||
984 | for_each_possible_cpu(cpu) { | 954 | for_each_possible_cpu(cpu) { |
985 | if (cpu == curcpu) | 955 | if (cpu == curcpu) |
986 | continue; | 956 | continue; |
987 | i = 0; | 957 | i = 0; |
988 | xt_info_wrlock(cpu); | 958 | xt_info_wrlock(cpu); |
989 | xt_entry_foreach(iter, t->entries[cpu], t->size) | 959 | xt_entry_foreach(iter, t->entries[cpu], t->size) { |
990 | if (add_entry_to_counter(iter, counters, &i) != 0) | 960 | ADD_COUNTER(counters[i], iter->counters.bcnt, |
991 | break; | 961 | iter->counters.pcnt); |
962 | ++i; | ||
963 | } | ||
992 | xt_info_wrunlock(cpu); | 964 | xt_info_wrunlock(cpu); |
993 | } | 965 | } |
994 | local_bh_enable(); | 966 | local_bh_enable(); |
@@ -1148,7 +1120,7 @@ static int compat_table_info(const struct xt_table_info *info, | |||
1148 | { | 1120 | { |
1149 | struct ip6t_entry *iter; | 1121 | struct ip6t_entry *iter; |
1150 | void *loc_cpu_entry; | 1122 | void *loc_cpu_entry; |
1151 | int ret = 0; | 1123 | int ret; |
1152 | 1124 | ||
1153 | if (!newinfo || !info) | 1125 | if (!newinfo || !info) |
1154 | return -EINVAL; | 1126 | return -EINVAL; |
@@ -1160,9 +1132,9 @@ static int compat_table_info(const struct xt_table_info *info, | |||
1160 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { | 1132 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { |
1161 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); | 1133 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); |
1162 | if (ret != 0) | 1134 | if (ret != 0) |
1163 | break; | 1135 | return ret; |
1164 | } | 1136 | } |
1165 | return ret; | 1137 | return 0; |
1166 | } | 1138 | } |
1167 | #endif | 1139 | #endif |
1168 | 1140 | ||
@@ -1321,8 +1293,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
1321 | /* Decrease module usage counts and free resource */ | 1293 | /* Decrease module usage counts and free resource */ |
1322 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1294 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1323 | xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) | 1295 | xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) |
1324 | if (cleanup_entry(iter, net, NULL) != 0) | 1296 | cleanup_entry(iter, net); |
1325 | break; | ||
1326 | 1297 | ||
1327 | xt_free_table_info(oldinfo); | 1298 | xt_free_table_info(oldinfo); |
1328 | if (copy_to_user(counters_ptr, counters, | 1299 | if (copy_to_user(counters_ptr, counters, |
@@ -1385,26 +1356,12 @@ do_replace(struct net *net, const void __user *user, unsigned int len) | |||
1385 | 1356 | ||
1386 | free_newinfo_untrans: | 1357 | free_newinfo_untrans: |
1387 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) | 1358 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) |
1388 | if (cleanup_entry(iter, net, NULL) != 0) | 1359 | cleanup_entry(iter, net); |
1389 | break; | ||
1390 | free_newinfo: | 1360 | free_newinfo: |
1391 | xt_free_table_info(newinfo); | 1361 | xt_free_table_info(newinfo); |
1392 | return ret; | 1362 | return ret; |
1393 | } | 1363 | } |
1394 | 1364 | ||
1395 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
1396 | * and everything is OK. */ | ||
1397 | static int | ||
1398 | add_counter_to_entry(struct ip6t_entry *e, | ||
1399 | const struct xt_counters addme[], | ||
1400 | unsigned int *i) | ||
1401 | { | ||
1402 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
1403 | |||
1404 | (*i)++; | ||
1405 | return 0; | ||
1406 | } | ||
1407 | |||
1408 | static int | 1365 | static int |
1409 | do_add_counters(struct net *net, const void __user *user, unsigned int len, | 1366 | do_add_counters(struct net *net, const void __user *user, unsigned int len, |
1410 | int compat) | 1367 | int compat) |
@@ -1479,9 +1436,10 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, | |||
1479 | curcpu = smp_processor_id(); | 1436 | curcpu = smp_processor_id(); |
1480 | xt_info_wrlock(curcpu); | 1437 | xt_info_wrlock(curcpu); |
1481 | loc_cpu_entry = private->entries[curcpu]; | 1438 | loc_cpu_entry = private->entries[curcpu]; |
1482 | xt_entry_foreach(iter, loc_cpu_entry, private->size) | 1439 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { |
1483 | if (add_counter_to_entry(iter, paddc, &i) != 0) | 1440 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); |
1484 | break; | 1441 | ++i; |
1442 | } | ||
1485 | xt_info_wrunlock(curcpu); | 1443 | xt_info_wrunlock(curcpu); |
1486 | 1444 | ||
1487 | unlock_up_free: | 1445 | unlock_up_free: |
@@ -1510,7 +1468,7 @@ struct compat_ip6t_replace { | |||
1510 | static int | 1468 | static int |
1511 | compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | 1469 | compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, |
1512 | unsigned int *size, struct xt_counters *counters, | 1470 | unsigned int *size, struct xt_counters *counters, |
1513 | unsigned int *i) | 1471 | unsigned int i) |
1514 | { | 1472 | { |
1515 | struct ip6t_entry_target *t; | 1473 | struct ip6t_entry_target *t; |
1516 | struct compat_ip6t_entry __user *ce; | 1474 | struct compat_ip6t_entry __user *ce; |
@@ -1518,14 +1476,12 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | |||
1518 | compat_uint_t origsize; | 1476 | compat_uint_t origsize; |
1519 | int ret; | 1477 | int ret; |
1520 | 1478 | ||
1521 | ret = -EFAULT; | ||
1522 | origsize = *size; | 1479 | origsize = *size; |
1523 | ce = (struct compat_ip6t_entry __user *)*dstptr; | 1480 | ce = (struct compat_ip6t_entry __user *)*dstptr; |
1524 | if (copy_to_user(ce, e, sizeof(struct ip6t_entry))) | 1481 | if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 || |
1525 | goto out; | 1482 | copy_to_user(&ce->counters, &counters[i], |
1526 | 1483 | sizeof(counters[i])) != 0) | |
1527 | if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) | 1484 | return -EFAULT; |
1528 | goto out; | ||
1529 | 1485 | ||
1530 | *dstptr += sizeof(struct compat_ip6t_entry); | 1486 | *dstptr += sizeof(struct compat_ip6t_entry); |
1531 | *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); | 1487 | *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); |
@@ -1533,22 +1489,16 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr, | |||
1533 | ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); | 1489 | ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size); |
1534 | target_offset = e->target_offset - (origsize - *size); | 1490 | target_offset = e->target_offset - (origsize - *size); |
1535 | if (ret) | 1491 | if (ret) |
1536 | goto out; | 1492 | return ret; |
1537 | t = ip6t_get_target(e); | 1493 | t = ip6t_get_target(e); |
1538 | ret = xt_compat_target_to_user(t, dstptr, size); | 1494 | ret = xt_compat_target_to_user(t, dstptr, size); |
1539 | if (ret) | 1495 | if (ret) |
1540 | goto out; | 1496 | return ret; |
1541 | ret = -EFAULT; | ||
1542 | next_offset = e->next_offset - (origsize - *size); | 1497 | next_offset = e->next_offset - (origsize - *size); |
1543 | if (put_user(target_offset, &ce->target_offset)) | 1498 | if (put_user(target_offset, &ce->target_offset) != 0 || |
1544 | goto out; | 1499 | put_user(next_offset, &ce->next_offset) != 0) |
1545 | if (put_user(next_offset, &ce->next_offset)) | 1500 | return -EFAULT; |
1546 | goto out; | ||
1547 | |||
1548 | (*i)++; | ||
1549 | return 0; | 1501 | return 0; |
1550 | out: | ||
1551 | return ret; | ||
1552 | } | 1502 | } |
1553 | 1503 | ||
1554 | static int | 1504 | static int |
@@ -1585,19 +1535,14 @@ compat_release_match(struct ip6t_entry_match *m, unsigned int *i) | |||
1585 | return 0; | 1535 | return 0; |
1586 | } | 1536 | } |
1587 | 1537 | ||
1588 | static int | 1538 | static void compat_release_entry(struct compat_ip6t_entry *e) |
1589 | compat_release_entry(struct compat_ip6t_entry *e, unsigned int *i) | ||
1590 | { | 1539 | { |
1591 | struct ip6t_entry_target *t; | 1540 | struct ip6t_entry_target *t; |
1592 | 1541 | ||
1593 | if (i && (*i)-- == 0) | ||
1594 | return 1; | ||
1595 | |||
1596 | /* Cleanup all matches */ | 1542 | /* Cleanup all matches */ |
1597 | COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL); | 1543 | COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL); |
1598 | t = compat_ip6t_get_target(e); | 1544 | t = compat_ip6t_get_target(e); |
1599 | module_put(t->u.kernel.target->me); | 1545 | module_put(t->u.kernel.target->me); |
1600 | return 0; | ||
1601 | } | 1546 | } |
1602 | 1547 | ||
1603 | static int | 1548 | static int |
@@ -1608,7 +1553,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1608 | const unsigned char *limit, | 1553 | const unsigned char *limit, |
1609 | const unsigned int *hook_entries, | 1554 | const unsigned int *hook_entries, |
1610 | const unsigned int *underflows, | 1555 | const unsigned int *underflows, |
1611 | unsigned int *i, | ||
1612 | const char *name) | 1556 | const char *name) |
1613 | { | 1557 | { |
1614 | struct ip6t_entry_target *t; | 1558 | struct ip6t_entry_target *t; |
@@ -1674,8 +1618,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1674 | /* Clear counters and comefrom */ | 1618 | /* Clear counters and comefrom */ |
1675 | memset(&e->counters, 0, sizeof(e->counters)); | 1619 | memset(&e->counters, 0, sizeof(e->counters)); |
1676 | e->comefrom = 0; | 1620 | e->comefrom = 0; |
1677 | |||
1678 | (*i)++; | ||
1679 | return 0; | 1621 | return 0; |
1680 | 1622 | ||
1681 | out: | 1623 | out: |
@@ -1725,7 +1667,7 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1725 | } | 1667 | } |
1726 | 1668 | ||
1727 | static int compat_check_entry(struct ip6t_entry *e, struct net *net, | 1669 | static int compat_check_entry(struct ip6t_entry *e, struct net *net, |
1728 | const char *name, unsigned int *i) | 1670 | const char *name) |
1729 | { | 1671 | { |
1730 | unsigned int j; | 1672 | unsigned int j; |
1731 | int ret; | 1673 | int ret; |
@@ -1744,8 +1686,6 @@ static int compat_check_entry(struct ip6t_entry *e, struct net *net, | |||
1744 | ret = check_target(e, net, name); | 1686 | ret = check_target(e, net, name); |
1745 | if (ret) | 1687 | if (ret) |
1746 | goto cleanup_matches; | 1688 | goto cleanup_matches; |
1747 | |||
1748 | (*i)++; | ||
1749 | return 0; | 1689 | return 0; |
1750 | 1690 | ||
1751 | cleanup_matches: | 1691 | cleanup_matches: |
@@ -1790,12 +1730,11 @@ translate_compat_table(struct net *net, | |||
1790 | xt_entry_foreach(iter0, entry0, total_size) { | 1730 | xt_entry_foreach(iter0, entry0, total_size) { |
1791 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, | 1731 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, |
1792 | entry0, entry0 + total_size, hook_entries, underflows, | 1732 | entry0, entry0 + total_size, hook_entries, underflows, |
1793 | &j, name); | 1733 | name); |
1794 | if (ret != 0) | 1734 | if (ret != 0) |
1795 | break; | 1735 | goto out_unlock; |
1736 | ++j; | ||
1796 | } | 1737 | } |
1797 | if (ret != 0) | ||
1798 | goto out_unlock; | ||
1799 | 1738 | ||
1800 | ret = -EINVAL; | 1739 | ret = -EINVAL; |
1801 | if (j != number) { | 1740 | if (j != number) { |
@@ -1851,9 +1790,10 @@ translate_compat_table(struct net *net, | |||
1851 | 1790 | ||
1852 | i = 0; | 1791 | i = 0; |
1853 | xt_entry_foreach(iter1, entry1, newinfo->size) { | 1792 | xt_entry_foreach(iter1, entry1, newinfo->size) { |
1854 | ret = compat_check_entry(iter1, net, name, &i); | 1793 | ret = compat_check_entry(iter1, net, name); |
1855 | if (ret != 0) | 1794 | if (ret != 0) |
1856 | break; | 1795 | break; |
1796 | ++i; | ||
1857 | } | 1797 | } |
1858 | if (ret) { | 1798 | if (ret) { |
1859 | /* | 1799 | /* |
@@ -1866,12 +1806,15 @@ translate_compat_table(struct net *net, | |||
1866 | xt_entry_foreach(iter0, entry0, newinfo->size) { | 1806 | xt_entry_foreach(iter0, entry0, newinfo->size) { |
1867 | if (skip-- > 0) | 1807 | if (skip-- > 0) |
1868 | continue; | 1808 | continue; |
1869 | if (compat_release_entry(iter0, &j) != 0) | 1809 | if (j-- == 0) |
1870 | break; | 1810 | break; |
1811 | compat_release_entry(iter0); | ||
1871 | } | 1812 | } |
1872 | xt_entry_foreach(iter1, entry1, newinfo->size) | 1813 | xt_entry_foreach(iter1, entry1, newinfo->size) { |
1873 | if (cleanup_entry(iter1, net, &i) != 0) | 1814 | if (i-- == 0) |
1874 | break; | 1815 | break; |
1816 | cleanup_entry(iter1, net); | ||
1817 | } | ||
1875 | xt_free_table_info(newinfo); | 1818 | xt_free_table_info(newinfo); |
1876 | return ret; | 1819 | return ret; |
1877 | } | 1820 | } |
@@ -1889,9 +1832,11 @@ translate_compat_table(struct net *net, | |||
1889 | free_newinfo: | 1832 | free_newinfo: |
1890 | xt_free_table_info(newinfo); | 1833 | xt_free_table_info(newinfo); |
1891 | out: | 1834 | out: |
1892 | xt_entry_foreach(iter0, entry0, total_size) | 1835 | xt_entry_foreach(iter0, entry0, total_size) { |
1893 | if (compat_release_entry(iter0, &j) != 0) | 1836 | if (j-- == 0) |
1894 | break; | 1837 | break; |
1838 | compat_release_entry(iter0); | ||
1839 | } | ||
1895 | return ret; | 1840 | return ret; |
1896 | out_unlock: | 1841 | out_unlock: |
1897 | xt_compat_flush_offsets(AF_INET6); | 1842 | xt_compat_flush_offsets(AF_INET6); |
@@ -1946,8 +1891,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len) | |||
1946 | 1891 | ||
1947 | free_newinfo_untrans: | 1892 | free_newinfo_untrans: |
1948 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) | 1893 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) |
1949 | if (cleanup_entry(iter, net, NULL) != 0) | 1894 | cleanup_entry(iter, net); |
1950 | break; | ||
1951 | free_newinfo: | 1895 | free_newinfo: |
1952 | xt_free_table_info(newinfo); | 1896 | xt_free_table_info(newinfo); |
1953 | return ret; | 1897 | return ret; |
@@ -2011,7 +1955,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, | |||
2011 | size = total_size; | 1955 | size = total_size; |
2012 | xt_entry_foreach(iter, loc_cpu_entry, total_size) { | 1956 | xt_entry_foreach(iter, loc_cpu_entry, total_size) { |
2013 | ret = compat_copy_entry_to_user(iter, &pos, | 1957 | ret = compat_copy_entry_to_user(iter, &pos, |
2014 | &size, counters, &i); | 1958 | &size, counters, i++); |
2015 | if (ret != 0) | 1959 | if (ret != 0) |
2016 | break; | 1960 | break; |
2017 | } | 1961 | } |
@@ -2221,8 +2165,7 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table) | |||
2221 | /* Decrease module usage counts and free resources */ | 2165 | /* Decrease module usage counts and free resources */ |
2222 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; | 2166 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
2223 | xt_entry_foreach(iter, loc_cpu_entry, private->size) | 2167 | xt_entry_foreach(iter, loc_cpu_entry, private->size) |
2224 | if (cleanup_entry(iter, net, NULL) != 0) | 2168 | cleanup_entry(iter, net); |
2225 | break; | ||
2226 | if (private->number > private->initial_entries) | 2169 | if (private->number > private->initial_entries) |
2227 | module_put(table_owner); | 2170 | module_put(table_owner); |
2228 | xt_free_table_info(private); | 2171 | xt_free_table_info(private); |