monitor/att: Fix parsing of notifications
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Wed, 25 May 2022 00:51:44 +0000 (17:51 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 15 May 2023 09:25:54 +0000 (14:55 +0530)
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.

Signed-off-by: Manika Shrivastava <manika.sh@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
monitor/att.c
monitor/l2cap.h

index ed50734..4de7fd3 100644 (file)
@@ -741,6 +741,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);
@@ -758,6 +759,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);
 }
 
index 951b411..1daeb69 100755 (executable)
@@ -31,8 +31,8 @@ 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)
 {
        if (frame != source) {
                frame->index   = source->index;
@@ -43,7 +43,15 @@ 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)
+{
+       l2cap_frame_clone(frame, source);
 
        frame->data = source->data + len;
        frame->size = source->size - len;