diff options
author | Jan Engelhardt <jengelh@medozas.de> | 2010-02-24 12:33:43 -0500 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-02-24 12:33:43 -0500 |
commit | 0559518b5b99c591226460c0bbf8e6a570c518a8 (patch) | |
tree | da3dd25683636f80c4861150816c1cb1a643348a /net/ipv4/netfilter/arp_tables.c | |
parent | 72b2b1dd77e8feb0b7c0b26dee58f2a1e2c9828c (diff) |
netfilter: xtables: optimize call flow around xt_entry_foreach
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv4/netfilter/arp_tables.c')
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 180 |
1 files changed, 58 insertions, 122 deletions
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index f7338869fc4..5fdedeb4621 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -512,8 +512,7 @@ static inline int check_target(struct arpt_entry *e, const char *name) | |||
512 | } | 512 | } |
513 | 513 | ||
514 | static inline int | 514 | static inline int |
515 | find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, | 515 | find_check_entry(struct arpt_entry *e, const char *name, unsigned int size) |
516 | unsigned int *i) | ||
517 | { | 516 | { |
518 | struct arpt_entry_target *t; | 517 | struct arpt_entry_target *t; |
519 | struct xt_target *target; | 518 | struct xt_target *target; |
@@ -538,8 +537,6 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size, | |||
538 | ret = check_target(e, name); | 537 | ret = check_target(e, name); |
539 | if (ret) | 538 | if (ret) |
540 | goto err; | 539 | goto err; |
541 | |||
542 | (*i)++; | ||
543 | return 0; | 540 | return 0; |
544 | err: | 541 | err: |
545 | module_put(t->u.kernel.target->me); | 542 | module_put(t->u.kernel.target->me); |
@@ -568,8 +565,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, | |||
568 | const unsigned char *limit, | 565 | const unsigned char *limit, |
569 | const unsigned int *hook_entries, | 566 | const unsigned int *hook_entries, |
570 | const unsigned int *underflows, | 567 | const unsigned int *underflows, |
571 | unsigned int valid_hooks, | 568 | unsigned int valid_hooks) |
572 | unsigned int *i) | ||
573 | { | 569 | { |
574 | unsigned int h; | 570 | unsigned int h; |
575 | 571 | ||
@@ -606,19 +602,14 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, | |||
606 | /* Clear counters and comefrom */ | 602 | /* Clear counters and comefrom */ |
607 | e->counters = ((struct xt_counters) { 0, 0 }); | 603 | e->counters = ((struct xt_counters) { 0, 0 }); |
608 | e->comefrom = 0; | 604 | e->comefrom = 0; |
609 | |||
610 | (*i)++; | ||
611 | return 0; | 605 | return 0; |
612 | } | 606 | } |
613 | 607 | ||
614 | static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) | 608 | static inline void cleanup_entry(struct arpt_entry *e) |
615 | { | 609 | { |
616 | struct xt_tgdtor_param par; | 610 | struct xt_tgdtor_param par; |
617 | struct arpt_entry_target *t; | 611 | struct arpt_entry_target *t; |
618 | 612 | ||
619 | if (i && (*i)-- == 0) | ||
620 | return 1; | ||
621 | |||
622 | t = arpt_get_target(e); | 613 | t = arpt_get_target(e); |
623 | par.target = t->u.kernel.target; | 614 | par.target = t->u.kernel.target; |
624 | par.targinfo = t->data; | 615 | par.targinfo = t->data; |
@@ -626,7 +617,6 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) | |||
626 | if (par.target->destroy != NULL) | 617 | if (par.target->destroy != NULL) |
627 | par.target->destroy(&par); | 618 | par.target->destroy(&par); |
628 | module_put(par.target->me); | 619 | module_put(par.target->me); |
629 | return 0; | ||
630 | } | 620 | } |
631 | 621 | ||
632 | /* Checks and translates the user-supplied table segment (held in | 622 | /* Checks and translates the user-supplied table segment (held in |
@@ -660,10 +650,10 @@ static int translate_table(const char *name, | |||
660 | /* Walk through entries, checking offsets. */ | 650 | /* Walk through entries, checking offsets. */ |
661 | xt_entry_foreach(iter, entry0, newinfo->size) { | 651 | xt_entry_foreach(iter, entry0, newinfo->size) { |
662 | ret = check_entry_size_and_hooks(iter, newinfo, entry0, | 652 | ret = check_entry_size_and_hooks(iter, newinfo, entry0, |
663 | entry0 + size, hook_entries, underflows, | 653 | entry0 + size, hook_entries, underflows, valid_hooks); |
664 | valid_hooks, &i); | ||
665 | if (ret != 0) | 654 | if (ret != 0) |
666 | break; | 655 | break; |
656 | ++i; | ||
667 | } | 657 | } |
668 | duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); | 658 | duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); |
669 | if (ret != 0) | 659 | if (ret != 0) |
@@ -700,15 +690,18 @@ static int translate_table(const char *name, | |||
700 | /* Finally, each sanity check must pass */ | 690 | /* Finally, each sanity check must pass */ |
701 | i = 0; | 691 | i = 0; |
702 | xt_entry_foreach(iter, entry0, newinfo->size) { | 692 | xt_entry_foreach(iter, entry0, newinfo->size) { |
703 | ret = find_check_entry(iter, name, size, &i); | 693 | ret = find_check_entry(iter, name, size); |
704 | if (ret != 0) | 694 | if (ret != 0) |
705 | break; | 695 | break; |
696 | ++i; | ||
706 | } | 697 | } |
707 | 698 | ||
708 | if (ret != 0) { | 699 | if (ret != 0) { |
709 | xt_entry_foreach(iter, entry0, newinfo->size) | 700 | xt_entry_foreach(iter, entry0, newinfo->size) { |
710 | if (cleanup_entry(iter, &i) != 0) | 701 | if (i-- == 0) |
711 | break; | 702 | break; |
703 | cleanup_entry(iter); | ||
704 | } | ||
712 | return ret; | 705 | return ret; |
713 | } | 706 | } |
714 | 707 | ||
@@ -721,27 +714,6 @@ static int translate_table(const char *name, | |||
721 | return ret; | 714 | return ret; |
722 | } | 715 | } |
723 | 716 | ||
724 | /* Gets counters. */ | ||
725 | static inline int add_entry_to_counter(const struct arpt_entry *e, | ||
726 | struct xt_counters total[], | ||
727 | unsigned int *i) | ||
728 | { | ||
729 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | ||
730 | |||
731 | (*i)++; | ||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static inline int set_entry_to_counter(const struct arpt_entry *e, | ||
736 | struct xt_counters total[], | ||
737 | unsigned int *i) | ||
738 | { | ||
739 | SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | ||
740 | |||
741 | (*i)++; | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static void get_counters(const struct xt_table_info *t, | 717 | static void get_counters(const struct xt_table_info *t, |
746 | struct xt_counters counters[]) | 718 | struct xt_counters counters[]) |
747 | { | 719 | { |
@@ -761,18 +733,22 @@ static void get_counters(const struct xt_table_info *t, | |||
761 | curcpu = smp_processor_id(); | 733 | curcpu = smp_processor_id(); |
762 | 734 | ||
763 | i = 0; | 735 | i = 0; |
764 | xt_entry_foreach(iter, t->entries[curcpu], t->size) | 736 | xt_entry_foreach(iter, t->entries[curcpu], t->size) { |
765 | if (set_entry_to_counter(iter, counters, &i) != 0) | 737 | SET_COUNTER(counters[i], iter->counters.bcnt, |
766 | break; | 738 | iter->counters.pcnt); |
739 | ++i; | ||
740 | } | ||
767 | 741 | ||
768 | for_each_possible_cpu(cpu) { | 742 | for_each_possible_cpu(cpu) { |
769 | if (cpu == curcpu) | 743 | if (cpu == curcpu) |
770 | continue; | 744 | continue; |
771 | i = 0; | 745 | i = 0; |
772 | xt_info_wrlock(cpu); | 746 | xt_info_wrlock(cpu); |
773 | xt_entry_foreach(iter, t->entries[cpu], t->size) | 747 | xt_entry_foreach(iter, t->entries[cpu], t->size) { |
774 | if (add_entry_to_counter(iter, counters, &i) != 0) | 748 | ADD_COUNTER(counters[i], iter->counters.bcnt, |
775 | break; | 749 | iter->counters.pcnt); |
750 | ++i; | ||
751 | } | ||
776 | xt_info_wrunlock(cpu); | 752 | xt_info_wrunlock(cpu); |
777 | } | 753 | } |
778 | local_bh_enable(); | 754 | local_bh_enable(); |
@@ -904,7 +880,7 @@ static int compat_table_info(const struct xt_table_info *info, | |||
904 | { | 880 | { |
905 | struct arpt_entry *iter; | 881 | struct arpt_entry *iter; |
906 | void *loc_cpu_entry; | 882 | void *loc_cpu_entry; |
907 | int ret = 0; | 883 | int ret; |
908 | 884 | ||
909 | if (!newinfo || !info) | 885 | if (!newinfo || !info) |
910 | return -EINVAL; | 886 | return -EINVAL; |
@@ -916,9 +892,9 @@ static int compat_table_info(const struct xt_table_info *info, | |||
916 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { | 892 | xt_entry_foreach(iter, loc_cpu_entry, info->size) { |
917 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); | 893 | ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo); |
918 | if (ret != 0) | 894 | if (ret != 0) |
919 | break; | 895 | return ret; |
920 | } | 896 | } |
921 | return ret; | 897 | return 0; |
922 | } | 898 | } |
923 | #endif | 899 | #endif |
924 | 900 | ||
@@ -1078,8 +1054,7 @@ static int __do_replace(struct net *net, const char *name, | |||
1078 | /* Decrease module usage counts and free resource */ | 1054 | /* Decrease module usage counts and free resource */ |
1079 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1055 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1080 | xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) | 1056 | xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size) |
1081 | if (cleanup_entry(iter, NULL) != 0) | 1057 | cleanup_entry(iter); |
1082 | break; | ||
1083 | 1058 | ||
1084 | xt_free_table_info(oldinfo); | 1059 | xt_free_table_info(oldinfo); |
1085 | if (copy_to_user(counters_ptr, counters, | 1060 | if (copy_to_user(counters_ptr, counters, |
@@ -1142,26 +1117,12 @@ static int do_replace(struct net *net, const void __user *user, | |||
1142 | 1117 | ||
1143 | free_newinfo_untrans: | 1118 | free_newinfo_untrans: |
1144 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) | 1119 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) |
1145 | if (cleanup_entry(iter, NULL) != 0) | 1120 | cleanup_entry(iter); |
1146 | break; | ||
1147 | free_newinfo: | 1121 | free_newinfo: |
1148 | xt_free_table_info(newinfo); | 1122 | xt_free_table_info(newinfo); |
1149 | return ret; | 1123 | return ret; |
1150 | } | 1124 | } |
1151 | 1125 | ||
1152 | /* We're lazy, and add to the first CPU; overflow works its fey magic | ||
1153 | * and everything is OK. */ | ||
1154 | static int | ||
1155 | add_counter_to_entry(struct arpt_entry *e, | ||
1156 | const struct xt_counters addme[], | ||
1157 | unsigned int *i) | ||
1158 | { | ||
1159 | ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt); | ||
1160 | |||
1161 | (*i)++; | ||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | static int do_add_counters(struct net *net, const void __user *user, | 1126 | static int do_add_counters(struct net *net, const void __user *user, |
1166 | unsigned int len, int compat) | 1127 | unsigned int len, int compat) |
1167 | { | 1128 | { |
@@ -1234,9 +1195,10 @@ static int do_add_counters(struct net *net, const void __user *user, | |||
1234 | curcpu = smp_processor_id(); | 1195 | curcpu = smp_processor_id(); |
1235 | loc_cpu_entry = private->entries[curcpu]; | 1196 | loc_cpu_entry = private->entries[curcpu]; |
1236 | xt_info_wrlock(curcpu); | 1197 | xt_info_wrlock(curcpu); |
1237 | xt_entry_foreach(iter, loc_cpu_entry, private->size) | 1198 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { |
1238 | if (add_counter_to_entry(iter, paddc, &i) != 0) | 1199 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); |
1239 | break; | 1200 | ++i; |
1201 | } | ||
1240 | xt_info_wrunlock(curcpu); | 1202 | xt_info_wrunlock(curcpu); |
1241 | unlock_up_free: | 1203 | unlock_up_free: |
1242 | local_bh_enable(); | 1204 | local_bh_enable(); |
@@ -1249,17 +1211,12 @@ static int do_add_counters(struct net *net, const void __user *user, | |||
1249 | } | 1211 | } |
1250 | 1212 | ||
1251 | #ifdef CONFIG_COMPAT | 1213 | #ifdef CONFIG_COMPAT |
1252 | static inline int | 1214 | static inline void compat_release_entry(struct compat_arpt_entry *e) |
1253 | compat_release_entry(struct compat_arpt_entry *e, unsigned int *i) | ||
1254 | { | 1215 | { |
1255 | struct arpt_entry_target *t; | 1216 | struct arpt_entry_target *t; |
1256 | 1217 | ||
1257 | if (i && (*i)-- == 0) | ||
1258 | return 1; | ||
1259 | |||
1260 | t = compat_arpt_get_target(e); | 1218 | t = compat_arpt_get_target(e); |
1261 | module_put(t->u.kernel.target->me); | 1219 | module_put(t->u.kernel.target->me); |
1262 | return 0; | ||
1263 | } | 1220 | } |
1264 | 1221 | ||
1265 | static inline int | 1222 | static inline int |
@@ -1270,7 +1227,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, | |||
1270 | const unsigned char *limit, | 1227 | const unsigned char *limit, |
1271 | const unsigned int *hook_entries, | 1228 | const unsigned int *hook_entries, |
1272 | const unsigned int *underflows, | 1229 | const unsigned int *underflows, |
1273 | unsigned int *i, | ||
1274 | const char *name) | 1230 | const char *name) |
1275 | { | 1231 | { |
1276 | struct arpt_entry_target *t; | 1232 | struct arpt_entry_target *t; |
@@ -1330,8 +1286,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, | |||
1330 | /* Clear counters and comefrom */ | 1286 | /* Clear counters and comefrom */ |
1331 | memset(&e->counters, 0, sizeof(e->counters)); | 1287 | memset(&e->counters, 0, sizeof(e->counters)); |
1332 | e->comefrom = 0; | 1288 | e->comefrom = 0; |
1333 | |||
1334 | (*i)++; | ||
1335 | return 0; | 1289 | return 0; |
1336 | 1290 | ||
1337 | release_target: | 1291 | release_target: |
@@ -1375,19 +1329,6 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr, | |||
1375 | return ret; | 1329 | return ret; |
1376 | } | 1330 | } |
1377 | 1331 | ||
1378 | static inline int compat_check_entry(struct arpt_entry *e, const char *name, | ||
1379 | unsigned int *i) | ||
1380 | { | ||
1381 | int ret; | ||
1382 | |||
1383 | ret = check_target(e, name); | ||
1384 | if (ret) | ||
1385 | return ret; | ||
1386 | |||
1387 | (*i)++; | ||
1388 | return 0; | ||
1389 | } | ||
1390 | |||
1391 | static int translate_compat_table(const char *name, | 1332 | static int translate_compat_table(const char *name, |
1392 | unsigned int valid_hooks, | 1333 | unsigned int valid_hooks, |
1393 | struct xt_table_info **pinfo, | 1334 | struct xt_table_info **pinfo, |
@@ -1423,12 +1364,11 @@ static int translate_compat_table(const char *name, | |||
1423 | xt_entry_foreach(iter0, entry0, total_size) { | 1364 | xt_entry_foreach(iter0, entry0, total_size) { |
1424 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, | 1365 | ret = check_compat_entry_size_and_hooks(iter0, info, &size, |
1425 | entry0, entry0 + total_size, hook_entries, underflows, | 1366 | entry0, entry0 + total_size, hook_entries, underflows, |
1426 | &j, name); | 1367 | name); |
1427 | if (ret != 0) | 1368 | if (ret != 0) |
1428 | break; | 1369 | goto out_unlock; |
1370 | ++j; | ||
1429 | } | 1371 | } |
1430 | if (ret != 0) | ||
1431 | goto out_unlock; | ||
1432 | 1372 | ||
1433 | ret = -EINVAL; | 1373 | ret = -EINVAL; |
1434 | if (j != number) { | 1374 | if (j != number) { |
@@ -1484,9 +1424,10 @@ static int translate_compat_table(const char *name, | |||
1484 | 1424 | ||
1485 | i = 0; | 1425 | i = 0; |
1486 | xt_entry_foreach(iter1, entry1, newinfo->size) { | 1426 | xt_entry_foreach(iter1, entry1, newinfo->size) { |
1487 | ret = compat_check_entry(iter1, name, &i); | 1427 | ret = check_target(iter1, name); |
1488 | if (ret != 0) | 1428 | if (ret != 0) |
1489 | break; | 1429 | break; |
1430 | ++i; | ||
1490 | } | 1431 | } |
1491 | if (ret) { | 1432 | if (ret) { |
1492 | /* | 1433 | /* |
@@ -1499,12 +1440,15 @@ static int translate_compat_table(const char *name, | |||
1499 | xt_entry_foreach(iter0, entry0, newinfo->size) { | 1440 | xt_entry_foreach(iter0, entry0, newinfo->size) { |
1500 | if (skip-- > 0) | 1441 | if (skip-- > 0) |
1501 | continue; | 1442 | continue; |
1502 | if (compat_release_entry(iter0, &j) != 0) | 1443 | if (j-- == 0) |
1503 | break; | 1444 | break; |
1445 | compat_release_entry(iter0); | ||
1504 | } | 1446 | } |
1505 | xt_entry_foreach(iter1, entry1, newinfo->size) | 1447 | xt_entry_foreach(iter1, entry1, newinfo->size) { |
1506 | if (cleanup_entry(iter1, &i) != 0) | 1448 | if (i-- == 0) |
1507 | break; | 1449 | break; |
1450 | cleanup_entry(iter1); | ||
1451 | } | ||
1508 | xt_free_table_info(newinfo); | 1452 | xt_free_table_info(newinfo); |
1509 | return ret; | 1453 | return ret; |
1510 | } | 1454 | } |
@@ -1522,9 +1466,11 @@ static int translate_compat_table(const char *name, | |||
1522 | free_newinfo: | 1466 | free_newinfo: |
1523 | xt_free_table_info(newinfo); | 1467 | xt_free_table_info(newinfo); |
1524 | out: | 1468 | out: |
1525 | xt_entry_foreach(iter0, entry0, total_size) | 1469 | xt_entry_foreach(iter0, entry0, total_size) { |
1526 | if (compat_release_entry(iter0, &j) != 0) | 1470 | if (j-- == 0) |
1527 | break; | 1471 | break; |
1472 | compat_release_entry(iter0); | ||
1473 | } | ||
1528 | return ret; | 1474 | return ret; |
1529 | out_unlock: | 1475 | out_unlock: |
1530 | xt_compat_flush_offsets(NFPROTO_ARP); | 1476 | xt_compat_flush_offsets(NFPROTO_ARP); |
@@ -1590,8 +1536,7 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
1590 | 1536 | ||
1591 | free_newinfo_untrans: | 1537 | free_newinfo_untrans: |
1592 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) | 1538 | xt_entry_foreach(iter, loc_cpu_entry, newinfo->size) |
1593 | if (cleanup_entry(iter, NULL) != 0) | 1539 | cleanup_entry(iter); |
1594 | break; | ||
1595 | free_newinfo: | 1540 | free_newinfo: |
1596 | xt_free_table_info(newinfo); | 1541 | xt_free_table_info(newinfo); |
1597 | return ret; | 1542 | return ret; |
@@ -1625,7 +1570,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, | |||
1625 | static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, | 1570 | static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, |
1626 | compat_uint_t *size, | 1571 | compat_uint_t *size, |
1627 | struct xt_counters *counters, | 1572 | struct xt_counters *counters, |
1628 | unsigned int *i) | 1573 | unsigned int i) |
1629 | { | 1574 | { |
1630 | struct arpt_entry_target *t; | 1575 | struct arpt_entry_target *t; |
1631 | struct compat_arpt_entry __user *ce; | 1576 | struct compat_arpt_entry __user *ce; |
@@ -1633,14 +1578,12 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, | |||
1633 | compat_uint_t origsize; | 1578 | compat_uint_t origsize; |
1634 | int ret; | 1579 | int ret; |
1635 | 1580 | ||
1636 | ret = -EFAULT; | ||
1637 | origsize = *size; | 1581 | origsize = *size; |
1638 | ce = (struct compat_arpt_entry __user *)*dstptr; | 1582 | ce = (struct compat_arpt_entry __user *)*dstptr; |
1639 | if (copy_to_user(ce, e, sizeof(struct arpt_entry))) | 1583 | if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 || |
1640 | goto out; | 1584 | copy_to_user(&ce->counters, &counters[i], |
1641 | 1585 | sizeof(counters[i])) != 0) | |
1642 | if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i]))) | 1586 | return -EFAULT; |
1643 | goto out; | ||
1644 | 1587 | ||
1645 | *dstptr += sizeof(struct compat_arpt_entry); | 1588 | *dstptr += sizeof(struct compat_arpt_entry); |
1646 | *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); | 1589 | *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); |
@@ -1650,18 +1593,12 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr, | |||
1650 | t = arpt_get_target(e); | 1593 | t = arpt_get_target(e); |
1651 | ret = xt_compat_target_to_user(t, dstptr, size); | 1594 | ret = xt_compat_target_to_user(t, dstptr, size); |
1652 | if (ret) | 1595 | if (ret) |
1653 | goto out; | 1596 | return ret; |
1654 | ret = -EFAULT; | ||
1655 | next_offset = e->next_offset - (origsize - *size); | 1597 | next_offset = e->next_offset - (origsize - *size); |
1656 | if (put_user(target_offset, &ce->target_offset)) | 1598 | if (put_user(target_offset, &ce->target_offset) != 0 || |
1657 | goto out; | 1599 | put_user(next_offset, &ce->next_offset) != 0) |
1658 | if (put_user(next_offset, &ce->next_offset)) | 1600 | return -EFAULT; |
1659 | goto out; | ||
1660 | |||
1661 | (*i)++; | ||
1662 | return 0; | 1601 | return 0; |
1663 | out: | ||
1664 | return ret; | ||
1665 | } | 1602 | } |
1666 | 1603 | ||
1667 | static int compat_copy_entries_to_user(unsigned int total_size, | 1604 | static int compat_copy_entries_to_user(unsigned int total_size, |
@@ -1687,7 +1624,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, | |||
1687 | size = total_size; | 1624 | size = total_size; |
1688 | xt_entry_foreach(iter, loc_cpu_entry, total_size) { | 1625 | xt_entry_foreach(iter, loc_cpu_entry, total_size) { |
1689 | ret = compat_copy_entry_to_user(iter, &pos, | 1626 | ret = compat_copy_entry_to_user(iter, &pos, |
1690 | &size, counters, &i); | 1627 | &size, counters, i++); |
1691 | if (ret != 0) | 1628 | if (ret != 0) |
1692 | break; | 1629 | break; |
1693 | } | 1630 | } |
@@ -1893,8 +1830,7 @@ void arpt_unregister_table(struct xt_table *table) | |||
1893 | /* Decrease module usage counts and free resources */ | 1830 | /* Decrease module usage counts and free resources */ |
1894 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; | 1831 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1895 | xt_entry_foreach(iter, loc_cpu_entry, private->size) | 1832 | xt_entry_foreach(iter, loc_cpu_entry, private->size) |
1896 | if (cleanup_entry(iter, NULL) != 0) | 1833 | cleanup_entry(iter); |
1897 | break; | ||
1898 | if (private->number > private->initial_entries) | 1834 | if (private->number > private->initial_entries) |
1899 | module_put(table_owner); | 1835 | module_put(table_owner); |
1900 | xt_free_table_info(private); | 1836 | xt_free_table_info(private); |