Skip to contentSkip to conversation

hog: fix invalid type cast in discover_descriptor_cb

PATCH In review Founder Fang 2 participants 3 messages Sep 16, 2015 – Sep 17, 2015 Bluetooth drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 hog: fix invalid type cast in discover_descriptor_cb

the argument user_data for discover_descriptor_cb can be either a pointer to report or a pointer to hogdev, it is differentiate by uuid. when uuid is GATT_EXTERNAL_REPORT_REFERENCE and actual user_data is a pointer to a report, the user_data is wrongly cast to hogdev, hence cause memory corruption.
create another function discover_descriptor_no_report_cb, avoid type cast based on uuid fix the problem.

---
 profiles/input/hog.c | 43 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)
profiles/input/hog.c +39 -4
index e006add..bea8637 100644
@@ -219,7 +219,6 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
 								void *user_data)
 {
 	struct report *report;
-	struct hog_device *hogdev;
 	GAttrib *attrib = NULL;
 
 	if (status != 0) {
@@ -244,6 +243,41 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
 						report_reference_cb, report);
 			break;
 		case GATT_EXTERNAL_REPORT_REFERENCE:
+			break;
+		}
+	}
+}
+
+static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
+							gpointer user_data)
+{
+	if (start > end)
+		return;
+
+	gatt_discover_desc(attrib, start, end, NULL,
+					discover_descriptor_cb, user_data);
+}
+
+static void discover_descriptor_no_report_cb(uint8_t status, GSList *descs,
+								void *user_data)
+{
+	struct hog_device *hogdev;
+	GAttrib *attrib = NULL;
+
+	if (status != 0) {
+		error("Discover all descriptors failed: %s",
+							att_ecode2str(status));
+		return;
+	}
+
+	for ( ; descs; descs = descs->next) {
+		struct gatt_desc *desc = descs->data;
+
+		switch (desc->uuid16) {
+		case GATT_CLIENT_CHARAC_CFG_UUID:
+		case GATT_REPORT_REFERENCE:
+			break;
+		case GATT_EXTERNAL_REPORT_REFERENCE:
 			hogdev = user_data;
 			attrib = hogdev->attrib;
 			gatt_read_char(attrib, desc->handle,
@@ -253,16 +287,17 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
 	}
 }
 
-static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
+static void discover_descriptor_no_report(GAttrib *attrib, uint16_t start, uint16_t end,
 							gpointer user_data)
 {
 	if (start > end)
 		return;
 
 	gatt_discover_desc(attrib, start, end, NULL,
-					discover_descriptor_cb, user_data);
+					discover_descriptor_no_report_cb, user_data);
 }
 
+
 static void external_service_char_cb(uint8_t status, GSList *chars,
 								void *user_data)
 {
@@ -824,7 +859,7 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
 			DBG("HoG discovering report map");
 			gatt_read_char(hogdev->attrib, chr->value_handle,
 						report_map_read_cb, hogdev);
-			discover_descriptor(hogdev->attrib, start, end, hogdev);
+			discover_descriptor_no_report(hogdev->attrib, start, end, hogdev);
 		} else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
 			info_handle = chr->value_handle;
 		else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
Signature · 1 line
1.9.1
#1 lore raw

Hi,

Quoted 95 lines · Founder Fang

the argument user_data for discover_descriptor_cb can be either a pointer to report or a pointer to hogdev, it is differentiate by uuid. when uuid is GATT_EXTERNAL_REPORT_REFERENCE and actual user_data is a pointer to a report, the user_data is wrongly cast to hogdev, hence cause memory corruption.
create another function discover_descriptor_no_report_cb, avoid type cast based on uuid fix the problem.

---
 profiles/input/hog.c | 43 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)
profiles/input/hog.c +39 -5
index e006add..bea8637 100644
@@ -219,7 +219,6 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
                                                                void *user_data)
 {
        struct report *report;
-       struct hog_device *hogdev;
        GAttrib *attrib = NULL;
 
        if (status != 0) {
@@ -244,6 +243,41 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
                                                report_reference_cb, report);
                        break;
                case GATT_EXTERNAL_REPORT_REFERENCE:
+                       break;
+               }
+       }
+}
+
+static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
+                                                       gpointer user_data)
+{
+       if (start > end)
+               return;
+
+       gatt_discover_desc(attrib, start, end, NULL,
+                                       discover_descriptor_cb, user_data);
+}
+
+static void discover_descriptor_no_report_cb(uint8_t status, GSList *descs,
+                                                               void *user_data)
+{
+       struct hog_device *hogdev;
+       GAttrib *attrib = NULL;
+
+       if (status != 0) {
+               error("Discover all descriptors failed: %s",
+                                                       att_ecode2str(status));
+               return;
+       }
+
+       for ( ; descs; descs = descs->next) {
+               struct gatt_desc *desc = descs->data;
+
+               switch (desc->uuid16) {
+               case GATT_CLIENT_CHARAC_CFG_UUID:
+               case GATT_REPORT_REFERENCE:
+                       break;
+               case GATT_EXTERNAL_REPORT_REFERENCE:
                        hogdev = user_data;
                        attrib = hogdev->attrib;
                        gatt_read_char(attrib, desc->handle,
@@ -253,16 +287,17 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
        }
 }
 
-static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
+static void discover_descriptor_no_report(GAttrib *attrib, uint16_t start, uint16_t end,
                                                        gpointer user_data)
 {
        if (start > end)
                return;
 
        gatt_discover_desc(attrib, start, end, NULL,
-                                       discover_descriptor_cb, user_data);
+                                       discover_descriptor_no_report_cb, user_data);
 }
 
+
 static void external_service_char_cb(uint8_t status, GSList *chars,
                                                                void *user_data)
 {
@@ -824,7 +859,7 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
                        DBG("HoG discovering report map");
                        gatt_read_char(hogdev->attrib, chr->value_handle,
                                                report_map_read_cb, hogdev);
-                       discover_descriptor(hogdev->attrib, start, end, hogdev);
+                       discover_descriptor_no_report(hogdev->attrib, start, end, hogdev);
                } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
                        info_handle = chr->value_handle;
                else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
--
Quoted 1 line

1.9.1

Ive made a similar fix to android in 47a337152d342a37e3021dab0b18487b185e8b76, we should probably port that one to profile/input since in future we are planning to use to share the same implementation.

Signature · 1 line
Luiz Augusto von Dentz
#2 lore raw

Hi,

Quoted 96 lines · Luiz Augusto von Dentz

Hi,

Quoted 93 lines · Founder Fang

the argument user_data for discover_descriptor_cb can be either a pointer to report or a pointer to hogdev, it is differentiate by uuid. when uuid is GATT_EXTERNAL_REPORT_REFERENCE and actual user_data is a pointer to a report, the user_data is wrongly cast to hogdev, hence cause memory corruption.
create another function discover_descriptor_no_report_cb, avoid type cast based on uuid fix the problem.

---
 profiles/input/hog.c | 43 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)
profiles/input/hog.c +39 -4
index e006add..bea8637 100644
@@ -219,7 +219,6 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
                                                                void *user_data)
 {
        struct report *report;
-       struct hog_device *hogdev;
        GAttrib *attrib = NULL;
 
        if (status != 0) {
@@ -244,6 +243,41 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
                                                report_reference_cb, report);
                        break;
                case GATT_EXTERNAL_REPORT_REFERENCE:
+                       break;
+               }
+       }
+}
+
+static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
+                                                       gpointer user_data)
+{
+       if (start > end)
+               return;
+
+       gatt_discover_desc(attrib, start, end, NULL,
+                                       discover_descriptor_cb, user_data);
+}
+
+static void discover_descriptor_no_report_cb(uint8_t status, GSList *descs,
+                                                               void *user_data)
+{
+       struct hog_device *hogdev;
+       GAttrib *attrib = NULL;
+
+       if (status != 0) {
+               error("Discover all descriptors failed: %s",
+                                                       att_ecode2str(status));
+               return;
+       }
+
+       for ( ; descs; descs = descs->next) {
+               struct gatt_desc *desc = descs->data;
+
+               switch (desc->uuid16) {
+               case GATT_CLIENT_CHARAC_CFG_UUID:
+               case GATT_REPORT_REFERENCE:
+                       break;
+               case GATT_EXTERNAL_REPORT_REFERENCE:
                        hogdev = user_data;
                        attrib = hogdev->attrib;
                        gatt_read_char(attrib, desc->handle,
@@ -253,16 +287,17 @@ static void discover_descriptor_cb(uint8_t status, GSList *descs,
        }
 }
 
-static void discover_descriptor(GAttrib *attrib, uint16_t start, uint16_t end,
+static void discover_descriptor_no_report(GAttrib *attrib, uint16_t start, uint16_t end,
                                                        gpointer user_data)
 {
        if (start > end)
                return;
 
        gatt_discover_desc(attrib, start, end, NULL,
-                                       discover_descriptor_cb, user_data);
+                                       discover_descriptor_no_report_cb, user_data);
 }
 
+
 static void external_service_char_cb(uint8_t status, GSList *chars,
                                                                void *user_data)
 {
@@ -824,7 +859,7 @@ static void char_discovered_cb(uint8_t status, GSList *chars, void *user_data)
                        DBG("HoG discovering report map");
                        gatt_read_char(hogdev->attrib, chr->value_handle,
                                                report_map_read_cb, hogdev);
-                       discover_descriptor(hogdev->attrib, start, end, hogdev);
+                       discover_descriptor_no_report(hogdev->attrib, start, end, hogdev);
                } else if (bt_uuid_cmp(&uuid, &info_uuid) == 0)
                        info_handle = chr->value_handle;
Quoted 12 lines
Quoted 3 lines
profiles/input/hog.c +0 -1
                else if (bt_uuid_cmp(&uuid, &proto_mode_uuid) == 0)
--

1.9.1

Ive made a similar fix to android in 47a337152d342a37e3021dab0b18487b185e8b76, we should probably port that one to profile/input since in future we are planning to use to share the same implementation.

Signature · 1 line
Luiz Augusto von Dentz

any plan to merge android/hog.c and profile/input/hog.c? i notice
recently there are important patches apply to profile/input/hog.c but not in android/hog.c, eg. 8e73a002848a6a2abcbd436ea8aac089320c13f2

Founder Fang