summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2021-05-15 15:29:32 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-05-18 10:58:16 +0200
commit0e39fe0d85fec302d620365a04d98c974d7659ce (patch)
treeef7dc12453b173fb63a14ad01abf347cdfc4c72f
parentfd5aa84c5d92d94b9cc07350afc5e72a1f541347 (diff)
downloadlibmbim-0e39fe0d85fec302d620365a04d98c974d7659ce.tar.gz
libmbim-glib,message: fix overflows when checking required size
The message parsers will make sure the amount of data read from the message is within the boundaries of the message itself. But, while doing so, the parser will "compute" the required size based on message field offsets and also based on offsets and sizes reported within the message itself. If these fields are malformed and report very long offsets or sizes (e.g. 0xFFFFFFFF), adding those values into a target uint32 value will definitely overflow. Fix this by making the required size computations using a target uint64 value instead, so that adding up several uint32 values (even if some of them are e.g. 0xFFFFFFFF) won't overflow the operation. Fixes https://gitlab.freedesktop.org/mobile-broadband/libmbim/-/issues/16 (cherry picked from commit 9016e0d72d5c7da68eccdc8413e82240a27bfeef)
-rw-r--r--src/libmbim-glib/mbim-message.c160
1 files changed, 80 insertions, 80 deletions
diff --git a/src/libmbim-glib/mbim-message.c b/src/libmbim-glib/mbim-message.c
index fa08304..7c30dd2 100644
--- a/src/libmbim-glib/mbim-message.c
+++ b/src/libmbim-glib/mbim-message.c
@@ -168,17 +168,17 @@ _mbim_message_read_guint32 (const MbimMessage *self,
guint32 *value,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 information_buffer_offset;
g_assert (value);
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read 32bit unsigned integer (4 bytes) (%u < %u)",
+ "cannot read 32bit unsigned integer (4 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -197,7 +197,7 @@ _mbim_message_read_guint32_array (const MbimMessage *self,
guint32 **array,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint i;
guint32 information_buffer_offset;
@@ -210,11 +210,11 @@ _mbim_message_read_guint32_array (const MbimMessage *self,
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset_array_start + (4 * array_size);
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset_array_start + (4 * (guint64)array_size);
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read 32bit unsigned integer array (%u bytes) (%u < %u)",
- (4 * array_size), self->len, required_size);
+ "cannot read 32bit unsigned integer array (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")",
+ (4 * (guint64)array_size), self->len, (guint64)required_size);
return FALSE;
}
@@ -237,17 +237,17 @@ _mbim_message_read_guint64 (const MbimMessage *self,
guint64 *value,
GError **error)
{
- guint32 required_size;
- guint64 information_buffer_offset;
+ guint64 required_size;
+ guint32 information_buffer_offset;
g_assert (value != NULL);
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset + 8;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 8;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read 64bit unsigned integer (8 bytes) (%u < %u)",
+ "cannot read 64bit unsigned integer (8 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -266,7 +266,7 @@ _mbim_message_read_string (const MbimMessage *self,
gchar **str,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 offset;
guint32 size;
guint32 information_buffer_offset;
@@ -275,10 +275,10 @@ _mbim_message_read_string (const MbimMessage *self,
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset + 8;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 8;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read string offset and size (%u < %u)",
+ "cannot read string offset and size (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -296,10 +296,10 @@ _mbim_message_read_string (const MbimMessage *self,
return TRUE;
}
- required_size = information_buffer_offset + struct_start_offset + offset + size;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)struct_start_offset + (guint64)offset + (guint64)size;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read string data (%u bytes) (%u < %u)",
+ "cannot read string data (%u bytes) (%u < %" G_GUINT64_FORMAT ")",
size, self->len, required_size);
return FALSE;
}
@@ -392,16 +392,16 @@ _mbim_message_read_byte_array (const MbimMessage *self,
/* (a) Offset + Length pair in static buffer, data in variable buffer. */
if (has_offset && has_length) {
guint32 offset;
- guint32 required_size;
+ guint64 required_size;
g_assert (array_size != NULL);
g_assert (explicit_array_size == 0);
/* requires 8 bytes in relative offset */
- required_size = information_buffer_offset + relative_offset + 8;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 8;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array offset and size (%u < %u)",
+ "cannot read byte array offset and size (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -416,10 +416,10 @@ _mbim_message_read_byte_array (const MbimMessage *self,
(information_buffer_offset + relative_offset + 4)));
/* requires array_size bytes in offset */
- required_size = information_buffer_offset + struct_start_offset + offset + *array_size;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)struct_start_offset + (guint64)offset + (guint64)(*array_size);
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array data (%u bytes) (%u < %u)",
+ "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")",
*array_size, self->len, required_size);
return FALSE;
}
@@ -431,16 +431,16 @@ _mbim_message_read_byte_array (const MbimMessage *self,
/* (b) Just length in static buffer, data just afterwards. */
if (!has_offset && has_length) {
- guint32 required_size;
+ guint64 required_size;
g_assert (array_size != NULL);
g_assert (explicit_array_size == 0);
/* requires 4 bytes in relative offset */
- required_size = information_buffer_offset + relative_offset + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array size (%u < %u)",
+ "cannot read byte array size (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -451,10 +451,10 @@ _mbim_message_read_byte_array (const MbimMessage *self,
(information_buffer_offset + relative_offset)));
/* requires array_size bytes in after the array_size variable */
- required_size += *array_size;
- if (self->len < required_size) {
+ required_size += (guint64)(*array_size);
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array data (%u bytes) (%u < %u)",
+ "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")",
*array_size, self->len, required_size);
return FALSE;
}
@@ -466,16 +466,16 @@ _mbim_message_read_byte_array (const MbimMessage *self,
/* (c) Just offset in static buffer, length given in another variable, data in variable buffer. */
if (has_offset && !has_length) {
- guint32 required_size;
+ guint64 required_size;
guint32 offset;
g_assert (array_size == NULL);
/* requires 4 bytes in relative offset */
- required_size = information_buffer_offset + relative_offset + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array offset (%u < %u)",
+ "cannot read byte array offset (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -486,10 +486,10 @@ _mbim_message_read_byte_array (const MbimMessage *self,
(information_buffer_offset + relative_offset)));
/* requires explicit_array_size bytes in offset */
- required_size = information_buffer_offset + struct_start_offset + offset + explicit_array_size;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)struct_start_offset + (guint64)offset + (guint64)explicit_array_size;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array data (%u bytes) (%u < %u)",
+ "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")",
explicit_array_size, self->len, required_size);
return FALSE;
}
@@ -508,13 +508,13 @@ _mbim_message_read_byte_array (const MbimMessage *self,
* length */
*array_size = self->len - (information_buffer_offset + relative_offset);
} else {
- guint32 required_size;
+ guint64 required_size;
/* requires explicit_array_size bytes in offset */
- required_size = information_buffer_offset + relative_offset + explicit_array_size;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + (guint64)explicit_array_size;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read byte array data (%u bytes) (%u < %u)",
+ "cannot read byte array data (%u bytes) (%u < %" G_GUINT64_FORMAT ")",
explicit_array_size, self->len, required_size);
return FALSE;
}
@@ -534,17 +534,17 @@ _mbim_message_read_uuid (const MbimMessage *self,
const MbimUuid **uuid,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 information_buffer_offset;
g_assert (uuid);
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset + 16;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 16;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read UUID (16 bytes) (%u < %u)",
+ "cannot read UUID (16 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -561,7 +561,7 @@ _mbim_message_read_ipv4 (const MbimMessage *self,
const MbimIPv4 **ipv4,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 information_buffer_offset;
guint32 offset;
@@ -570,10 +570,10 @@ _mbim_message_read_ipv4 (const MbimMessage *self,
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
if (ref) {
- required_size = information_buffer_offset + relative_offset + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv4 offset (4 bytes) (%u < %u)",
+ "cannot read IPv4 offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -588,10 +588,10 @@ _mbim_message_read_ipv4 (const MbimMessage *self,
} else
offset = relative_offset;
- required_size = information_buffer_offset + offset + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)offset + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv4 (4 bytes) (%u < %u)",
+ "cannot read IPv4 (4 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -608,7 +608,7 @@ _mbim_message_read_ipv4_array (const MbimMessage *self,
MbimIPv4 **array,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 offset;
guint32 i;
guint32 information_buffer_offset;
@@ -622,10 +622,10 @@ _mbim_message_read_ipv4_array (const MbimMessage *self,
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset_array_start + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset_array_start + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv4 array offset (4 bytes) (%u < %u)",
+ "cannot read IPv4 array offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -635,11 +635,11 @@ _mbim_message_read_ipv4_array (const MbimMessage *self,
self->data,
(information_buffer_offset + relative_offset_array_start)));
- required_size = information_buffer_offset + offset + (4 * array_size);
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)offset + (4 * (guint64)array_size);
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv4 array data (%u bytes) (%u < %u)",
- (4 * array_size), self->len, required_size);
+ "cannot read IPv4 array data (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")",
+ (4 * (guint64)array_size), self->len, required_size);
return FALSE;
}
@@ -661,7 +661,7 @@ _mbim_message_read_ipv6 (const MbimMessage *self,
const MbimIPv6 **ipv6,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 information_buffer_offset;
guint32 offset;
@@ -670,10 +670,10 @@ _mbim_message_read_ipv6 (const MbimMessage *self,
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
if (ref) {
- required_size = information_buffer_offset + relative_offset + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv6 offset (4 bytes) (%u < %u)",
+ "cannot read IPv6 offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -688,10 +688,10 @@ _mbim_message_read_ipv6 (const MbimMessage *self,
} else
offset = relative_offset;
- required_size = information_buffer_offset + offset + 16;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)offset + 16;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv6 (16 bytes) (%u < %u)",
+ "cannot read IPv6 (16 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -708,7 +708,7 @@ _mbim_message_read_ipv6_array (const MbimMessage *self,
MbimIPv6 **array,
GError **error)
{
- guint32 required_size;
+ guint64 required_size;
guint32 offset;
guint32 i;
guint32 information_buffer_offset;
@@ -722,10 +722,10 @@ _mbim_message_read_ipv6_array (const MbimMessage *self,
information_buffer_offset = _mbim_message_get_information_buffer_offset (self);
- required_size = information_buffer_offset + relative_offset_array_start + 4;
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)relative_offset_array_start + 4;
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv6 array offset (4 bytes) (%u < %u)",
+ "cannot read IPv6 array offset (4 bytes) (%u < %" G_GUINT64_FORMAT ")",
self->len, required_size);
return FALSE;
}
@@ -735,11 +735,11 @@ _mbim_message_read_ipv6_array (const MbimMessage *self,
self->data,
(information_buffer_offset + relative_offset_array_start)));
- required_size = information_buffer_offset + offset + (16 * array_size);
- if (self->len < required_size) {
+ required_size = (guint64)information_buffer_offset + (guint64)offset + (16 * (guint64)array_size);
+ if ((guint64)self->len < required_size) {
g_set_error (error, MBIM_CORE_ERROR, MBIM_CORE_ERROR_INVALID_MESSAGE,
- "cannot read IPv6 array data (%u bytes) (%u < %u)",
- (16 * array_size), self->len, required_size);
+ "cannot read IPv6 array data (%" G_GUINT64_FORMAT " bytes) (%u < %" G_GUINT64_FORMAT ")",
+ (16 * (guint64)array_size), self->len, required_size);
return FALSE;
}