summaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorKirill Korotaev <dev@openvz.org>2006-02-04 02:16:56 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-02-04 23:51:25 -0800
commitee4bb818ae35f68d1f848eae0a7b150a38eb4168 (patch)
tree85a6ba60fc5782d77779f466f1ad5f2ec4330914 /net/bridge
parentdf4e9574a36748c3a4d9b03ffca6b42321a797a9 (diff)
downloadlinux-ee4bb818ae35f68d1f848eae0a7b150a38eb4168.tar.gz
linux-ee4bb818ae35f68d1f848eae0a7b150a38eb4168.tar.bz2
linux-ee4bb818ae35f68d1f848eae0a7b150a38eb4168.zip
[NETFILTER]: Fix possible overflow in netfilters do_replace()
netfilter's do_replace() can overflow on addition within SMP_ALIGN() and/or on multiplication by NR_CPUS, resulting in a buffer overflow on the copy_from_user(). In practice, the overflow on addition is triggerable on all systems, whereas the multiplication one might require much physical memory to be present due to the check above. Either is sufficient to overwrite arbitrary amounts of kernel memory. I really hate adding the same check to all 4 versions of do_replace(), but the code is duplicate... Found by Solar Designer during security audit of OpenVZ.org Signed-Off-By: Kirill Korotaev <dev@openvz.org> Signed-Off-By: Solar Designer <solar@openwall.com> Signed-off-by: Patrck McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/netfilter/ebtables.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 00729b3604f8..cbd4020cc84d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -934,6 +934,13 @@ static int do_replace(void __user *user, unsigned int len)
BUGPRINT("Entries_size never zero\n");
return -EINVAL;
}
+ /* overflow check */
+ if (tmp.nentries >= ((INT_MAX - sizeof(struct ebt_table_info)) / NR_CPUS -
+ SMP_CACHE_BYTES) / sizeof(struct ebt_counter))
+ return -ENOMEM;
+ if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
+ return -ENOMEM;
+
countersize = COUNTER_OFFSET(tmp.nentries) *
(highest_possible_processor_id()+1);
newinfo = (struct ebt_table_info *)