diff options
author | Kees Cook <keescook@chromium.org> | 2013-09-11 21:56:50 +0200 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2014-02-10 16:10:46 -0500 |
commit | 8e8f904083cd716a0244e89020b26a7346202a3b (patch) | |
tree | d7bfd3a4e874ef74a4c4b8a4bbf46182861c2569 /drivers | |
parent | 88b152e6f128b050bc15e16d55c003994be352ce (diff) |
HID: provide a helper for validating hid reports
commit 331415ff16a12147d57d5c953f3a961b7ede348b upstream.
Many drivers need to validate the characteristics of their HID report
during initialization to avoid misusing the reports. This adds a common
helper to perform validation of the report exisitng, the field existing,
and the expected number of values within the field.
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
[PG: in 2.6.34 it is err_hid(), original baseline had hid_err().]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hid/hid-core.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 195e366ea18..b71ff324bec 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -808,6 +808,64 @@ static __inline__ int search(__s32 *array, __s32 value, unsigned n) return -1; } +static const char * const hid_report_names[] = { + "HID_INPUT_REPORT", + "HID_OUTPUT_REPORT", + "HID_FEATURE_REPORT", +}; +/** + * hid_validate_values - validate existing device report's value indexes + * + * @device: hid device + * @type: which report type to examine + * @id: which report ID to examine (0 for first) + * @field_index: which report field to examine + * @report_counts: expected number of values + * + * Validate the number of values in a given field of a given report, after + * parsing. + */ +struct hid_report *hid_validate_values(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int field_index, + unsigned int report_counts) +{ + struct hid_report *report; + + if (type > HID_FEATURE_REPORT) { + err_hid("invalid HID report type %u\n", type); + return NULL; + } + + if (id >= HID_MAX_IDS) { + err_hid("invalid HID report id %u\n", id); + return NULL; + } + + /* + * Explicitly not using hid_get_report() here since it depends on + * ->numbered being checked, which may not always be the case when + * drivers go to access report values. + */ + report = hid->report_enum[type].report_id_hash[id]; + if (!report) { + err_hid("missing %s %u\n", hid_report_names[type], id); + return NULL; + } + if (report->maxfield <= field_index) { + err_hid("not enough fields in %s %u\n", + hid_report_names[type], id); + return NULL; + } + if (report->field[field_index]->report_count < report_counts) { + err_hid("not enough values in %s %u field %u\n", + hid_report_names[type], id, field_index); + return NULL; + } + return report; +} +EXPORT_SYMBOL_GPL(hid_validate_values); + /** * hid_match_report - check if driver's raw_event should be called * |