diff options
-rw-r--r-- | include/linux/netfilter/x_tables.h | 9 | ||||
-rw-r--r-- | include/linux/netfilter_arp/arp_tables.h | 10 | ||||
-rw-r--r-- | include/linux/netfilter_ipv4/ip_tables.h | 11 | ||||
-rw-r--r-- | include/linux/netfilter_ipv6/ip6_tables.h | 10 | ||||
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 151 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_tables.c | 160 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 160 |
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, | |||
739 | static void get_counters(const struct xt_table_info *t, | 745 | static 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, | |||
899 | static int compat_table_info(const struct xt_table_info *info, | 902 | static 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, | |||
1488 | free_newinfo: | 1522 | free_newinfo: |
1489 | xt_free_table_info(newinfo); | 1523 | xt_free_table_info(newinfo); |
1490 | out: | 1524 | out: |
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; |
1493 | out_unlock: | 1529 | out_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 | |||
923 | get_counters(const struct xt_table_info *t, | 930 | get_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, | |||
1111 | static int compat_table_info(const struct xt_table_info *info, | 1115 | static 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, | |||
1820 | free_newinfo: | 1856 | free_newinfo: |
1821 | xt_free_table_info(newinfo); | 1857 | xt_free_table_info(newinfo); |
1822 | out: | 1858 | out: |
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; |
1825 | out_unlock: | 1863 | out_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 | |||
954 | get_counters(const struct xt_table_info *t, | 961 | get_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, | |||
1142 | static int compat_table_info(const struct xt_table_info *info, | 1146 | static 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, | |||
1853 | free_newinfo: | 1889 | free_newinfo: |
1854 | xt_free_table_info(newinfo); | 1890 | xt_free_table_info(newinfo); |
1855 | out: | 1891 | out: |
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; |
1858 | out_unlock: | 1896 | out_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); |