aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Rosenberg <drosenberg@vsecurity.com>2010-12-22 08:58:27 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-23 13:09:43 -0500
commitfdac1e0697356ac212259f2147aa60c72e334861 (patch)
treece479592fda66f81e1058c02b813dbc168958197
parent1bde5ac49398a064c753bb490535cfad89e99a5f (diff)
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>
-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,
2281 2281
2282 switch (optname) { 2282 switch (optname) {
2283 case IRLMP_ENUMDEVICES: 2283 case IRLMP_ENUMDEVICES:
2284
2285 /* Offset to first device entry */
2286 offset = sizeof(struct irda_device_list) -
2287 sizeof(struct irda_device_info);
2288
2289 if (len < offset) {
2290 err = -EINVAL;
2291 goto out;
2292 }
2293
2284 /* Ask lmp for the current discovery log */ 2294 /* Ask lmp for the current discovery log */
2285 discoveries = irlmp_get_discoveries(&list.len, self->mask.word, 2295 discoveries = irlmp_get_discoveries(&list.len, self->mask.word,
2286 self->nslots); 2296 self->nslots);
@@ -2291,15 +2301,9 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
2291 } 2301 }
2292 2302
2293 /* Write total list length back to client */ 2303 /* Write total list length back to client */
2294 if (copy_to_user(optval, &list, 2304 if (copy_to_user(optval, &list, offset))
2295 sizeof(struct irda_device_list) -
2296 sizeof(struct irda_device_info)))
2297 err = -EFAULT; 2305 err = -EFAULT;
2298 2306
2299 /* Offset to first device entry */
2300 offset = sizeof(struct irda_device_list) -
2301 sizeof(struct irda_device_info);
2302
2303 /* Copy the list itself - watch for overflow */ 2307 /* Copy the list itself - watch for overflow */
2304 if (list.len > 2048) { 2308 if (list.len > 2048) {
2305 err = -EINVAL; 2309 err = -EINVAL;