diff options
author | Kees Cook <keescook@chromium.org> | 2013-09-11 15:56:50 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-09-13 09:11:21 -0400 |
commit | 331415ff16a12147d57d5c953f3a961b7ede348b (patch) | |
tree | 79a497ffd03b720215e567c9c9862090fc76d0fa /drivers | |
parent | b04c99e3b845892d754ee8052d6324c39c4040de (diff) |
HID: provide a helper for validating hid reports
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>
Cc: stable@vger.kernel.org
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
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 ae88a97f976e..be52c06dbe30 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -801,6 +801,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) | |||
801 | } | 801 | } |
802 | EXPORT_SYMBOL_GPL(hid_parse_report); | 802 | EXPORT_SYMBOL_GPL(hid_parse_report); |
803 | 803 | ||
804 | static const char * const hid_report_names[] = { | ||
805 | "HID_INPUT_REPORT", | ||
806 | "HID_OUTPUT_REPORT", | ||
807 | "HID_FEATURE_REPORT", | ||
808 | }; | ||
809 | /** | ||
810 | * hid_validate_values - validate existing device report's value indexes | ||
811 | * | ||
812 | * @device: hid device | ||
813 | * @type: which report type to examine | ||
814 | * @id: which report ID to examine (0 for first) | ||
815 | * @field_index: which report field to examine | ||
816 | * @report_counts: expected number of values | ||
817 | * | ||
818 | * Validate the number of values in a given field of a given report, after | ||
819 | * parsing. | ||
820 | */ | ||
821 | struct hid_report *hid_validate_values(struct hid_device *hid, | ||
822 | unsigned int type, unsigned int id, | ||
823 | unsigned int field_index, | ||
824 | unsigned int report_counts) | ||
825 | { | ||
826 | struct hid_report *report; | ||
827 | |||
828 | if (type > HID_FEATURE_REPORT) { | ||
829 | hid_err(hid, "invalid HID report type %u\n", type); | ||
830 | return NULL; | ||
831 | } | ||
832 | |||
833 | if (id >= HID_MAX_IDS) { | ||
834 | hid_err(hid, "invalid HID report id %u\n", id); | ||
835 | return NULL; | ||
836 | } | ||
837 | |||
838 | /* | ||
839 | * Explicitly not using hid_get_report() here since it depends on | ||
840 | * ->numbered being checked, which may not always be the case when | ||
841 | * drivers go to access report values. | ||
842 | */ | ||
843 | report = hid->report_enum[type].report_id_hash[id]; | ||
844 | if (!report) { | ||
845 | hid_err(hid, "missing %s %u\n", hid_report_names[type], id); | ||
846 | return NULL; | ||
847 | } | ||
848 | if (report->maxfield <= field_index) { | ||
849 | hid_err(hid, "not enough fields in %s %u\n", | ||
850 | hid_report_names[type], id); | ||
851 | return NULL; | ||
852 | } | ||
853 | if (report->field[field_index]->report_count < report_counts) { | ||
854 | hid_err(hid, "not enough values in %s %u field %u\n", | ||
855 | hid_report_names[type], id, field_index); | ||
856 | return NULL; | ||
857 | } | ||
858 | return report; | ||
859 | } | ||
860 | EXPORT_SYMBOL_GPL(hid_validate_values); | ||
861 | |||
804 | /** | 862 | /** |
805 | * hid_open_report - open a driver-specific device report | 863 | * hid_open_report - open a driver-specific device report |
806 | * | 864 | * |