ChangeSet 1.1673.8.23, 2004/03/25 17:19:38-08:00, [EMAIL PROTECTED]

[PATCH] USB: usb hiddev stack usage patch

Patch below fixes some obscenely high stack uage;
struct hiddev_usage_ref_multi is well over 4Kb in size so really doesn't
belong on the stack.


 drivers/usb/input/hiddev.c |   80 +++++++++++++++++++++++++++------------------
 1 files changed, 49 insertions(+), 31 deletions(-)


diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c        Wed Apr 14 14:38:25 2004
+++ b/drivers/usb/input/hiddev.c        Wed Apr 14 14:38:25 2004
@@ -403,8 +403,8 @@
        struct hiddev_collection_info cinfo;
        struct hiddev_report_info rinfo;
        struct hiddev_field_info finfo;
-       struct hiddev_usage_ref_multi uref_multi;
-       struct hiddev_usage_ref *uref = &uref_multi.uref;
+       struct hiddev_usage_ref_multi *uref_multi=NULL;
+       struct hiddev_usage_ref *uref;
        struct hiddev_devinfo dinfo;
        struct hid_report *report;
        struct hid_field *field;
@@ -576,26 +576,31 @@
                return 0;
 
        case HIDIOCGUCODE:
-               if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
-                       return -EFAULT;
+               uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), 
GFP_KERNEL);
+               if (!uref_multi)
+                       return -ENOMEM;
+               uref = &uref_multi->uref;
+               if (copy_from_user(uref, (void *) arg, sizeof(*uref))) 
+                       goto fault;
 
                rinfo.report_type = uref->report_type;
                rinfo.report_id = uref->report_id;
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-                       return -EINVAL;
+                       goto inval;
 
                if (uref->field_index >= report->maxfield)
-                       return -EINVAL;
+                       goto inval;
 
                field = report->field[uref->field_index];
                if (uref->usage_index >= field->maxusage)
-                       return -EINVAL;
+                       goto inval;
 
                uref->usage_code = field->usage[uref->usage_index].hid;
 
                if (copy_to_user((void *) arg, uref, sizeof(*uref)))
-                       return -EFAULT;
+                       goto fault;
 
+               kfree(uref_multi);
                return 0;
 
        case HIDIOCGUSAGE:
@@ -603,42 +608,46 @@
        case HIDIOCGUSAGES:
        case HIDIOCSUSAGES:
        case HIDIOCGCOLLECTIONINDEX:
+               uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), 
GFP_KERNEL);
+               if (!uref_multi)
+                       return -ENOMEM;
+               uref = &uref_multi->uref;
                if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-                       if (copy_from_user(&uref_multi, (void *) arg, 
+                       if (copy_from_user(uref_multi, (void *) arg, 
                                           sizeof(uref_multi)))
-                               return -EFAULT;
+                               goto fault;
                } else {
                        if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
-                               return -EFAULT;
+                               goto fault;
                }
 
                if (cmd != HIDIOCGUSAGE && 
                    cmd != HIDIOCGUSAGES &&
                    uref->report_type == HID_REPORT_TYPE_INPUT)
-                       return -EINVAL;
+                       goto inval;
 
                if (uref->report_id == HID_REPORT_ID_UNKNOWN) {
                        field = hiddev_lookup_usage(hid, uref);
                        if (field == NULL)
-                               return -EINVAL;
+                               goto inval;
                } else {
                        rinfo.report_type = uref->report_type;
                        rinfo.report_id = uref->report_id;
                        if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-                               return -EINVAL;
+                               goto inval;
 
                        if (uref->field_index >= report->maxfield)
-                               return -EINVAL;
+                               goto inval;
 
                        field = report->field[uref->field_index];
                        if (uref->usage_index >= field->maxusage)
-                               return -EINVAL;
+                               goto inval;
 
                        if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-                               if (uref_multi.num_values >= HID_MAX_USAGES || 
+                               if (uref_multi->num_values >= HID_MAX_USAGES || 
                                    uref->usage_index >= field->maxusage || 
-                                  (uref->usage_index + uref_multi.num_values) >= 
field->maxusage)
-                                       return -EINVAL;
+                                  (uref->usage_index + uref_multi->num_values) >= 
field->maxusage)
+                                       goto inval;
                        }
                }
 
@@ -646,31 +655,40 @@
                        case HIDIOCGUSAGE:
                                uref->value = field->value[uref->usage_index];
                                if (copy_to_user((void *) arg, uref, sizeof(*uref)))
-                                       return -EFAULT;
-                               return 0;
+                                       goto fault;
+                               goto goodreturn;
 
                        case HIDIOCSUSAGE:
                                field->value[uref->usage_index] = uref->value;
-                               return 0;
+                               goto goodreturn;
 
                        case HIDIOCGCOLLECTIONINDEX:
+                               kfree(uref_multi);
                                return 
field->usage[uref->usage_index].collection_index;
                        case HIDIOCGUSAGES:
-                               for (i = 0; i < uref_multi.num_values; i++)
-                                       uref_multi.values[i] = 
+                               for (i = 0; i < uref_multi->num_values; i++)
+                                       uref_multi->values[i] = 
                                            field->value[uref->usage_index + i];
-                               if (copy_to_user((void *) arg, &uref_multi, 
-                                                sizeof(uref_multi)))
-                                       return -EFAULT;
-                               return 0;
+                               if (copy_to_user((void *) arg, uref_multi, 
+                                                sizeof(*uref_multi)))
+                                       goto fault;
+                               goto goodreturn;
                        case HIDIOCSUSAGES:
-                               for (i = 0; i < uref_multi.num_values; i++)
+                               for (i = 0; i < uref_multi->num_values; i++)
                                        field->value[uref->usage_index + i] = 
-                                           uref_multi.values[i];
-                               return 0;
+                                           uref_multi->values[i];
+                               goto goodreturn;
                }
 
+goodreturn:
+               kfree(uref_multi);
                return 0;
+fault:
+               kfree(uref_multi);
+               return -EFAULT;
+inval:         
+               kfree(uref_multi);
+               return -EINVAL;
 
        case HIDIOCGCOLLECTIONINFO:
                if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo)))



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id70&alloc_id638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to