Skip to content

Commit

Permalink
HID: provide a helper for validating hid reports
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kees Cook authored and Jiri Kosina committed Sep 13, 2013
1 parent b04c99e commit 331415f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
58 changes: 58 additions & 0 deletions drivers/hid/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,64 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size)
}
EXPORT_SYMBOL_GPL(hid_parse_report);

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) {
hid_err(hid, "invalid HID report type %u\n", type);
return NULL;
}

if (id >= HID_MAX_IDS) {
hid_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) {
hid_err(hid, "missing %s %u\n", hid_report_names[type], id);
return NULL;
}
if (report->maxfield <= field_index) {
hid_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) {
hid_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_open_report - open a driver-specific device report
*
Expand Down
4 changes: 4 additions & 0 deletions include/linux/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,10 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
struct hid_device *hid_allocate_device(void);
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
struct hid_report *hid_validate_values(struct hid_device *hid,
unsigned int type, unsigned int id,
unsigned int field_index,
unsigned int report_counts);
int hid_open_report(struct hid_device *device);
int hid_check_keys_pressed(struct hid_device *hid);
int hid_connect(struct hid_device *hid, unsigned int connect_mask);
Expand Down

0 comments on commit 331415f

Please sign in to comment.