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