broadband-modem-mbim: ensure message array contains valid PDUs
When reading SMS PDUs during initialization or upon a notification of a new PDU arriving, we should ensure that the array of messages returned is of type PDU, and also validate whether the array contains valid PDUs before processing them, otherwise we could be dereferencing invalid memory. This is trying to fix crashes like the following: 0x000059502b7ebaa2(ModemManager -mm-broadband-modem-mbim.c:7816)add_sms_part 0x000059502b7f5cf5(ModemManager -mm-broadband-modem-mbim.c:7849)sms_read_query_ready 0x000079e48edb36d3(libgio-2.0.so.0 -gtask.c:1230)g_task_return_now 0x000079e48edb2732(libgio-2.0.so.0 -gtask.c:1300)g_task_return 0x000079e48ee64ce5(libmbim-glib.so.4 -mbim-device.c:240)transaction_task_complete_and_free 0x000079e48ee6665f(libmbim-glib.so.4 -mbim-device.c:1017)data_available 0x000079e48ec65463(libglib-2.0.so.0 -gmain.c:3417)g_main_context_dispatch 0x000079e48ec6576e(libglib-2.0.so.0 -gmain.c:4211)g_main_context_iterate 0x000079e48ec659e2(libglib-2.0.so.0 -gmain.c:4411)g_main_loop_run 0x000059502b7796b1(ModemManager -main.c:217)main 0x000079e48e9f77a7(libc.so.6 + 0x000227a7)__libc_start_main 0x000059502b7794b9(ModemManager + 0x0005f4b9)_start 0x00007ffef825c6a7
This commit is contained in:
@@ -4893,18 +4893,21 @@ basic_connect_notification_provisioned_contexts (MMBroadbandModemMbim *self,
|
|||||||
mm_iface_modem_3gpp_profile_manager_updated (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self));
|
mm_iface_modem_3gpp_profile_manager_updated (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_sms_part (MMBroadbandModemMbim *self,
|
static gboolean process_pdu_messages (MMBroadbandModemMbim *self,
|
||||||
const MbimSmsPduReadRecord *pdu);
|
MbimSmsFormat format,
|
||||||
|
guint32 messages_count,
|
||||||
|
MbimSmsPduReadRecordArray *pdu_messages,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sms_notification_read_flash_sms (MMBroadbandModemMbim *self,
|
sms_notification_read_flash_sms (MMBroadbandModemMbim *self,
|
||||||
MbimDevice *device,
|
MbimDevice *device,
|
||||||
MbimMessage *notification)
|
MbimMessage *notification)
|
||||||
{
|
{
|
||||||
MbimSmsFormat format;
|
g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL;
|
||||||
guint32 messages_count;
|
g_autoptr(GError) error = NULL;
|
||||||
MbimSmsPduReadRecord **pdu_messages;
|
MbimSmsFormat format;
|
||||||
guint i;
|
guint32 messages_count;
|
||||||
|
|
||||||
if (!mbim_message_sms_read_notification_parse (
|
if (!mbim_message_sms_read_notification_parse (
|
||||||
notification,
|
notification,
|
||||||
@@ -4912,16 +4915,13 @@ sms_notification_read_flash_sms (MMBroadbandModemMbim *self,
|
|||||||
&messages_count,
|
&messages_count,
|
||||||
&pdu_messages,
|
&pdu_messages,
|
||||||
NULL, /* cdma_messages */
|
NULL, /* cdma_messages */
|
||||||
NULL) ||
|
&error) ||
|
||||||
/* Only PDUs */
|
!process_pdu_messages (self,
|
||||||
format != MBIM_SMS_FORMAT_PDU) {
|
format,
|
||||||
return;
|
messages_count,
|
||||||
}
|
pdu_messages,
|
||||||
|
&error))
|
||||||
for (i = 0; i < messages_count; i++)
|
mm_obj_dbg (self, "flash SMS message reading failed: %s", error->message);
|
||||||
add_sms_part (self, pdu_messages[i]);
|
|
||||||
|
|
||||||
mbim_sms_pdu_read_record_array_free (pdu_messages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -4960,50 +4960,43 @@ basic_connect_notification (MMBroadbandModemMbim *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
alert_sms_read_query_ready (MbimDevice *device,
|
alert_sms_read_query_ready (MbimDevice *device,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
MMBroadbandModemMbim *self)
|
MMBroadbandModemMbim *self) /* full ref */
|
||||||
{
|
{
|
||||||
MbimMessage *response;
|
g_autoptr(MbimMessage) response = NULL;
|
||||||
GError *error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
guint32 messages_count;
|
g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL;
|
||||||
MbimSmsPduReadRecord **pdu_messages;
|
MbimSmsFormat format;
|
||||||
|
guint32 messages_count;
|
||||||
|
|
||||||
response = mbim_device_command_finish (device, res, &error);
|
response = mbim_device_command_finish (device, res, &error);
|
||||||
if (response &&
|
if (!response ||
|
||||||
mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) &&
|
!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
|
||||||
mbim_message_sms_read_response_parse (
|
!mbim_message_sms_read_response_parse (
|
||||||
response,
|
response,
|
||||||
NULL,
|
&format,
|
||||||
&messages_count,
|
&messages_count,
|
||||||
&pdu_messages,
|
&pdu_messages,
|
||||||
NULL, /* cdma_messages */
|
NULL, /* cdma_messages */
|
||||||
&error)) {
|
&error) ||
|
||||||
guint i;
|
!process_pdu_messages (self,
|
||||||
|
format,
|
||||||
for (i = 0; i < messages_count; i++)
|
messages_count,
|
||||||
add_sms_part (self, pdu_messages[i]);
|
pdu_messages,
|
||||||
mbim_sms_pdu_read_record_array_free (pdu_messages);
|
&error))
|
||||||
}
|
mm_obj_dbg (self, "SMS message reading failed: %s", error->message);
|
||||||
|
|
||||||
if (error) {
|
|
||||||
mm_obj_dbg (self, "flash message reading failed: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response)
|
|
||||||
mbim_message_unref (response);
|
|
||||||
|
|
||||||
g_object_unref (self);
|
g_object_unref (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sms_notification_read_stored_sms (MMBroadbandModemMbim *self,
|
sms_notification_read_stored_sms (MMBroadbandModemMbim *self,
|
||||||
guint32 index)
|
guint32 index)
|
||||||
{
|
{
|
||||||
MMPortMbim *port;
|
g_autoptr(MbimMessage) message = NULL;
|
||||||
MbimDevice *device;
|
MMPortMbim *port;
|
||||||
MbimMessage *message;
|
MbimDevice *device;
|
||||||
|
|
||||||
port = mm_broadband_modem_mbim_peek_port_mbim (self);
|
port = mm_broadband_modem_mbim_peek_port_mbim (self);
|
||||||
if (!port)
|
if (!port)
|
||||||
@@ -5023,7 +5016,6 @@ sms_notification_read_stored_sms (MMBroadbandModemMbim *self,
|
|||||||
NULL,
|
NULL,
|
||||||
(GAsyncReadyCallback)alert_sms_read_query_ready,
|
(GAsyncReadyCallback)alert_sms_read_query_ready,
|
||||||
g_object_ref (self));
|
g_object_ref (self));
|
||||||
mbim_message_unref (message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -7843,19 +7835,19 @@ messaging_load_supported_storages (MMIfaceModemMessaging *self,
|
|||||||
/* Load initial SMS parts */
|
/* Load initial SMS parts */
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
load_initial_sms_parts_finish (MMIfaceModemMessaging *self,
|
load_initial_sms_parts_finish (MMIfaceModemMessaging *self,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
return g_task_propagate_boolean (G_TASK (res), error);
|
return g_task_propagate_boolean (G_TASK (res), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_sms_part (MMBroadbandModemMbim *self,
|
add_sms_part (MMBroadbandModemMbim *self,
|
||||||
const MbimSmsPduReadRecord *pdu)
|
const MbimSmsPduReadRecord *pdu)
|
||||||
{
|
{
|
||||||
MMSmsPart *part;
|
MMSmsPart *part;
|
||||||
GError *error = NULL;
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
part = mm_sms_part_3gpp_new_from_binary_pdu (pdu->message_index,
|
part = mm_sms_part_3gpp_new_from_binary_pdu (pdu->message_index,
|
||||||
pdu->pdu_data,
|
pdu->pdu_data,
|
||||||
@@ -7872,59 +7864,88 @@ add_sms_part (MMBroadbandModemMbim *self,
|
|||||||
} else {
|
} else {
|
||||||
/* Don't treat the error as critical */
|
/* Don't treat the error as critical */
|
||||||
mm_obj_dbg (self, "error parsing PDU (%d): %s",
|
mm_obj_dbg (self, "error parsing PDU (%d): %s",
|
||||||
pdu->message_index,
|
pdu->message_index, error->message);
|
||||||
error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
sms_read_query_ready (MbimDevice *device,
|
process_pdu_messages (MMBroadbandModemMbim *self,
|
||||||
GAsyncResult *res,
|
MbimSmsFormat format,
|
||||||
GTask *task)
|
guint32 messages_count,
|
||||||
|
MbimSmsPduReadRecordArray *pdu_messages,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MMBroadbandModemMbim *self;
|
guint i;
|
||||||
MbimMessage *response;
|
|
||||||
GError *error = NULL;
|
if (format != MBIM_SMS_FORMAT_PDU) {
|
||||||
guint32 messages_count;
|
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
||||||
MbimSmsPduReadRecord **pdu_messages;
|
"Ignoring SMS, unsupported format: '%s'",
|
||||||
|
mbim_sms_format_get_string (format));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdu_messages || !messages_count) {
|
||||||
|
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
|
||||||
|
"No SMS PDUs read");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mm_obj_dbg (self, "%u SMS PDUs reported", messages_count);
|
||||||
|
for (i = 0; i < messages_count; i++) {
|
||||||
|
if (pdu_messages[i]) {
|
||||||
|
mm_obj_dbg (self, "processing SMS PDU %u/%u...", i+1, messages_count);
|
||||||
|
add_sms_part (self, pdu_messages[i]);
|
||||||
|
} else
|
||||||
|
mm_obj_dbg (self, "ignoring invalid SMS PDU %u/%u...", i+1, messages_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sms_read_query_ready (MbimDevice *device,
|
||||||
|
GAsyncResult *res,
|
||||||
|
GTask *task)
|
||||||
|
{
|
||||||
|
MMBroadbandModemMbim *self;
|
||||||
|
GError *error = NULL;
|
||||||
|
MbimSmsFormat format;
|
||||||
|
guint32 messages_count;
|
||||||
|
g_autoptr(MbimMessage) response = NULL;
|
||||||
|
g_autoptr(MbimSmsPduReadRecordArray) pdu_messages = NULL;
|
||||||
|
|
||||||
self = g_task_get_source_object (task);
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
response = mbim_device_command_finish (device, res, &error);
|
response = mbim_device_command_finish (device, res, &error);
|
||||||
if (response &&
|
if (!response ||
|
||||||
mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) &&
|
!mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
|
||||||
mbim_message_sms_read_response_parse (
|
!mbim_message_sms_read_response_parse (
|
||||||
response,
|
response,
|
||||||
NULL,
|
&format,
|
||||||
&messages_count,
|
&messages_count,
|
||||||
&pdu_messages,
|
&pdu_messages,
|
||||||
NULL, /* cdma_messages */
|
NULL, /* cdma_messages */
|
||||||
&error)) {
|
&error) ||
|
||||||
guint i;
|
!process_pdu_messages (self,
|
||||||
|
format,
|
||||||
for (i = 0; i < messages_count; i++)
|
messages_count,
|
||||||
add_sms_part (self, pdu_messages[i]);
|
pdu_messages,
|
||||||
mbim_sms_pdu_read_record_array_free (pdu_messages);
|
&error))
|
||||||
g_task_return_boolean (task, TRUE);
|
|
||||||
} else
|
|
||||||
g_task_return_error (task, error);
|
g_task_return_error (task, error);
|
||||||
|
else
|
||||||
|
g_task_return_boolean (task, TRUE);
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
|
|
||||||
if (response)
|
|
||||||
mbim_message_unref (response);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
load_initial_sms_parts (MMIfaceModemMessaging *self,
|
load_initial_sms_parts (MMIfaceModemMessaging *self,
|
||||||
MMSmsStorage storage,
|
MMSmsStorage storage,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MbimDevice *device;
|
GTask *task;
|
||||||
MbimMessage *message;
|
MbimDevice *device;
|
||||||
GTask *task;
|
g_autoptr(MbimMessage) message = NULL;
|
||||||
|
|
||||||
if (!peek_device (self, &device, callback, user_data))
|
if (!peek_device (self, &device, callback, user_data))
|
||||||
return;
|
return;
|
||||||
@@ -7932,8 +7953,6 @@ load_initial_sms_parts (MMIfaceModemMessaging *self,
|
|||||||
g_assert (storage == MM_SMS_STORAGE_MT);
|
g_assert (storage == MM_SMS_STORAGE_MT);
|
||||||
|
|
||||||
task = g_task_new (self, NULL, callback, user_data);
|
task = g_task_new (self, NULL, callback, user_data);
|
||||||
|
|
||||||
mm_obj_dbg (self, "loading SMS parts...");
|
|
||||||
message = mbim_message_sms_read_query_new (MBIM_SMS_FORMAT_PDU,
|
message = mbim_message_sms_read_query_new (MBIM_SMS_FORMAT_PDU,
|
||||||
MBIM_SMS_FLAG_ALL,
|
MBIM_SMS_FLAG_ALL,
|
||||||
0, /* message index, unused */
|
0, /* message index, unused */
|
||||||
@@ -7944,7 +7963,6 @@ load_initial_sms_parts (MMIfaceModemMessaging *self,
|
|||||||
NULL,
|
NULL,
|
||||||
(GAsyncReadyCallback)sms_read_query_ready,
|
(GAsyncReadyCallback)sms_read_query_ready,
|
||||||
task);
|
task);
|
||||||
mbim_message_unref (message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
Reference in New Issue
Block a user