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