summaryrefslogtreecommitdiff
path: root/profiles/input
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2021-03-22 13:10:10 -0700
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2021-03-31 14:44:44 -0700
commit3f4039f43ba02418452edab7aab374e17dce6c8e (patch)
treef8d97d05e9318c7a382928fc084fb2acf1dc59d9 /profiles/input
parent09080c0022ba11ddf70b8b0c4f5119072017e04e (diff)
downloadbluez-3f4039f43ba02418452edab7aab374e17dce6c8e.tar.gz
hog-lib: Fix crash when receiving UHID_GET_REPORT
If UHID_GET_REPORT is received but a report cannot be found, etc, the would pass bt_hog as user_data instead of report to get_report_cb leading to a crash. Fixes https://github.com/bluez/bluez/issues/112
Diffstat (limited to 'profiles/input')
-rw-r--r--profiles/input/hog-lib.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/profiles/input/hog-lib.c b/profiles/input/hog-lib.c
index 6ac14e401..e5e3d3e7f 100644
--- a/profiles/input/hog-lib.c
+++ b/profiles/input/hog-lib.c
@@ -786,11 +786,9 @@ fail:
set_report_cb(err, NULL, 0, hog);
}
-static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
- gpointer user_data)
+static void report_reply(struct bt_hog *hog, uint8_t status, uint8_t id,
+ uint16_t len, const uint8_t *data)
{
- struct report *report = user_data;
- struct bt_hog *hog = report->hog;
struct uhid_event rsp;
int err;
@@ -800,6 +798,31 @@ static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
rsp.type = UHID_GET_REPORT_REPLY;
rsp.u.get_report_reply.id = hog->getrep_id;
+ if (status)
+ goto done;
+
+ if (hog->has_report_id && len > 0) {
+ rsp.u.get_report_reply.size = len + 1;
+ rsp.u.get_report_reply.data[0] = id;
+ memcpy(&rsp.u.get_report_reply.data[1], data, len);
+ } else {
+ rsp.u.get_report_reply.size = len;
+ memcpy(rsp.u.get_report_reply.data, data, len);
+ }
+
+done:
+ rsp.u.get_report_reply.err = status;
+ err = bt_uhid_send(hog->uhid, &rsp);
+ if (err < 0)
+ error("bt_uhid_send: %s", strerror(-err));
+}
+
+static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
+ gpointer user_data)
+{
+ struct report *report = user_data;
+ struct bt_hog *hog = report->hog;
+
if (status != 0) {
error("Error reading Report value: %s", att_ecode2str(status));
goto exit;
@@ -820,20 +843,8 @@ static void get_report_cb(guint8 status, const guint8 *pdu, guint16 len,
--len;
++pdu;
- if (hog->has_report_id && len > 0) {
- rsp.u.get_report_reply.size = len + 1;
- rsp.u.get_report_reply.data[0] = report->id;
- memcpy(&rsp.u.get_report_reply.data[1], pdu, len);
- } else {
- rsp.u.get_report_reply.size = len;
- memcpy(rsp.u.get_report_reply.data, pdu, len);
- }
-
exit:
- rsp.u.get_report_reply.err = status;
- err = bt_uhid_send(hog->uhid, &rsp);
- if (err < 0)
- error("bt_uhid_send: %s", strerror(-err));
+ report_reply(hog, status, report->id, len, pdu);
}
static void get_report(struct uhid_event *ev, void *user_data)
@@ -868,8 +879,8 @@ static void get_report(struct uhid_event *ev, void *user_data)
return;
fail:
- /* cancel the request on failure */
- get_report_cb(err, NULL, 0, hog);
+ /* reply with an error on failure */
+ report_reply(hog, err, 0, 0, NULL);
}
static bool get_descriptor_item_info(uint8_t *buf, ssize_t blen, ssize_t *len,