mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-09-02 12:43:43 +00:00
fix(security): close OOB read in path-decoding callers (BLE + LoRa-anon)
Both mesh::Packet::writePath and ::copyPath did a raw memcpy of the
decoded hash_count*hash_size bytes from src to dest with no bound on
src. Two call sites used phone-supplied or LoRa-anon-supplied buffers
where the path_len byte was attacker-controlled:
- CompanionMesh CMD_SEND_CHANNEL_DATA accepted len>=4 and called
writePath with no src bound; a paired phone could leak up to ~65
bytes of syswq stack into the outgoing LoRa channel-data frame.
- RepeaterMesh handleAnonRegionsReq / handleAnonOwnerReq /
handleAnonClockReq read reply_path_len from an unauthenticated
LoRa anon-request payload and called copyPath without any src
bound. Any LoRa neighbor could leak repeater stack into the
reply path.
Hardened the API: both functions now require an explicit src_len
and reject (return 0) when the decoded byte count exceeds it.
Updated all 14 call sites across Packet/Mesh/Dispatcher/BaseChatMesh/
CompanionMesh/RepeaterMesh. Trusted callers (internal MAX_PATH_SIZE
buffers) pass MAX_PATH_SIZE; untrusted callers pass real remaining
length. Added len-5 plumbing through the anon-handler signatures.
CMD_SEND_CHANNEL_DATA also gained a local len>=5 + path_bytes
sanity check for early rejection.
This commit is contained in:
@@ -24,21 +24,24 @@ bool Packet::isValidPathLen(uint8_t path_len)
|
||||
return hash_count * hash_size <= MAX_PATH_SIZE;
|
||||
}
|
||||
|
||||
size_t Packet::writePath(uint8_t *dest, const uint8_t *src, uint8_t path_len)
|
||||
size_t Packet::writePath(uint8_t *dest, const uint8_t *src, size_t src_len, uint8_t path_len)
|
||||
{
|
||||
uint8_t hash_count = path_len & 63;
|
||||
uint8_t hash_size = (path_len >> 6) + 1;
|
||||
size_t len = hash_count * hash_size;
|
||||
if (len > MAX_PATH_SIZE) {
|
||||
return 0; // Error
|
||||
return 0; // Decoded path exceeds max
|
||||
}
|
||||
if (len > src_len) {
|
||||
return 0; // Would read past source buffer (caller-supplied bound)
|
||||
}
|
||||
memcpy(dest, src, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
uint8_t Packet::copyPath(uint8_t *dest, const uint8_t *src, uint8_t path_len)
|
||||
uint8_t Packet::copyPath(uint8_t *dest, const uint8_t *src, size_t src_len, uint8_t path_len)
|
||||
{
|
||||
size_t written = writePath(dest, src, path_len);
|
||||
size_t written = writePath(dest, src, src_len, path_len);
|
||||
return written > 0 ? path_len : 0;
|
||||
}
|
||||
|
||||
@@ -73,7 +76,8 @@ uint8_t Packet::writeTo(uint8_t dest[]) const
|
||||
memcpy(&dest[i], &transport_codes[1], 2); i += 2;
|
||||
}
|
||||
dest[i++] = path_len;
|
||||
i += writePath(&dest[i], path, path_len);
|
||||
/* Trusted source: Packet::path is MAX_PATH_SIZE-sized. */
|
||||
i += writePath(&dest[i], path, MAX_PATH_SIZE, path_len);
|
||||
memcpy(&dest[i], payload, payload_len); i += payload_len;
|
||||
return i;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user