From 1ffd74a6d4212a165763dc53e58a1b49b6fc5a98 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 24 May 2022 17:51:44 -0700 Subject: [PATCH] monitor/att: Fix parsing of notifications 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 | 12 ++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/monitor/att.c b/monitor/att.c index 3644436e4..df3e65057 100644 --- a/monitor/att.c +++ b/monitor/att.c @@ -742,6 +742,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); @@ -759,6 +760,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 951b411e0..1daeb69be 100644 --- a/monitor/l2cap.h +++ b/monitor/l2cap.h @@ -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; -- 2.47.3