[PATCH BlueZ 2/2] monitor/att: Fix parsing of notifications

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

If there are multiple notifications in the same frame the callback may
alter it when using l2cap_frame_pull helpers, so instead this passes a
cloned frame with just the expected length so callbacks cannot alter
original frame.
---
 monitor/att.c   | 10 ++++++++++
 monitor/l2cap.h | 16 ++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/monitor/att.c b/monitor/att.c
index 27d4730fc..f4caca4ca 100644
--- a/monitor/att.c
+++ b/monitor/att.c
@@ -1547,6 +1547,7 @@ static void print_notify(const struct l2cap_frame *frame, uint16_t handle,
 {
 	struct gatt_db_attribute *attr;
 	struct gatt_handler *handler;
+	struct l2cap_frame clone;
 
 	print_handle(frame, handle, false);
 	print_hex_field("  Data", frame->data, len);
@@ -1564,6 +1565,15 @@ static void print_notify(const struct l2cap_frame *frame, uint16_t handle,
 	if (!handler)
 		return;
 
+	/* Use a clone if the callback is not expected to parse the whole
+	 * frame.
+	 */
+	if (len != frame->size) {
+		l2cap_frame_clone(&clone, frame);
+		clone.size = len;
+		frame = &clone;
+	}
+
 	handler->notify(frame);
 }
 
diff --git a/monitor/l2cap.h b/monitor/l2cap.h
index 19e03637a..38d40716b 100644
--- a/monitor/l2cap.h
+++ b/monitor/l2cap.h
@@ -31,11 +31,9 @@ void l2cap_frame_init(struct l2cap_frame *frame, uint16_t index, bool in,
 				uint16_t cid, uint16_t psm,
 				const void *data, uint16_t size);
 
-static inline void *l2cap_frame_pull(struct l2cap_frame *frame,
-				const struct l2cap_frame *source, uint16_t len)
+static inline void l2cap_frame_clone(struct l2cap_frame *frame,
+					const struct l2cap_frame *source)
 {
-	void *data;
-
 	if (frame != source) {
 		frame->index   = source->index;
 		frame->in      = source->in;
@@ -45,7 +43,17 @@ static inline void *l2cap_frame_pull(struct l2cap_frame *frame,
 		frame->psm     = source->psm;
 		frame->chan    = source->chan;
 		frame->mode    = source->mode;
+		frame->data    = source->data;
+		frame->size    = source->size;
 	}
+}
+
+static inline void *l2cap_frame_pull(struct l2cap_frame *frame,
+				const struct l2cap_frame *source, uint16_t len)
+{
+	void *data;
+
+	l2cap_frame_clone(frame, source);
 
 	if (source->size < len)
 		return NULL;
-- 
2.35.1




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux