Ensure that xt_alloc_table_info returns an correctly aligned address, as vmalloc(), at least on PowerPC with gcc 4.0.3, does otherwise. This patch makes netfilter happy again on PowerPC. Without this patch, and with CONFIG_DEBUG_SLAB on, netfilter was broken since 2.6.16-rc1. Signed-off-by: Stelian Pop diff -r e21252272908 net/netfilter/x_tables.c --- a/net/netfilter/x_tables.c Mon Jun 05 11:48:18 2006 +0200 +++ b/net/netfilter/x_tables.c Tue Jun 06 00:22:27 2006 +0200 @@ -413,19 +413,21 @@ struct xt_table_info *xt_alloc_table_inf newinfo->size = size; + size += __alignof__(struct _xt_align); + for_each_possible_cpu(cpu) { + void *p; if (size <= PAGE_SIZE) - newinfo->entries[cpu] = kmalloc_node(size, - GFP_KERNEL, - cpu_to_node(cpu)); + p = kmalloc_node(size, GFP_KERNEL, cpu_to_node(cpu)); else - newinfo->entries[cpu] = vmalloc_node(size, - cpu_to_node(cpu)); - - if (newinfo->entries[cpu] == NULL) { + p = vmalloc_node(size, cpu_to_node(cpu)); + + if (p == NULL) { xt_free_table_info(newinfo); return NULL; } + newinfo->real_entries[cpu] = p; + newinfo->entries[cpu] = (char *)XT_ALIGN((unsigned long)p); } return newinfo; @@ -437,10 +439,10 @@ void xt_free_table_info(struct xt_table_ int cpu; for_each_possible_cpu(cpu) { - if (info->size <= PAGE_SIZE) - kfree(info->entries[cpu]); + if ((info->size + __alignof__(struct _xt_align)) <= PAGE_SIZE) + kfree(info->real_entries[cpu]); else - vfree(info->entries[cpu]); + vfree(info->real_entries[cpu]); } kfree(info); } diff -r e21252272908 include/linux/netfilter/x_tables.h --- a/include/linux/netfilter/x_tables.h Mon Jun 05 11:48:18 2006 +0200 +++ b/include/linux/netfilter/x_tables.h Tue Jun 06 00:22:27 2006 +0200 @@ -286,6 +286,7 @@ struct xt_table_info /* ipt_entry tables: one per CPU */ char *entries[NR_CPUS]; + char *real_entries[NR_CPUS]; }; extern int xt_register_target(struct xt_target *target);