aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2005-10-13 17:41:23 -0400
committerDavid S. Miller <davem@davemloft.net>2005-10-13 17:41:23 -0400
commitc8923c6b852d3a97c1faad0566e38fca330375a7 (patch)
treeeb79e97c5468bba641c7a34b83514876f4902cf2 /net/ipv6
parentc931488cc4619eecfe68a2f046b5898fddc2f904 (diff)
[NETFILTER]: Fix OOPSes on machines with discontiguous cpu numbering.
Original patch by Harald Welte, with feedback from Herbert Xu and testing by Sébastien Bernard. EBTABLES, ARP tables, and IP/IP6 tables all assume that cpus are numbered linearly. That is not necessarily true. This patch fixes that up by calculating the largest possible cpu number, and allocating enough per-cpu structure space given that. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_tables.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 2da514b16d95..b03e90649eb5 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -28,6 +28,7 @@
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29#include <asm/semaphore.h> 29#include <asm/semaphore.h>
30#include <linux/proc_fs.h> 30#include <linux/proc_fs.h>
31#include <linux/cpumask.h>
31 32
32#include <linux/netfilter_ipv6/ip6_tables.h> 33#include <linux/netfilter_ipv6/ip6_tables.h>
33 34
@@ -950,8 +951,10 @@ translate_table(const char *name,
950 } 951 }
951 952
952 /* And one copy for every other CPU */ 953 /* And one copy for every other CPU */
953 for (i = 1; i < num_possible_cpus(); i++) { 954 for_each_cpu(i) {
954 memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, 955 if (i == 0)
956 continue;
957 memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i,
955 newinfo->entries, 958 newinfo->entries,
956 SMP_ALIGN(newinfo->size)); 959 SMP_ALIGN(newinfo->size));
957 } 960 }
@@ -973,6 +976,7 @@ replace_table(struct ip6t_table *table,
973 unsigned int i; 976 unsigned int i;
974 977
975 for (i = 0; i < num_possible_cpus(); i++) { 978 for (i = 0; i < num_possible_cpus(); i++) {
979 for_each_cpu(i) {
976 table_base = 980 table_base =
977 (void *)newinfo->entries 981 (void *)newinfo->entries
978 + TABLE_OFFSET(newinfo, i); 982 + TABLE_OFFSET(newinfo, i);
@@ -1019,7 +1023,7 @@ get_counters(const struct ip6t_table_info *t,
1019 unsigned int cpu; 1023 unsigned int cpu;
1020 unsigned int i; 1024 unsigned int i;
1021 1025
1022 for (cpu = 0; cpu < num_possible_cpus(); cpu++) { 1026 for_each_cpu(cpu) {
1023 i = 0; 1027 i = 0;
1024 IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), 1028 IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
1025 t->size, 1029 t->size,
@@ -1153,7 +1157,8 @@ do_replace(void __user *user, unsigned int len)
1153 return -ENOMEM; 1157 return -ENOMEM;
1154 1158
1155 newinfo = vmalloc(sizeof(struct ip6t_table_info) 1159 newinfo = vmalloc(sizeof(struct ip6t_table_info)
1156 + SMP_ALIGN(tmp.size) * num_possible_cpus()); 1160 + SMP_ALIGN(tmp.size) *
1161 (highest_possible_processor_id()+1));
1157 if (!newinfo) 1162 if (!newinfo)
1158 return -ENOMEM; 1163 return -ENOMEM;
1159 1164
@@ -1467,7 +1472,8 @@ int ip6t_register_table(struct ip6t_table *table,
1467 = { 0, 0, 0, { 0 }, { 0 }, { } }; 1472 = { 0, 0, 0, { 0 }, { 0 }, { } };
1468 1473
1469 newinfo = vmalloc(sizeof(struct ip6t_table_info) 1474 newinfo = vmalloc(sizeof(struct ip6t_table_info)
1470 + SMP_ALIGN(repl->size) * num_possible_cpus()); 1475 + SMP_ALIGN(repl->size) *
1476 (highest_possible_processor_id()+1));
1471 if (!newinfo) 1477 if (!newinfo)
1472 return -ENOMEM; 1478 return -ENOMEM;
1473 1479