summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDan Rosenberg <drosenberg@vsecurity.com>2010-12-22 13:58:27 +0000
committerDavid S. Miller <davem@davemloft.net>2010-12-23 10:09:43 -0800
commitfdac1e0697356ac212259f2147aa60c72e334861 (patch)
treece479592fda66f81e1058c02b813dbc168958197 /net
parent1bde5ac49398a064c753bb490535cfad89e99a5f (diff)
downloadlinux-fdac1e0697356ac212259f2147aa60c72e334861.tar.gz
linux-fdac1e0697356ac212259f2147aa60c72e334861.tar.bz2
linux-fdac1e0697356ac212259f2147aa60c72e334861.zip
irda: prevent integer underflow in IRLMP_ENUMDEVICES
If the user-provided len is less than the expected offset, the IRLMP_ENUMDEVICES getsockopt will do a copy_to_user() with a very large size value. While this isn't be a security issue on x86 because it will get caught by the access_ok() check, it may leak large amounts of kernel heap on other architectures. In any event, this patch fixes it. Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/irda/af_irda.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 7f097989cde2..5007541b6478 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2281,6 +2281,16 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
switch (optname) {
case IRLMP_ENUMDEVICES:
+
+ /* Offset to first device entry */
+ offset = sizeof(struct irda_device_list) -
+ sizeof(struct irda_device_info);
+
+ if (len < offset) {
+ err = -EINVAL;
+ goto out;
+ }
+
/* Ask lmp for the current discovery log */
discoveries = irlmp_get_discoveries(&list.len, self->mask.word,
self->nslots);
@@ -2291,15 +2301,9 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
}
/* Write total list length back to client */
- if (copy_to_user(optval, &list,
- sizeof(struct irda_device_list) -
- sizeof(struct irda_device_info)))
+ if (copy_to_user(optval, &list, offset))
err = -EFAULT;
- /* Offset to first device entry */
- offset = sizeof(struct irda_device_list) -
- sizeof(struct irda_device_info);
-
/* Copy the list itself - watch for overflow */
if (list.len > 2048) {
err = -EINVAL;