Summary
In utf8_trunc
in zephyr/lib/utils/utf8.c
, last_byte_p
can point to one byte before the string pointer if the string is empty.
Details
First of all, I'm not sure whether this is a bug of library function or calling site's function.
The function utf8_trunc
can be invoked by utf8_lcpy
.
utf8_lcpy
is called by multiple sites, and one example could be handle_generic_update
in zephyr/subsys/bluetooth/audio/has_client.c
.
There is no check for the input string, which could be empty string starting with null character, but name_len
is larger than 0:
pdu = net_buf_simple_pull_mem(buf, sizeof(*pdu));
...
name_len = buf->len + 1; /* + 1 byte for NULL terminator */
if (name_len > ARRAY_SIZE(name)) {
LOG_WRN("name is too long (%zu > %u)", buf->len, BT_HAS_PRESET_NAME_MAX);
name_len = ARRAY_SIZE(name);
}
utf8_lcpy(name, pdu->name, name_len); // pdu->name could be null while name_len is not zero
When it goes into utf8_lcpy
, it enters utf8_trunc
since n
is not 0:
char *utf8_lcpy(char *dst, const char *src, size_t n)
{
if (n > 0) {
strncpy(dst, src, n - 1);
dst[n - 1] = '\0';
if (n != 1) {
utf8_trunc(dst);
}
}
return dst;
}
This results in last_byte_p
pointing to utf8_str
- 1, because utf8_trunc
seems to assume that utf8_str
is not an empty string.
char *utf8_trunc(char *utf8_str)
{
char *last_byte_p = utf8_str + strlen(utf8_str) - 1;
uint8_t bytes_truncated;
char seq_start_byte;
if ((*last_byte_p & ASCII_CHAR) == *last_byte_p) {
/* Not part of an UTF8 sequence, return */
return utf8_str;
}
...
It directly leads to an out-of-bounds read in the subsequent code.
PoC
Send Read Preset response with PresetRecord name starting with a null character.
The name length can be any value other than 0.
Impact
Result of exploitation could lead to instability (i.e., crash) or denial of service attacks.
Patches
main: #74949
v3.6: #78286
For more information
If you have any questions or comments about this advisory:
embargo: 2024-09-22
Summary
In
utf8_trunc
inzephyr/lib/utils/utf8.c
,last_byte_p
can point to one byte before the string pointer if the string is empty.Details
First of all, I'm not sure whether this is a bug of library function or calling site's function.
The function
utf8_trunc
can be invoked byutf8_lcpy
.utf8_lcpy
is called by multiple sites, and one example could behandle_generic_update
inzephyr/subsys/bluetooth/audio/has_client.c
.There is no check for the input string, which could be empty string starting with null character, but
name_len
is larger than 0:When it goes into
utf8_lcpy
, it entersutf8_trunc
sincen
is not 0:This results in
last_byte_p
pointing toutf8_str
- 1, becauseutf8_trunc
seems to assume thatutf8_str
is not an empty string.It directly leads to an out-of-bounds read in the subsequent code.
PoC
Send Read Preset response with PresetRecord name starting with a null character.
The name length can be any value other than 0.
Impact
Result of exploitation could lead to instability (i.e., crash) or denial of service attacks.
Patches
main: #74949
v3.6: #78286
For more information
If you have any questions or comments about this advisory:
embargo: 2024-09-22