Browse Source

fix out_frame buffer overflow in companion radio response handlers

The onContactResponse handler copies peer response data into out_frame
(MAX_FRAME_SIZE + 1 bytes) without checking whether the data fits. A
peer response with len close to MAX_PACKET_PAYLOAD (184) writes up to
188 bytes into the 173-byte buffer, overflowing by 15 bytes.

This affects the status response, telemetry response, and binary
response code paths. A malicious peer can trigger the overflow by
sending a large response payload, corrupting the stack.

Cap each memcpy to the remaining space in out_frame before copying.
pull/1659/head
Wessel Nieboer 6 months ago
parent
commit
13d0f5e01d
No known key found for this signature in database GPG Key ID: 929C8E45E33B5FD2
  1. 18
      examples/companion_radio/MyMesh.cpp

18
examples/companion_radio/MyMesh.cpp

@ -719,8 +719,10 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
out_frame[i++] = 0; // reserved out_frame[i++] = 0; // reserved
memcpy(&out_frame[i], contact.id.pub_key, 6); memcpy(&out_frame[i], contact.id.pub_key, 6);
i += 6; // pub_key_prefix i += 6; // pub_key_prefix
memcpy(&out_frame[i], &data[4], len - 4); int copy_len = len - 4;
i += (len - 4); if (copy_len > MAX_FRAME_SIZE - i) copy_len = MAX_FRAME_SIZE - i;
memcpy(&out_frame[i], &data[4], copy_len);
i += copy_len;
_serial->writeFrame(out_frame, i); _serial->writeFrame(out_frame, i);
} else if (len > 4 && tag == pending_telemetry) { // check for matching response tag } else if (len > 4 && tag == pending_telemetry) { // check for matching response tag
pending_telemetry = 0; pending_telemetry = 0;
@ -730,8 +732,10 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
out_frame[i++] = 0; // reserved out_frame[i++] = 0; // reserved
memcpy(&out_frame[i], contact.id.pub_key, 6); memcpy(&out_frame[i], contact.id.pub_key, 6);
i += 6; // pub_key_prefix i += 6; // pub_key_prefix
memcpy(&out_frame[i], &data[4], len - 4); int copy_len = len - 4;
i += (len - 4); if (copy_len > MAX_FRAME_SIZE - i) copy_len = MAX_FRAME_SIZE - i;
memcpy(&out_frame[i], &data[4], copy_len);
i += copy_len;
_serial->writeFrame(out_frame, i); _serial->writeFrame(out_frame, i);
} else if (len > 4 && tag == pending_req) { // check for matching response tag } else if (len > 4 && tag == pending_req) { // check for matching response tag
pending_req = 0; pending_req = 0;
@ -741,8 +745,10 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
out_frame[i++] = 0; // reserved out_frame[i++] = 0; // reserved
memcpy(&out_frame[i], &tag, 4); // app needs to match this to RESP_CODE_SENT.tag memcpy(&out_frame[i], &tag, 4); // app needs to match this to RESP_CODE_SENT.tag
i += 4; i += 4;
memcpy(&out_frame[i], &data[4], len - 4); int copy_len = len - 4;
i += (len - 4); if (copy_len > MAX_FRAME_SIZE - i) copy_len = MAX_FRAME_SIZE - i;
memcpy(&out_frame[i], &data[4], copy_len);
i += copy_len;
_serial->writeFrame(out_frame, i); _serial->writeFrame(out_frame, i);
} }
} }

Loading…
Cancel
Save