lkml.org 
[lkml]   [2014]   [Feb]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[v2.6.34-stable 019/213] HID: provide a helper for validating hid reports
    Date
    From: Kees Cook <keescook@chromium.org>

    -------------------
    This is a commit scheduled for the next v2.6.34 longterm release.
    http://git.kernel.org/?p=linux/kernel/git/paulg/longterm-queue-2.6.34.git
    If you see a problem with using this for longterm, please comment.
    -------------------

    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>
    ---
    drivers/hid/hid-core.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++
    include/linux/hid.h | 4 ++++
    2 files changed, 62 insertions(+)

    diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
    index 195e366ea18d..b71ff324bec9 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
    *
    diff --git a/include/linux/hid.h b/include/linux/hid.h
    index 85e0942cfd76..cd7049a670bc 100644
    --- a/include/linux/hid.h
    +++ b/include/linux/hid.h
    @@ -694,6 +694,10 @@ void hid_output_report(struct hid_report *report, __u8 *data);
    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_check_keys_pressed(struct hid_device *hid);
    int hid_connect(struct hid_device *hid, unsigned int connect_mask);
    void hid_disconnect(struct hid_device *hid);
    --
    1.8.5.2


    \
     
     \ /
      Last update: 2014-02-06 04:01    [W:5.107 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site