aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Rosenberg <drosenberg@vsecurity.com>2010-12-22 18:58:27 -0500
committerWilly Tarreau <w@1wt.eu>2012-04-09 14:19:45 +0200
commita61eed7f742c596ad18f423be576563ac9d59c11 (patch)
tree6598fa2d6fa2557d4892d7c02dfb319970cdd190
parent632faa2d548dabaf55ac0bfcb21599da946f9936 (diff)
downloadlinux-2.4-a61eed7f742c596ad18f423be576563ac9d59c11.tar.gz
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> Cc: stable <stable@kernel.org> Signed-off-by: Willy Tarreau <w@1wt.eu>
-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 3d198b1f7dea6c..a029801e997516 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -2154,6 +2154,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,
self->nslots);
@@ -2163,15 +2173,9 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
err = 0;
/* 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)
{