aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/x_tables.h9
-rw-r--r--include/linux/netfilter_arp/arp_tables.h10
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h11
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h10
-rw-r--r--net/ipv4/netfilter/arp_tables.c151
-rw-r--r--net/ipv4/netfilter/ip_tables.c160
-rw-r--r--net/ipv6/netfilter/ip6_tables.c160
7 files changed, 321 insertions, 190 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index a18119fb88f0..9df3f5a8f9f7 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -139,6 +139,7 @@ struct xt_counters_info {
139 __ret; \ 139 __ret; \
140}) 140})
141 141
142#ifndef __KERNEL__
142/* fn returns 0 to continue iteration */ 143/* fn returns 0 to continue iteration */
143#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \ 144#define XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \
144({ \ 145({ \
@@ -163,6 +164,14 @@ struct xt_counters_info {
163#define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \ 164#define XT_ENTRY_ITERATE(type, entries, size, fn, args...) \
164 XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args) 165 XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args)
165 166
167#endif /* !__KERNEL__ */
168
169/* pos is normally a struct ipt_entry/ip6t_entry/etc. */
170#define xt_entry_foreach(pos, ehead, esize) \
171 for ((pos) = (typeof(pos))(ehead); \
172 (pos) < (typeof(pos))((char *)(ehead) + (esize)); \
173 (pos) = (typeof(pos))((char *)(pos) + (pos)->next_offset))
174
166#ifdef __KERNEL__ 175#ifdef __KERNEL__
167 176
168#include <linux/netdevice.h> 177#include <linux/netdevice.h>
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 0b33980611b2..e9948c0560f6 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -211,9 +211,11 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e
211 return (void *)e + e->target_offset; 211 return (void *)e + e->target_offset;
212} 212}
213 213
214#ifndef __KERNEL__
214/* fn returns 0 to continue iteration */ 215/* fn returns 0 to continue iteration */
215#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \ 216#define ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
216 XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args) 217 XT_ENTRY_ITERATE(struct arpt_entry, entries, size, fn, ## args)
218#endif
217 219
218/* 220/*
219 * Main firewall chains definitions and global var's definitions. 221 * Main firewall chains definitions and global var's definitions.
@@ -291,14 +293,6 @@ compat_arpt_get_target(struct compat_arpt_entry *e)
291 293
292#define COMPAT_ARPT_ALIGN(s) COMPAT_XT_ALIGN(s) 294#define COMPAT_ARPT_ALIGN(s) COMPAT_XT_ALIGN(s)
293 295
294/* fn returns 0 to continue iteration */
295#define COMPAT_ARPT_ENTRY_ITERATE(entries, size, fn, args...) \
296 XT_ENTRY_ITERATE(struct compat_arpt_entry, entries, size, fn, ## args)
297
298#define COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
299 XT_ENTRY_ITERATE_CONTINUE(struct compat_arpt_entry, entries, size, n, \
300 fn, ## args)
301
302#endif /* CONFIG_COMPAT */ 296#endif /* CONFIG_COMPAT */
303#endif /*__KERNEL__*/ 297#endif /*__KERNEL__*/
304#endif /* _ARPTABLES_H */ 298#endif /* _ARPTABLES_H */
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 364973b42133..5b20ae724b41 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -227,9 +227,11 @@ ipt_get_target(struct ipt_entry *e)
227#define IPT_MATCH_ITERATE(e, fn, args...) \ 227#define IPT_MATCH_ITERATE(e, fn, args...) \
228 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args) 228 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)
229 229
230#ifndef __KERNEL__
230/* fn returns 0 to continue iteration */ 231/* fn returns 0 to continue iteration */
231#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ 232#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \
232 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) 233 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
234#endif
233 235
234/* 236/*
235 * Main firewall chains definitions and global var's definitions. 237 * Main firewall chains definitions and global var's definitions.
@@ -317,15 +319,6 @@ compat_ipt_get_target(struct compat_ipt_entry *e)
317#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \ 319#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \
318 XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args) 320 XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args)
319 321
320/* fn returns 0 to continue iteration */
321#define COMPAT_IPT_ENTRY_ITERATE(entries, size, fn, args...) \
322 XT_ENTRY_ITERATE(struct compat_ipt_entry, entries, size, fn, ## args)
323
324/* fn returns 0 to continue iteration */
325#define COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
326 XT_ENTRY_ITERATE_CONTINUE(struct compat_ipt_entry, entries, size, n, \
327 fn, ## args)
328
329#endif /* CONFIG_COMPAT */ 322#endif /* CONFIG_COMPAT */
330#endif /*__KERNEL__*/ 323#endif /*__KERNEL__*/
331#endif /* _IPTABLES_H */ 324#endif /* _IPTABLES_H */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 8031eb486a10..8bb3f5ba5ff2 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -284,9 +284,11 @@ ip6t_get_target(struct ip6t_entry *e)
284#define IP6T_MATCH_ITERATE(e, fn, args...) \ 284#define IP6T_MATCH_ITERATE(e, fn, args...) \
285 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args) 285 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)
286 286
287#ifndef __KERNEL__
287/* fn returns 0 to continue iteration */ 288/* fn returns 0 to continue iteration */
288#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \ 289#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
289 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args) 290 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)
291#endif
290 292
291/* 293/*
292 * Main firewall chains definitions and global var's definitions. 294 * Main firewall chains definitions and global var's definitions.
@@ -345,14 +347,6 @@ compat_ip6t_get_target(struct compat_ip6t_entry *e)
345#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \ 347#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \
346 XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args) 348 XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args)
347 349
348/* fn returns 0 to continue iteration */
349#define COMPAT_IP6T_ENTRY_ITERATE(entries, size, fn, args...) \
350 XT_ENTRY_ITERATE(struct compat_ip6t_entry, entries, size, fn, ## args)
351
352#define COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \
353 XT_ENTRY_ITERATE_CONTINUE(struct compat_ip6t_entry, entries, size, n, \
354 fn, ## args)
355
356#endif /* CONFIG_COMPAT */ 350#endif /* CONFIG_COMPAT */
357#endif /*__KERNEL__*/ 351#endif /*__KERNEL__*/
358#endif /* _IP6_TABLES_H */ 352#endif /* _IP6_TABLES_H */
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 4db5c1ece0f9..f7338869fc4c 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -641,8 +641,9 @@ static int translate_table(const char *name,
641 const unsigned int *hook_entries, 641 const unsigned int *hook_entries,
642 const unsigned int *underflows) 642 const unsigned int *underflows)
643{ 643{
644 struct arpt_entry *iter;
644 unsigned int i; 645 unsigned int i;
645 int ret; 646 int ret = 0;
646 647
647 newinfo->size = size; 648 newinfo->size = size;
648 newinfo->number = number; 649 newinfo->number = number;
@@ -657,12 +658,13 @@ static int translate_table(const char *name,
657 i = 0; 658 i = 0;
658 659
659 /* Walk through entries, checking offsets. */ 660 /* Walk through entries, checking offsets. */
660 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 661 xt_entry_foreach(iter, entry0, newinfo->size) {
661 check_entry_size_and_hooks, 662 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
662 newinfo, 663 entry0 + size, hook_entries, underflows,
663 entry0, 664 valid_hooks, &i);
664 entry0 + size, 665 if (ret != 0)
665 hook_entries, underflows, valid_hooks, &i); 666 break;
667 }
666 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret); 668 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);
667 if (ret != 0) 669 if (ret != 0)
668 return ret; 670 return ret;
@@ -697,12 +699,16 @@ static int translate_table(const char *name,
697 699
698 /* Finally, each sanity check must pass */ 700 /* Finally, each sanity check must pass */
699 i = 0; 701 i = 0;
700 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 702 xt_entry_foreach(iter, entry0, newinfo->size) {
701 find_check_entry, name, size, &i); 703 ret = find_check_entry(iter, name, size, &i);
704 if (ret != 0)
705 break;
706 }
702 707
703 if (ret != 0) { 708 if (ret != 0) {
704 ARPT_ENTRY_ITERATE(entry0, newinfo->size, 709 xt_entry_foreach(iter, entry0, newinfo->size)
705 cleanup_entry, &i); 710 if (cleanup_entry(iter, &i) != 0)
711 break;
706 return ret; 712 return ret;
707 } 713 }
708 714
@@ -739,6 +745,7 @@ static inline int set_entry_to_counter(const struct arpt_entry *e,
739static void get_counters(const struct xt_table_info *t, 745static void get_counters(const struct xt_table_info *t,
740 struct xt_counters counters[]) 746 struct xt_counters counters[])
741{ 747{
748 struct arpt_entry *iter;
742 unsigned int cpu; 749 unsigned int cpu;
743 unsigned int i; 750 unsigned int i;
744 unsigned int curcpu; 751 unsigned int curcpu;
@@ -754,22 +761,18 @@ static void get_counters(const struct xt_table_info *t,
754 curcpu = smp_processor_id(); 761 curcpu = smp_processor_id();
755 762
756 i = 0; 763 i = 0;
757 ARPT_ENTRY_ITERATE(t->entries[curcpu], 764 xt_entry_foreach(iter, t->entries[curcpu], t->size)
758 t->size, 765 if (set_entry_to_counter(iter, counters, &i) != 0)
759 set_entry_to_counter, 766 break;
760 counters,
761 &i);
762 767
763 for_each_possible_cpu(cpu) { 768 for_each_possible_cpu(cpu) {
764 if (cpu == curcpu) 769 if (cpu == curcpu)
765 continue; 770 continue;
766 i = 0; 771 i = 0;
767 xt_info_wrlock(cpu); 772 xt_info_wrlock(cpu);
768 ARPT_ENTRY_ITERATE(t->entries[cpu], 773 xt_entry_foreach(iter, t->entries[cpu], t->size)
769 t->size, 774 if (add_entry_to_counter(iter, counters, &i) != 0)
770 add_entry_to_counter, 775 break;
771 counters,
772 &i);
773 xt_info_wrunlock(cpu); 776 xt_info_wrunlock(cpu);
774 } 777 }
775 local_bh_enable(); 778 local_bh_enable();
@@ -899,7 +902,9 @@ static int compat_calc_entry(const struct arpt_entry *e,
899static int compat_table_info(const struct xt_table_info *info, 902static int compat_table_info(const struct xt_table_info *info,
900 struct xt_table_info *newinfo) 903 struct xt_table_info *newinfo)
901{ 904{
905 struct arpt_entry *iter;
902 void *loc_cpu_entry; 906 void *loc_cpu_entry;
907 int ret = 0;
903 908
904 if (!newinfo || !info) 909 if (!newinfo || !info)
905 return -EINVAL; 910 return -EINVAL;
@@ -908,9 +913,12 @@ static int compat_table_info(const struct xt_table_info *info,
908 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 913 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
909 newinfo->initial_entries = 0; 914 newinfo->initial_entries = 0;
910 loc_cpu_entry = info->entries[raw_smp_processor_id()]; 915 loc_cpu_entry = info->entries[raw_smp_processor_id()];
911 return ARPT_ENTRY_ITERATE(loc_cpu_entry, info->size, 916 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
912 compat_calc_entry, info, loc_cpu_entry, 917 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
913 newinfo); 918 if (ret != 0)
919 break;
920 }
921 return ret;
914} 922}
915#endif 923#endif
916 924
@@ -1025,6 +1033,7 @@ static int __do_replace(struct net *net, const char *name,
1025 struct xt_table_info *oldinfo; 1033 struct xt_table_info *oldinfo;
1026 struct xt_counters *counters; 1034 struct xt_counters *counters;
1027 void *loc_cpu_old_entry; 1035 void *loc_cpu_old_entry;
1036 struct arpt_entry *iter;
1028 1037
1029 ret = 0; 1038 ret = 0;
1030 counters = vmalloc_node(num_counters * sizeof(struct xt_counters), 1039 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
@@ -1068,8 +1077,9 @@ static int __do_replace(struct net *net, const char *name,
1068 1077
1069 /* Decrease module usage counts and free resource */ 1078 /* Decrease module usage counts and free resource */
1070 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1079 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1071 ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1080 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1072 NULL); 1081 if (cleanup_entry(iter, NULL) != 0)
1082 break;
1073 1083
1074 xt_free_table_info(oldinfo); 1084 xt_free_table_info(oldinfo);
1075 if (copy_to_user(counters_ptr, counters, 1085 if (copy_to_user(counters_ptr, counters,
@@ -1095,6 +1105,7 @@ static int do_replace(struct net *net, const void __user *user,
1095 struct arpt_replace tmp; 1105 struct arpt_replace tmp;
1096 struct xt_table_info *newinfo; 1106 struct xt_table_info *newinfo;
1097 void *loc_cpu_entry; 1107 void *loc_cpu_entry;
1108 struct arpt_entry *iter;
1098 1109
1099 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1110 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1100 return -EFAULT; 1111 return -EFAULT;
@@ -1130,7 +1141,9 @@ static int do_replace(struct net *net, const void __user *user,
1130 return 0; 1141 return 0;
1131 1142
1132 free_newinfo_untrans: 1143 free_newinfo_untrans:
1133 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1144 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1145 if (cleanup_entry(iter, NULL) != 0)
1146 break;
1134 free_newinfo: 1147 free_newinfo:
1135 xt_free_table_info(newinfo); 1148 xt_free_table_info(newinfo);
1136 return ret; 1149 return ret;
@@ -1163,6 +1176,7 @@ static int do_add_counters(struct net *net, const void __user *user,
1163 const struct xt_table_info *private; 1176 const struct xt_table_info *private;
1164 int ret = 0; 1177 int ret = 0;
1165 void *loc_cpu_entry; 1178 void *loc_cpu_entry;
1179 struct arpt_entry *iter;
1166#ifdef CONFIG_COMPAT 1180#ifdef CONFIG_COMPAT
1167 struct compat_xt_counters_info compat_tmp; 1181 struct compat_xt_counters_info compat_tmp;
1168 1182
@@ -1220,11 +1234,9 @@ static int do_add_counters(struct net *net, const void __user *user,
1220 curcpu = smp_processor_id(); 1234 curcpu = smp_processor_id();
1221 loc_cpu_entry = private->entries[curcpu]; 1235 loc_cpu_entry = private->entries[curcpu];
1222 xt_info_wrlock(curcpu); 1236 xt_info_wrlock(curcpu);
1223 ARPT_ENTRY_ITERATE(loc_cpu_entry, 1237 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1224 private->size, 1238 if (add_counter_to_entry(iter, paddc, &i) != 0)
1225 add_counter_to_entry, 1239 break;
1226 paddc,
1227 &i);
1228 xt_info_wrunlock(curcpu); 1240 xt_info_wrunlock(curcpu);
1229 unlock_up_free: 1241 unlock_up_free:
1230 local_bh_enable(); 1242 local_bh_enable();
@@ -1388,8 +1400,10 @@ static int translate_compat_table(const char *name,
1388 unsigned int i, j; 1400 unsigned int i, j;
1389 struct xt_table_info *newinfo, *info; 1401 struct xt_table_info *newinfo, *info;
1390 void *pos, *entry0, *entry1; 1402 void *pos, *entry0, *entry1;
1403 struct compat_arpt_entry *iter0;
1404 struct arpt_entry *iter1;
1391 unsigned int size; 1405 unsigned int size;
1392 int ret; 1406 int ret = 0;
1393 1407
1394 info = *pinfo; 1408 info = *pinfo;
1395 entry0 = *pentry0; 1409 entry0 = *pentry0;
@@ -1406,11 +1420,13 @@ static int translate_compat_table(const char *name,
1406 j = 0; 1420 j = 0;
1407 xt_compat_lock(NFPROTO_ARP); 1421 xt_compat_lock(NFPROTO_ARP);
1408 /* Walk through entries, checking offsets. */ 1422 /* Walk through entries, checking offsets. */
1409 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, 1423 xt_entry_foreach(iter0, entry0, total_size) {
1410 check_compat_entry_size_and_hooks, 1424 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1411 info, &size, entry0, 1425 entry0, entry0 + total_size, hook_entries, underflows,
1412 entry0 + total_size, 1426 &j, name);
1413 hook_entries, underflows, &j, name); 1427 if (ret != 0)
1428 break;
1429 }
1414 if (ret != 0) 1430 if (ret != 0)
1415 goto out_unlock; 1431 goto out_unlock;
1416 1432
@@ -1451,9 +1467,12 @@ static int translate_compat_table(const char *name,
1451 entry1 = newinfo->entries[raw_smp_processor_id()]; 1467 entry1 = newinfo->entries[raw_smp_processor_id()];
1452 pos = entry1; 1468 pos = entry1;
1453 size = total_size; 1469 size = total_size;
1454 ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, 1470 xt_entry_foreach(iter0, entry0, total_size) {
1455 compat_copy_entry_from_user, 1471 ret = compat_copy_entry_from_user(iter0, &pos,
1456 &pos, &size, name, newinfo, entry1); 1472 &size, name, newinfo, entry1);
1473 if (ret != 0)
1474 break;
1475 }
1457 xt_compat_flush_offsets(NFPROTO_ARP); 1476 xt_compat_flush_offsets(NFPROTO_ARP);
1458 xt_compat_unlock(NFPROTO_ARP); 1477 xt_compat_unlock(NFPROTO_ARP);
1459 if (ret) 1478 if (ret)
@@ -1464,13 +1483,28 @@ static int translate_compat_table(const char *name,
1464 goto free_newinfo; 1483 goto free_newinfo;
1465 1484
1466 i = 0; 1485 i = 0;
1467 ret = ARPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1486 xt_entry_foreach(iter1, entry1, newinfo->size) {
1468 name, &i); 1487 ret = compat_check_entry(iter1, name, &i);
1488 if (ret != 0)
1489 break;
1490 }
1469 if (ret) { 1491 if (ret) {
1492 /*
1493 * The first i matches need cleanup_entry (calls ->destroy)
1494 * because they had called ->check already. The other j-i
1495 * entries need only release.
1496 */
1497 int skip = i;
1470 j -= i; 1498 j -= i;
1471 COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1499 xt_entry_foreach(iter0, entry0, newinfo->size) {
1472 compat_release_entry, &j); 1500 if (skip-- > 0)
1473 ARPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); 1501 continue;
1502 if (compat_release_entry(iter0, &j) != 0)
1503 break;
1504 }
1505 xt_entry_foreach(iter1, entry1, newinfo->size)
1506 if (cleanup_entry(iter1, &i) != 0)
1507 break;
1474 xt_free_table_info(newinfo); 1508 xt_free_table_info(newinfo);
1475 return ret; 1509 return ret;
1476 } 1510 }
@@ -1488,7 +1522,9 @@ static int translate_compat_table(const char *name,
1488free_newinfo: 1522free_newinfo:
1489 xt_free_table_info(newinfo); 1523 xt_free_table_info(newinfo);
1490out: 1524out:
1491 COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1525 xt_entry_foreach(iter0, entry0, total_size)
1526 if (compat_release_entry(iter0, &j) != 0)
1527 break;
1492 return ret; 1528 return ret;
1493out_unlock: 1529out_unlock:
1494 xt_compat_flush_offsets(NFPROTO_ARP); 1530 xt_compat_flush_offsets(NFPROTO_ARP);
@@ -1515,6 +1551,7 @@ static int compat_do_replace(struct net *net, void __user *user,
1515 struct compat_arpt_replace tmp; 1551 struct compat_arpt_replace tmp;
1516 struct xt_table_info *newinfo; 1552 struct xt_table_info *newinfo;
1517 void *loc_cpu_entry; 1553 void *loc_cpu_entry;
1554 struct arpt_entry *iter;
1518 1555
1519 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1556 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1520 return -EFAULT; 1557 return -EFAULT;
@@ -1552,7 +1589,9 @@ static int compat_do_replace(struct net *net, void __user *user,
1552 return 0; 1589 return 0;
1553 1590
1554 free_newinfo_untrans: 1591 free_newinfo_untrans:
1555 ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1592 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1593 if (cleanup_entry(iter, NULL) != 0)
1594 break;
1556 free_newinfo: 1595 free_newinfo:
1557 xt_free_table_info(newinfo); 1596 xt_free_table_info(newinfo);
1558 return ret; 1597 return ret;
@@ -1636,6 +1675,7 @@ static int compat_copy_entries_to_user(unsigned int total_size,
1636 int ret = 0; 1675 int ret = 0;
1637 void *loc_cpu_entry; 1676 void *loc_cpu_entry;
1638 unsigned int i = 0; 1677 unsigned int i = 0;
1678 struct arpt_entry *iter;
1639 1679
1640 counters = alloc_counters(table); 1680 counters = alloc_counters(table);
1641 if (IS_ERR(counters)) 1681 if (IS_ERR(counters))
@@ -1645,9 +1685,12 @@ static int compat_copy_entries_to_user(unsigned int total_size,
1645 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1685 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1646 pos = userptr; 1686 pos = userptr;
1647 size = total_size; 1687 size = total_size;
1648 ret = ARPT_ENTRY_ITERATE(loc_cpu_entry, total_size, 1688 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1649 compat_copy_entry_to_user, 1689 ret = compat_copy_entry_to_user(iter, &pos,
1650 &pos, &size, counters, &i); 1690 &size, counters, &i);
1691 if (ret != 0)
1692 break;
1693 }
1651 vfree(counters); 1694 vfree(counters);
1652 return ret; 1695 return ret;
1653} 1696}
@@ -1843,13 +1886,15 @@ void arpt_unregister_table(struct xt_table *table)
1843 struct xt_table_info *private; 1886 struct xt_table_info *private;
1844 void *loc_cpu_entry; 1887 void *loc_cpu_entry;
1845 struct module *table_owner = table->me; 1888 struct module *table_owner = table->me;
1889 struct arpt_entry *iter;
1846 1890
1847 private = xt_unregister_table(table); 1891 private = xt_unregister_table(table);
1848 1892
1849 /* Decrease module usage counts and free resources */ 1893 /* Decrease module usage counts and free resources */
1850 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1894 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1851 ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, 1895 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1852 cleanup_entry, NULL); 1896 if (cleanup_entry(iter, NULL) != 0)
1897 break;
1853 if (private->number > private->initial_entries) 1898 if (private->number > private->initial_entries)
1854 module_put(table_owner); 1899 module_put(table_owner);
1855 xt_free_table_info(private); 1900 xt_free_table_info(private);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e94c18bdfc68..b43280aad8a2 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -288,6 +288,7 @@ static void trace_packet(const struct sk_buff *skb,
288 const void *table_base; 288 const void *table_base;
289 const struct ipt_entry *root; 289 const struct ipt_entry *root;
290 const char *hookname, *chainname, *comment; 290 const char *hookname, *chainname, *comment;
291 const struct ipt_entry *iter;
291 unsigned int rulenum = 0; 292 unsigned int rulenum = 0;
292 293
293 table_base = private->entries[smp_processor_id()]; 294 table_base = private->entries[smp_processor_id()];
@@ -296,10 +297,10 @@ static void trace_packet(const struct sk_buff *skb,
296 hookname = chainname = hooknames[hook]; 297 hookname = chainname = hooknames[hook];
297 comment = comments[NF_IP_TRACE_COMMENT_RULE]; 298 comment = comments[NF_IP_TRACE_COMMENT_RULE];
298 299
299 IPT_ENTRY_ITERATE(root, 300 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
300 private->size - private->hook_entry[hook], 301 if (get_chainname_rulenum(iter, e, hookname,
301 get_chainname_rulenum, 302 &chainname, &comment, &rulenum) != 0)
302 e, hookname, &chainname, &comment, &rulenum); 303 break;
303 304
304 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo, 305 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,
305 "TRACE: %s:%s:%s:%u ", 306 "TRACE: %s:%s:%s:%u ",
@@ -826,8 +827,9 @@ translate_table(struct net *net,
826 const unsigned int *hook_entries, 827 const unsigned int *hook_entries,
827 const unsigned int *underflows) 828 const unsigned int *underflows)
828{ 829{
830 struct ipt_entry *iter;
829 unsigned int i; 831 unsigned int i;
830 int ret; 832 int ret = 0;
831 833
832 newinfo->size = size; 834 newinfo->size = size;
833 newinfo->number = number; 835 newinfo->number = number;
@@ -841,12 +843,13 @@ translate_table(struct net *net,
841 duprintf("translate_table: size %u\n", newinfo->size); 843 duprintf("translate_table: size %u\n", newinfo->size);
842 i = 0; 844 i = 0;
843 /* Walk through entries, checking offsets. */ 845 /* Walk through entries, checking offsets. */
844 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 846 xt_entry_foreach(iter, entry0, newinfo->size) {
845 check_entry_size_and_hooks, 847 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
846 newinfo, 848 entry0 + size, hook_entries, underflows,
847 entry0, 849 valid_hooks, &i);
848 entry0 + size, 850 if (ret != 0)
849 hook_entries, underflows, valid_hooks, &i); 851 break;
852 }
850 if (ret != 0) 853 if (ret != 0)
851 return ret; 854 return ret;
852 855
@@ -878,12 +881,16 @@ translate_table(struct net *net,
878 881
879 /* Finally, each sanity check must pass */ 882 /* Finally, each sanity check must pass */
880 i = 0; 883 i = 0;
881 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 884 xt_entry_foreach(iter, entry0, newinfo->size) {
882 find_check_entry, net, name, size, &i); 885 ret = find_check_entry(iter, net, name, size, &i);
886 if (ret != 0)
887 break;
888 }
883 889
884 if (ret != 0) { 890 if (ret != 0) {
885 IPT_ENTRY_ITERATE(entry0, newinfo->size, 891 xt_entry_foreach(iter, entry0, newinfo->size)
886 cleanup_entry, net, &i); 892 if (cleanup_entry(iter, net, &i) != 0)
893 break;
887 return ret; 894 return ret;
888 } 895 }
889 896
@@ -923,6 +930,7 @@ static void
923get_counters(const struct xt_table_info *t, 930get_counters(const struct xt_table_info *t,
924 struct xt_counters counters[]) 931 struct xt_counters counters[])
925{ 932{
933 struct ipt_entry *iter;
926 unsigned int cpu; 934 unsigned int cpu;
927 unsigned int i; 935 unsigned int i;
928 unsigned int curcpu; 936 unsigned int curcpu;
@@ -938,22 +946,18 @@ get_counters(const struct xt_table_info *t,
938 curcpu = smp_processor_id(); 946 curcpu = smp_processor_id();
939 947
940 i = 0; 948 i = 0;
941 IPT_ENTRY_ITERATE(t->entries[curcpu], 949 xt_entry_foreach(iter, t->entries[curcpu], t->size)
942 t->size, 950 if (set_entry_to_counter(iter, counters, &i) != 0)
943 set_entry_to_counter, 951 break;
944 counters,
945 &i);
946 952
947 for_each_possible_cpu(cpu) { 953 for_each_possible_cpu(cpu) {
948 if (cpu == curcpu) 954 if (cpu == curcpu)
949 continue; 955 continue;
950 i = 0; 956 i = 0;
951 xt_info_wrlock(cpu); 957 xt_info_wrlock(cpu);
952 IPT_ENTRY_ITERATE(t->entries[cpu], 958 xt_entry_foreach(iter, t->entries[cpu], t->size)
953 t->size, 959 if (add_entry_to_counter(iter, counters, &i) != 0)
954 add_entry_to_counter, 960 break;
955 counters,
956 &i);
957 xt_info_wrunlock(cpu); 961 xt_info_wrunlock(cpu);
958 } 962 }
959 local_bh_enable(); 963 local_bh_enable();
@@ -1111,7 +1115,9 @@ static int compat_calc_entry(const struct ipt_entry *e,
1111static int compat_table_info(const struct xt_table_info *info, 1115static int compat_table_info(const struct xt_table_info *info,
1112 struct xt_table_info *newinfo) 1116 struct xt_table_info *newinfo)
1113{ 1117{
1118 struct ipt_entry *iter;
1114 void *loc_cpu_entry; 1119 void *loc_cpu_entry;
1120 int ret = 0;
1115 1121
1116 if (!newinfo || !info) 1122 if (!newinfo || !info)
1117 return -EINVAL; 1123 return -EINVAL;
@@ -1120,9 +1126,12 @@ static int compat_table_info(const struct xt_table_info *info,
1120 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 1126 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1121 newinfo->initial_entries = 0; 1127 newinfo->initial_entries = 0;
1122 loc_cpu_entry = info->entries[raw_smp_processor_id()]; 1128 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1123 return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size, 1129 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1124 compat_calc_entry, info, loc_cpu_entry, 1130 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1125 newinfo); 1131 if (ret != 0)
1132 break;
1133 }
1134 return ret;
1126} 1135}
1127#endif 1136#endif
1128 1137
@@ -1236,6 +1245,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1236 struct xt_table_info *oldinfo; 1245 struct xt_table_info *oldinfo;
1237 struct xt_counters *counters; 1246 struct xt_counters *counters;
1238 void *loc_cpu_old_entry; 1247 void *loc_cpu_old_entry;
1248 struct ipt_entry *iter;
1239 1249
1240 ret = 0; 1250 ret = 0;
1241 counters = vmalloc(num_counters * sizeof(struct xt_counters)); 1251 counters = vmalloc(num_counters * sizeof(struct xt_counters));
@@ -1278,8 +1288,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1278 1288
1279 /* Decrease module usage counts and free resource */ 1289 /* Decrease module usage counts and free resource */
1280 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1290 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1281 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1291 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1282 net, NULL); 1292 if (cleanup_entry(iter, net, NULL) != 0)
1293 break;
1294
1283 xt_free_table_info(oldinfo); 1295 xt_free_table_info(oldinfo);
1284 if (copy_to_user(counters_ptr, counters, 1296 if (copy_to_user(counters_ptr, counters,
1285 sizeof(struct xt_counters) * num_counters) != 0) 1297 sizeof(struct xt_counters) * num_counters) != 0)
@@ -1304,6 +1316,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1304 struct ipt_replace tmp; 1316 struct ipt_replace tmp;
1305 struct xt_table_info *newinfo; 1317 struct xt_table_info *newinfo;
1306 void *loc_cpu_entry; 1318 void *loc_cpu_entry;
1319 struct ipt_entry *iter;
1307 1320
1308 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1321 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1309 return -EFAULT; 1322 return -EFAULT;
@@ -1339,7 +1352,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1339 return 0; 1352 return 0;
1340 1353
1341 free_newinfo_untrans: 1354 free_newinfo_untrans:
1342 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1355 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1356 if (cleanup_entry(iter, net, NULL) != 0)
1357 break;
1343 free_newinfo: 1358 free_newinfo:
1344 xt_free_table_info(newinfo); 1359 xt_free_table_info(newinfo);
1345 return ret; 1360 return ret;
@@ -1373,6 +1388,7 @@ do_add_counters(struct net *net, const void __user *user,
1373 const struct xt_table_info *private; 1388 const struct xt_table_info *private;
1374 int ret = 0; 1389 int ret = 0;
1375 void *loc_cpu_entry; 1390 void *loc_cpu_entry;
1391 struct ipt_entry *iter;
1376#ifdef CONFIG_COMPAT 1392#ifdef CONFIG_COMPAT
1377 struct compat_xt_counters_info compat_tmp; 1393 struct compat_xt_counters_info compat_tmp;
1378 1394
@@ -1430,11 +1446,9 @@ do_add_counters(struct net *net, const void __user *user,
1430 curcpu = smp_processor_id(); 1446 curcpu = smp_processor_id();
1431 loc_cpu_entry = private->entries[curcpu]; 1447 loc_cpu_entry = private->entries[curcpu];
1432 xt_info_wrlock(curcpu); 1448 xt_info_wrlock(curcpu);
1433 IPT_ENTRY_ITERATE(loc_cpu_entry, 1449 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1434 private->size, 1450 if (add_counter_to_entry(iter, paddc, &i) != 0)
1435 add_counter_to_entry, 1451 break;
1436 paddc,
1437 &i);
1438 xt_info_wrunlock(curcpu); 1452 xt_info_wrunlock(curcpu);
1439 unlock_up_free: 1453 unlock_up_free:
1440 local_bh_enable(); 1454 local_bh_enable();
@@ -1720,8 +1734,10 @@ translate_compat_table(struct net *net,
1720 unsigned int i, j; 1734 unsigned int i, j;
1721 struct xt_table_info *newinfo, *info; 1735 struct xt_table_info *newinfo, *info;
1722 void *pos, *entry0, *entry1; 1736 void *pos, *entry0, *entry1;
1737 struct compat_ipt_entry *iter0;
1738 struct ipt_entry *iter1;
1723 unsigned int size; 1739 unsigned int size;
1724 int ret; 1740 int ret = 0;
1725 1741
1726 info = *pinfo; 1742 info = *pinfo;
1727 entry0 = *pentry0; 1743 entry0 = *pentry0;
@@ -1738,11 +1754,13 @@ translate_compat_table(struct net *net,
1738 j = 0; 1754 j = 0;
1739 xt_compat_lock(AF_INET); 1755 xt_compat_lock(AF_INET);
1740 /* Walk through entries, checking offsets. */ 1756 /* Walk through entries, checking offsets. */
1741 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, 1757 xt_entry_foreach(iter0, entry0, total_size) {
1742 check_compat_entry_size_and_hooks, 1758 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1743 info, &size, entry0, 1759 entry0, entry0 + total_size, hook_entries, underflows,
1744 entry0 + total_size, 1760 &j, name);
1745 hook_entries, underflows, &j, name); 1761 if (ret != 0)
1762 break;
1763 }
1746 if (ret != 0) 1764 if (ret != 0)
1747 goto out_unlock; 1765 goto out_unlock;
1748 1766
@@ -1783,9 +1801,12 @@ translate_compat_table(struct net *net,
1783 entry1 = newinfo->entries[raw_smp_processor_id()]; 1801 entry1 = newinfo->entries[raw_smp_processor_id()];
1784 pos = entry1; 1802 pos = entry1;
1785 size = total_size; 1803 size = total_size;
1786 ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, 1804 xt_entry_foreach(iter0, entry0, total_size) {
1787 compat_copy_entry_from_user, 1805 ret = compat_copy_entry_from_user(iter0, &pos,
1788 &pos, &size, name, newinfo, entry1); 1806 &size, name, newinfo, entry1);
1807 if (ret != 0)
1808 break;
1809 }
1789 xt_compat_flush_offsets(AF_INET); 1810 xt_compat_flush_offsets(AF_INET);
1790 xt_compat_unlock(AF_INET); 1811 xt_compat_unlock(AF_INET);
1791 if (ret) 1812 if (ret)
@@ -1796,13 +1817,28 @@ translate_compat_table(struct net *net,
1796 goto free_newinfo; 1817 goto free_newinfo;
1797 1818
1798 i = 0; 1819 i = 0;
1799 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1820 xt_entry_foreach(iter1, entry1, newinfo->size) {
1800 net, name, &i); 1821 ret = compat_check_entry(iter1, net, name, &i);
1822 if (ret != 0)
1823 break;
1824 }
1801 if (ret) { 1825 if (ret) {
1826 /*
1827 * The first i matches need cleanup_entry (calls ->destroy)
1828 * because they had called ->check already. The other j-i
1829 * entries need only release.
1830 */
1831 int skip = i;
1802 j -= i; 1832 j -= i;
1803 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1833 xt_entry_foreach(iter0, entry0, newinfo->size) {
1804 compat_release_entry, &j); 1834 if (skip-- > 0)
1805 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); 1835 continue;
1836 if (compat_release_entry(iter0, &i) != 0)
1837 break;
1838 }
1839 xt_entry_foreach(iter1, entry1, newinfo->size)
1840 if (cleanup_entry(iter1, net, &i) != 0)
1841 break;
1806 xt_free_table_info(newinfo); 1842 xt_free_table_info(newinfo);
1807 return ret; 1843 return ret;
1808 } 1844 }
@@ -1820,7 +1856,9 @@ translate_compat_table(struct net *net,
1820free_newinfo: 1856free_newinfo:
1821 xt_free_table_info(newinfo); 1857 xt_free_table_info(newinfo);
1822out: 1858out:
1823 COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1859 xt_entry_foreach(iter0, entry0, total_size)
1860 if (compat_release_entry(iter0, &j) != 0)
1861 break;
1824 return ret; 1862 return ret;
1825out_unlock: 1863out_unlock:
1826 xt_compat_flush_offsets(AF_INET); 1864 xt_compat_flush_offsets(AF_INET);
@@ -1835,6 +1873,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1835 struct compat_ipt_replace tmp; 1873 struct compat_ipt_replace tmp;
1836 struct xt_table_info *newinfo; 1874 struct xt_table_info *newinfo;
1837 void *loc_cpu_entry; 1875 void *loc_cpu_entry;
1876 struct ipt_entry *iter;
1838 1877
1839 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1878 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1840 return -EFAULT; 1879 return -EFAULT;
@@ -1873,7 +1912,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1873 return 0; 1912 return 0;
1874 1913
1875 free_newinfo_untrans: 1914 free_newinfo_untrans:
1876 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1915 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1916 if (cleanup_entry(iter, net, NULL) != 0)
1917 break;
1877 free_newinfo: 1918 free_newinfo:
1878 xt_free_table_info(newinfo); 1919 xt_free_table_info(newinfo);
1879 return ret; 1920 return ret;
@@ -1922,6 +1963,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1922 int ret = 0; 1963 int ret = 0;
1923 const void *loc_cpu_entry; 1964 const void *loc_cpu_entry;
1924 unsigned int i = 0; 1965 unsigned int i = 0;
1966 struct ipt_entry *iter;
1925 1967
1926 counters = alloc_counters(table); 1968 counters = alloc_counters(table);
1927 if (IS_ERR(counters)) 1969 if (IS_ERR(counters))
@@ -1934,9 +1976,12 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1934 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 1976 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1935 pos = userptr; 1977 pos = userptr;
1936 size = total_size; 1978 size = total_size;
1937 ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size, 1979 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1938 compat_copy_entry_to_user, 1980 ret = compat_copy_entry_to_user(iter, &pos,
1939 &pos, &size, counters, &i); 1981 &size, counters, &i);
1982 if (ret != 0)
1983 break;
1984 }
1940 1985
1941 vfree(counters); 1986 vfree(counters);
1942 return ret; 1987 return ret;
@@ -2137,12 +2182,15 @@ void ipt_unregister_table(struct net *net, struct xt_table *table)
2137 struct xt_table_info *private; 2182 struct xt_table_info *private;
2138 void *loc_cpu_entry; 2183 void *loc_cpu_entry;
2139 struct module *table_owner = table->me; 2184 struct module *table_owner = table->me;
2185 struct ipt_entry *iter;
2140 2186
2141 private = xt_unregister_table(table); 2187 private = xt_unregister_table(table);
2142 2188
2143 /* Decrease module usage counts and free resources */ 2189 /* Decrease module usage counts and free resources */
2144 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2190 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2145 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); 2191 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2192 if (cleanup_entry(iter, net, NULL) != 0)
2193 break;
2146 if (private->number > private->initial_entries) 2194 if (private->number > private->initial_entries)
2147 module_put(table_owner); 2195 module_put(table_owner);
2148 xt_free_table_info(private); 2196 xt_free_table_info(private);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4185099c2943..23926e38d36b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -318,6 +318,7 @@ static void trace_packet(const struct sk_buff *skb,
318 const void *table_base; 318 const void *table_base;
319 const struct ip6t_entry *root; 319 const struct ip6t_entry *root;
320 const char *hookname, *chainname, *comment; 320 const char *hookname, *chainname, *comment;
321 const struct ip6t_entry *iter;
321 unsigned int rulenum = 0; 322 unsigned int rulenum = 0;
322 323
323 table_base = private->entries[smp_processor_id()]; 324 table_base = private->entries[smp_processor_id()];
@@ -326,10 +327,10 @@ static void trace_packet(const struct sk_buff *skb,
326 hookname = chainname = hooknames[hook]; 327 hookname = chainname = hooknames[hook];
327 comment = comments[NF_IP6_TRACE_COMMENT_RULE]; 328 comment = comments[NF_IP6_TRACE_COMMENT_RULE];
328 329
329 IP6T_ENTRY_ITERATE(root, 330 xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])
330 private->size - private->hook_entry[hook], 331 if (get_chainname_rulenum(iter, e, hookname,
331 get_chainname_rulenum, 332 &chainname, &comment, &rulenum) != 0)
332 e, hookname, &chainname, &comment, &rulenum); 333 break;
333 334
334 nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo, 335 nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,
335 "TRACE: %s:%s:%s:%u ", 336 "TRACE: %s:%s:%s:%u ",
@@ -857,8 +858,9 @@ translate_table(struct net *net,
857 const unsigned int *hook_entries, 858 const unsigned int *hook_entries,
858 const unsigned int *underflows) 859 const unsigned int *underflows)
859{ 860{
861 struct ip6t_entry *iter;
860 unsigned int i; 862 unsigned int i;
861 int ret; 863 int ret = 0;
862 864
863 newinfo->size = size; 865 newinfo->size = size;
864 newinfo->number = number; 866 newinfo->number = number;
@@ -872,12 +874,13 @@ translate_table(struct net *net,
872 duprintf("translate_table: size %u\n", newinfo->size); 874 duprintf("translate_table: size %u\n", newinfo->size);
873 i = 0; 875 i = 0;
874 /* Walk through entries, checking offsets. */ 876 /* Walk through entries, checking offsets. */
875 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 877 xt_entry_foreach(iter, entry0, newinfo->size) {
876 check_entry_size_and_hooks, 878 ret = check_entry_size_and_hooks(iter, newinfo, entry0,
877 newinfo, 879 entry0 + size, hook_entries, underflows,
878 entry0, 880 valid_hooks, &i);
879 entry0 + size, 881 if (ret != 0)
880 hook_entries, underflows, valid_hooks, &i); 882 break;
883 }
881 if (ret != 0) 884 if (ret != 0)
882 return ret; 885 return ret;
883 886
@@ -909,12 +912,16 @@ translate_table(struct net *net,
909 912
910 /* Finally, each sanity check must pass */ 913 /* Finally, each sanity check must pass */
911 i = 0; 914 i = 0;
912 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 915 xt_entry_foreach(iter, entry0, newinfo->size) {
913 find_check_entry, net, name, size, &i); 916 ret = find_check_entry(iter, net, name, size, &i);
917 if (ret != 0)
918 break;
919 }
914 920
915 if (ret != 0) { 921 if (ret != 0) {
916 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 922 xt_entry_foreach(iter, entry0, newinfo->size)
917 cleanup_entry, net, &i); 923 if (cleanup_entry(iter, net, &i) != 0)
924 break;
918 return ret; 925 return ret;
919 } 926 }
920 927
@@ -954,6 +961,7 @@ static void
954get_counters(const struct xt_table_info *t, 961get_counters(const struct xt_table_info *t,
955 struct xt_counters counters[]) 962 struct xt_counters counters[])
956{ 963{
964 struct ip6t_entry *iter;
957 unsigned int cpu; 965 unsigned int cpu;
958 unsigned int i; 966 unsigned int i;
959 unsigned int curcpu; 967 unsigned int curcpu;
@@ -969,22 +977,18 @@ get_counters(const struct xt_table_info *t,
969 curcpu = smp_processor_id(); 977 curcpu = smp_processor_id();
970 978
971 i = 0; 979 i = 0;
972 IP6T_ENTRY_ITERATE(t->entries[curcpu], 980 xt_entry_foreach(iter, t->entries[curcpu], t->size)
973 t->size, 981 if (set_entry_to_counter(iter, counters, &i) != 0)
974 set_entry_to_counter, 982 break;
975 counters,
976 &i);
977 983
978 for_each_possible_cpu(cpu) { 984 for_each_possible_cpu(cpu) {
979 if (cpu == curcpu) 985 if (cpu == curcpu)
980 continue; 986 continue;
981 i = 0; 987 i = 0;
982 xt_info_wrlock(cpu); 988 xt_info_wrlock(cpu);
983 IP6T_ENTRY_ITERATE(t->entries[cpu], 989 xt_entry_foreach(iter, t->entries[cpu], t->size)
984 t->size, 990 if (add_entry_to_counter(iter, counters, &i) != 0)
985 add_entry_to_counter, 991 break;
986 counters,
987 &i);
988 xt_info_wrunlock(cpu); 992 xt_info_wrunlock(cpu);
989 } 993 }
990 local_bh_enable(); 994 local_bh_enable();
@@ -1142,7 +1146,9 @@ static int compat_calc_entry(const struct ip6t_entry *e,
1142static int compat_table_info(const struct xt_table_info *info, 1146static int compat_table_info(const struct xt_table_info *info,
1143 struct xt_table_info *newinfo) 1147 struct xt_table_info *newinfo)
1144{ 1148{
1149 struct ip6t_entry *iter;
1145 void *loc_cpu_entry; 1150 void *loc_cpu_entry;
1151 int ret = 0;
1146 1152
1147 if (!newinfo || !info) 1153 if (!newinfo || !info)
1148 return -EINVAL; 1154 return -EINVAL;
@@ -1151,9 +1157,12 @@ static int compat_table_info(const struct xt_table_info *info,
1151 memcpy(newinfo, info, offsetof(struct xt_table_info, entries)); 1157 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
1152 newinfo->initial_entries = 0; 1158 newinfo->initial_entries = 0;
1153 loc_cpu_entry = info->entries[raw_smp_processor_id()]; 1159 loc_cpu_entry = info->entries[raw_smp_processor_id()];
1154 return IP6T_ENTRY_ITERATE(loc_cpu_entry, info->size, 1160 xt_entry_foreach(iter, loc_cpu_entry, info->size) {
1155 compat_calc_entry, info, loc_cpu_entry, 1161 ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
1156 newinfo); 1162 if (ret != 0)
1163 break;
1164 }
1165 return ret;
1157} 1166}
1158#endif 1167#endif
1159 1168
@@ -1267,6 +1276,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1267 struct xt_table_info *oldinfo; 1276 struct xt_table_info *oldinfo;
1268 struct xt_counters *counters; 1277 struct xt_counters *counters;
1269 const void *loc_cpu_old_entry; 1278 const void *loc_cpu_old_entry;
1279 struct ip6t_entry *iter;
1270 1280
1271 ret = 0; 1281 ret = 0;
1272 counters = vmalloc_node(num_counters * sizeof(struct xt_counters), 1282 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
@@ -1310,8 +1320,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1310 1320
1311 /* Decrease module usage counts and free resource */ 1321 /* Decrease module usage counts and free resource */
1312 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1322 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1313 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1323 xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
1314 net, NULL); 1324 if (cleanup_entry(iter, net, NULL) != 0)
1325 break;
1326
1315 xt_free_table_info(oldinfo); 1327 xt_free_table_info(oldinfo);
1316 if (copy_to_user(counters_ptr, counters, 1328 if (copy_to_user(counters_ptr, counters,
1317 sizeof(struct xt_counters) * num_counters) != 0) 1329 sizeof(struct xt_counters) * num_counters) != 0)
@@ -1336,6 +1348,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1336 struct ip6t_replace tmp; 1348 struct ip6t_replace tmp;
1337 struct xt_table_info *newinfo; 1349 struct xt_table_info *newinfo;
1338 void *loc_cpu_entry; 1350 void *loc_cpu_entry;
1351 struct ip6t_entry *iter;
1339 1352
1340 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1353 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1341 return -EFAULT; 1354 return -EFAULT;
@@ -1371,7 +1384,9 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
1371 return 0; 1384 return 0;
1372 1385
1373 free_newinfo_untrans: 1386 free_newinfo_untrans:
1374 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1387 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1388 if (cleanup_entry(iter, net, NULL) != 0)
1389 break;
1375 free_newinfo: 1390 free_newinfo:
1376 xt_free_table_info(newinfo); 1391 xt_free_table_info(newinfo);
1377 return ret; 1392 return ret;
@@ -1405,6 +1420,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
1405 const struct xt_table_info *private; 1420 const struct xt_table_info *private;
1406 int ret = 0; 1421 int ret = 0;
1407 const void *loc_cpu_entry; 1422 const void *loc_cpu_entry;
1423 struct ip6t_entry *iter;
1408#ifdef CONFIG_COMPAT 1424#ifdef CONFIG_COMPAT
1409 struct compat_xt_counters_info compat_tmp; 1425 struct compat_xt_counters_info compat_tmp;
1410 1426
@@ -1463,11 +1479,9 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
1463 curcpu = smp_processor_id(); 1479 curcpu = smp_processor_id();
1464 xt_info_wrlock(curcpu); 1480 xt_info_wrlock(curcpu);
1465 loc_cpu_entry = private->entries[curcpu]; 1481 loc_cpu_entry = private->entries[curcpu];
1466 IP6T_ENTRY_ITERATE(loc_cpu_entry, 1482 xt_entry_foreach(iter, loc_cpu_entry, private->size)
1467 private->size, 1483 if (add_counter_to_entry(iter, paddc, &i) != 0)
1468 add_counter_to_entry, 1484 break;
1469 paddc,
1470 &i);
1471 xt_info_wrunlock(curcpu); 1485 xt_info_wrunlock(curcpu);
1472 1486
1473 unlock_up_free: 1487 unlock_up_free:
@@ -1753,8 +1767,10 @@ translate_compat_table(struct net *net,
1753 unsigned int i, j; 1767 unsigned int i, j;
1754 struct xt_table_info *newinfo, *info; 1768 struct xt_table_info *newinfo, *info;
1755 void *pos, *entry0, *entry1; 1769 void *pos, *entry0, *entry1;
1770 struct compat_ip6t_entry *iter0;
1771 struct ip6t_entry *iter1;
1756 unsigned int size; 1772 unsigned int size;
1757 int ret; 1773 int ret = 0;
1758 1774
1759 info = *pinfo; 1775 info = *pinfo;
1760 entry0 = *pentry0; 1776 entry0 = *pentry0;
@@ -1771,11 +1787,13 @@ translate_compat_table(struct net *net,
1771 j = 0; 1787 j = 0;
1772 xt_compat_lock(AF_INET6); 1788 xt_compat_lock(AF_INET6);
1773 /* Walk through entries, checking offsets. */ 1789 /* Walk through entries, checking offsets. */
1774 ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, 1790 xt_entry_foreach(iter0, entry0, total_size) {
1775 check_compat_entry_size_and_hooks, 1791 ret = check_compat_entry_size_and_hooks(iter0, info, &size,
1776 info, &size, entry0, 1792 entry0, entry0 + total_size, hook_entries, underflows,
1777 entry0 + total_size, 1793 &j, name);
1778 hook_entries, underflows, &j, name); 1794 if (ret != 0)
1795 break;
1796 }
1779 if (ret != 0) 1797 if (ret != 0)
1780 goto out_unlock; 1798 goto out_unlock;
1781 1799
@@ -1816,9 +1834,12 @@ translate_compat_table(struct net *net,
1816 entry1 = newinfo->entries[raw_smp_processor_id()]; 1834 entry1 = newinfo->entries[raw_smp_processor_id()];
1817 pos = entry1; 1835 pos = entry1;
1818 size = total_size; 1836 size = total_size;
1819 ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, 1837 xt_entry_foreach(iter0, entry0, total_size) {
1820 compat_copy_entry_from_user, 1838 ret = compat_copy_entry_from_user(iter0, &pos,
1821 &pos, &size, name, newinfo, entry1); 1839 &size, name, newinfo, entry1);
1840 if (ret != 0)
1841 break;
1842 }
1822 xt_compat_flush_offsets(AF_INET6); 1843 xt_compat_flush_offsets(AF_INET6);
1823 xt_compat_unlock(AF_INET6); 1844 xt_compat_unlock(AF_INET6);
1824 if (ret) 1845 if (ret)
@@ -1829,13 +1850,28 @@ translate_compat_table(struct net *net,
1829 goto free_newinfo; 1850 goto free_newinfo;
1830 1851
1831 i = 0; 1852 i = 0;
1832 ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1853 xt_entry_foreach(iter1, entry1, newinfo->size) {
1833 net, name, &i); 1854 ret = compat_check_entry(iter1, net, name, &i);
1855 if (ret != 0)
1856 break;
1857 }
1834 if (ret) { 1858 if (ret) {
1859 /*
1860 * The first i matches need cleanup_entry (calls ->destroy)
1861 * because they had called ->check already. The other j-i
1862 * entries need only release.
1863 */
1864 int skip = i;
1835 j -= i; 1865 j -= i;
1836 COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1866 xt_entry_foreach(iter0, entry0, newinfo->size) {
1837 compat_release_entry, &j); 1867 if (skip-- > 0)
1838 IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i); 1868 continue;
1869 if (compat_release_entry(iter0, &j) != 0)
1870 break;
1871 }
1872 xt_entry_foreach(iter1, entry1, newinfo->size)
1873 if (cleanup_entry(iter1, net, &i) != 0)
1874 break;
1839 xt_free_table_info(newinfo); 1875 xt_free_table_info(newinfo);
1840 return ret; 1876 return ret;
1841 } 1877 }
@@ -1853,7 +1889,9 @@ translate_compat_table(struct net *net,
1853free_newinfo: 1889free_newinfo:
1854 xt_free_table_info(newinfo); 1890 xt_free_table_info(newinfo);
1855out: 1891out:
1856 COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); 1892 xt_entry_foreach(iter0, entry0, total_size)
1893 if (compat_release_entry(iter0, &j) != 0)
1894 break;
1857 return ret; 1895 return ret;
1858out_unlock: 1896out_unlock:
1859 xt_compat_flush_offsets(AF_INET6); 1897 xt_compat_flush_offsets(AF_INET6);
@@ -1868,6 +1906,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1868 struct compat_ip6t_replace tmp; 1906 struct compat_ip6t_replace tmp;
1869 struct xt_table_info *newinfo; 1907 struct xt_table_info *newinfo;
1870 void *loc_cpu_entry; 1908 void *loc_cpu_entry;
1909 struct ip6t_entry *iter;
1871 1910
1872 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) 1911 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
1873 return -EFAULT; 1912 return -EFAULT;
@@ -1906,7 +1945,9 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1906 return 0; 1945 return 0;
1907 1946
1908 free_newinfo_untrans: 1947 free_newinfo_untrans:
1909 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL); 1948 xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
1949 if (cleanup_entry(iter, net, NULL) != 0)
1950 break;
1910 free_newinfo: 1951 free_newinfo:
1911 xt_free_table_info(newinfo); 1952 xt_free_table_info(newinfo);
1912 return ret; 1953 return ret;
@@ -1955,6 +1996,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1955 int ret = 0; 1996 int ret = 0;
1956 const void *loc_cpu_entry; 1997 const void *loc_cpu_entry;
1957 unsigned int i = 0; 1998 unsigned int i = 0;
1999 struct ip6t_entry *iter;
1958 2000
1959 counters = alloc_counters(table); 2001 counters = alloc_counters(table);
1960 if (IS_ERR(counters)) 2002 if (IS_ERR(counters))
@@ -1967,9 +2009,12 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1967 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2009 loc_cpu_entry = private->entries[raw_smp_processor_id()];
1968 pos = userptr; 2010 pos = userptr;
1969 size = total_size; 2011 size = total_size;
1970 ret = IP6T_ENTRY_ITERATE(loc_cpu_entry, total_size, 2012 xt_entry_foreach(iter, loc_cpu_entry, total_size) {
1971 compat_copy_entry_to_user, 2013 ret = compat_copy_entry_to_user(iter, &pos,
1972 &pos, &size, counters, &i); 2014 &size, counters, &i);
2015 if (ret != 0)
2016 break;
2017 }
1973 2018
1974 vfree(counters); 2019 vfree(counters);
1975 return ret; 2020 return ret;
@@ -2169,12 +2214,15 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table)
2169 struct xt_table_info *private; 2214 struct xt_table_info *private;
2170 void *loc_cpu_entry; 2215 void *loc_cpu_entry;
2171 struct module *table_owner = table->me; 2216 struct module *table_owner = table->me;
2217 struct ip6t_entry *iter;
2172 2218
2173 private = xt_unregister_table(table); 2219 private = xt_unregister_table(table);
2174 2220
2175 /* Decrease module usage counts and free resources */ 2221 /* Decrease module usage counts and free resources */
2176 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2222 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2177 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL); 2223 xt_entry_foreach(iter, loc_cpu_entry, private->size)
2224 if (cleanup_entry(iter, net, NULL) != 0)
2225 break;
2178 if (private->number > private->initial_entries) 2226 if (private->number > private->initial_entries)
2179 module_put(table_owner); 2227 module_put(table_owner);
2180 xt_free_table_info(private); 2228 xt_free_table_info(private);