Skip to content

Commit 331415f

Browse files
keesJiri Kosina
authored andcommitted
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 <[email protected]> Cc: [email protected] Reviewed-by: Benjamin Tissoires <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent b04c99e commit 331415f

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

drivers/hid/hid-core.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
801801
}
802802
EXPORT_SYMBOL_GPL(hid_parse_report);
803803

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+
804862
/**
805863
* hid_open_report - open a driver-specific device report
806864
*

include/linux/hid.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,10 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
756756
struct hid_device *hid_allocate_device(void);
757757
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
758758
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
759+
struct hid_report *hid_validate_values(struct hid_device *hid,
760+
unsigned int type, unsigned int id,
761+
unsigned int field_index,
762+
unsigned int report_counts);
759763
int hid_open_report(struct hid_device *device);
760764
int hid_check_keys_pressed(struct hid_device *hid);
761765
int hid_connect(struct hid_device *hid, unsigned int connect_mask);

0 commit comments

Comments
 (0)