Skip to content

Commit aea0aa9

Browse files
committed
Bounds-check reply_path in anonymous request handlers
The handleAnon*Req functions read a reply_path_len byte from the decrypted data and memcpy that many bytes into reply_path, without checking that the data buffer actually contains that many bytes. With a minimal-length packet, this reads up to 63 bytes of uninitialized stack memory. Add a data_len parameter to all three handlers and validate that the buffer contains enough bytes for the claimed reply_path_len before copying. Also guard the callers to ensure len > 5 before passing &data[5].
1 parent cdd3d5f commit aea0aa9

2 files changed

Lines changed: 18 additions & 15 deletions

File tree

examples/simple_repeater/MyMesh.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,14 @@ uint8_t MyMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* secr
144144
return 13; // reply length
145145
}
146146

147-
uint8_t MyMesh::handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data) {
147+
uint8_t MyMesh::handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data, size_t data_len) {
148148
if (anon_limiter.allow(rtc_clock.getCurrentTime())) {
149149
// request data has: {reply-path-len}{reply-path}
150+
if (data_len < 1) return 0;
150151
reply_path_len = *data & 63;
151152
reply_path_hash_size = (*data >> 6) + 1;
152153
data++;
153-
154+
if (1 + (size_t)reply_path_len * reply_path_hash_size > data_len) return 0;
154155
memcpy(reply_path, data, ((uint8_t)reply_path_len) * reply_path_hash_size);
155156
// data += (uint8_t)reply_path_len * reply_path_hash_size;
156157

@@ -163,13 +164,14 @@ uint8_t MyMesh::handleAnonRegionsReq(const mesh::Identity& sender, uint32_t send
163164
return 0;
164165
}
165166

166-
uint8_t MyMesh::handleAnonOwnerReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data) {
167+
uint8_t MyMesh::handleAnonOwnerReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data, size_t data_len) {
167168
if (anon_limiter.allow(rtc_clock.getCurrentTime())) {
168169
// request data has: {reply-path-len}{reply-path}
170+
if (data_len < 1) return 0;
169171
reply_path_len = *data & 63;
170172
reply_path_hash_size = (*data >> 6) + 1;
171173
data++;
172-
174+
if (1 + (size_t)reply_path_len * reply_path_hash_size > data_len) return 0;
173175
memcpy(reply_path, data, ((uint8_t)reply_path_len) * reply_path_hash_size);
174176
// data += (uint8_t)reply_path_len * reply_path_hash_size;
175177

@@ -183,13 +185,14 @@ uint8_t MyMesh::handleAnonOwnerReq(const mesh::Identity& sender, uint32_t sender
183185
return 0;
184186
}
185187

186-
uint8_t MyMesh::handleAnonClockReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data) {
188+
uint8_t MyMesh::handleAnonClockReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data, size_t data_len) {
187189
if (anon_limiter.allow(rtc_clock.getCurrentTime())) {
188190
// request data has: {reply-path-len}{reply-path}
191+
if (data_len < 1) return 0;
189192
reply_path_len = *data & 63;
190193
reply_path_hash_size = (*data >> 6) + 1;
191194
data++;
192-
195+
if (1 + (size_t)reply_path_len * reply_path_hash_size > data_len) return 0;
193196
memcpy(reply_path, data, ((uint8_t)reply_path_len) * reply_path_hash_size);
194197
// data += (uint8_t)reply_path_len * reply_path_hash_size;
195198

@@ -531,12 +534,12 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
531534
reply_path_len = -1;
532535
if (data[4] == 0 || data[4] >= ' ') { // is password, ie. a login request
533536
reply_len = handleLoginReq(sender, secret, timestamp, &data[4], packet->isRouteFlood());
534-
} else if (data[4] == ANON_REQ_TYPE_REGIONS && packet->isRouteDirect()) {
535-
reply_len = handleAnonRegionsReq(sender, timestamp, &data[5]);
536-
} else if (data[4] == ANON_REQ_TYPE_OWNER && packet->isRouteDirect()) {
537-
reply_len = handleAnonOwnerReq(sender, timestamp, &data[5]);
538-
} else if (data[4] == ANON_REQ_TYPE_BASIC && packet->isRouteDirect()) {
539-
reply_len = handleAnonClockReq(sender, timestamp, &data[5]);
537+
} else if (data[4] == ANON_REQ_TYPE_REGIONS && packet->isRouteDirect() && len > 5) {
538+
reply_len = handleAnonRegionsReq(sender, timestamp, &data[5], len - 5);
539+
} else if (data[4] == ANON_REQ_TYPE_OWNER && packet->isRouteDirect() && len > 5) {
540+
reply_len = handleAnonOwnerReq(sender, timestamp, &data[5], len - 5);
541+
} else if (data[4] == ANON_REQ_TYPE_BASIC && packet->isRouteDirect() && len > 5) {
542+
reply_len = handleAnonClockReq(sender, timestamp, &data[5], len - 5);
540543
} else {
541544
reply_len = 0; // unknown/invalid request type
542545
}

examples/simple_repeater/MyMesh.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
121121
void putNeighbour(const mesh::Identity& id, uint32_t timestamp, float snr);
122122
void sendNodeDiscoverReq();
123123
uint8_t handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data, bool is_flood);
124-
uint8_t handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data);
125-
uint8_t handleAnonOwnerReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data);
126-
uint8_t handleAnonClockReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data);
124+
uint8_t handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data, size_t data_len);
125+
uint8_t handleAnonOwnerReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data, size_t data_len);
126+
uint8_t handleAnonClockReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data, size_t data_len);
127127
int handleRequest(ClientInfo* sender, uint32_t sender_timestamp, uint8_t* payload, size_t payload_len);
128128
mesh::Packet* createSelfAdvert();
129129

0 commit comments

Comments
 (0)