Message ID | alpine.LRH.2.00.1003220850180.3232@tundra.namei.org |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
Le lundi 22 mars 2010 à 08:50 +1100, James Morris a écrit : > ---------- Forwarded message ---------- > Date: Sat, 20 Mar 2010 22:32:40 +0800 > From: wzt.wzt@gmail.com > To: linux-kernel@vger.kernel.org > Cc: netfilter-devel@vger.kernel.org, kaber@trash.net > Subject: [PATCH] Netfilter: Fix integer overflow in > net/ipv6/netfilter/ip6_tables.c > > The get.size field in the get_entries() interface is not bounded > correctly. The size is used to determine the total entry size. > The size is bounded, but can overflow and so the size checks may > not be sufficient to catch invalid size. Fix it by catching size > values that would cause overflows before calculating the size. > > Signed-off-by: Zhitong Wang <zhitong.wangzt@alibaba-inc.com> > Unless I am wrong, this patch is not necessary, since we do a bit later : if (get.size == private->size) ret = copy_entries_to_user(private->size, t, uptr->entrytable); else { duprintf("get_entries: I've got %u not %u!\n", private->size, get.size); ret = -EAGAIN; } So if get.size doesnt match private->size (kernel certified), we exit with an error. No calculation, no overflow involved. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4e7c719..6abd3d2 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1164,6 +1164,10 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len) } if (copy_from_user(&get, uptr, sizeof(get)) != 0) return -EFAULT; + + if (get.size >= INT_MAX / sizeof(struct ipt_get_entries)) + return -EINVAL; + if (*len != sizeof(struct ipt_get_entries) + get.size) { duprintf("get_entries: %u != %zu\n", *len, sizeof(get) + get.size); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 0b4557e..5185822 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1190,6 +1190,10 @@ get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len) } if (copy_from_user(&get, uptr, sizeof(get)) != 0) return -EFAULT; + + if (get.size >= INT_MAX / sizeof(struct ip6t_get_entries)) + return -EINVAL; + if (*len != sizeof(struct ip6t_get_entries) + get.size) { duprintf("get_entries: %u != %zu\n", *len, sizeof(get) + get.size);