From af4cf780a234f39ab3e6a1f14bb404b909e1275f Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Wed, 18 May 2016 16:48:36 +0530 Subject: [PATCH] diag: Fix for possible dci stale entries This patch provides the protection to dci client entries from corruption. CRs-Fixed: 984942 992683 Change-Id: Ifcd9f14dc03d9e42a31b3e126839489881e98303 Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_dci.c | 6 ++--- drivers/char/diag/diagchar_core.c | 44 ++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 2a9ad0d95deb..2b606df5771c 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -1392,6 +1392,7 @@ void diag_dci_channel_open_work(struct work_struct *work) * which log entries in the cumulative logs that need * to be updated on the peripheral. */ + mutex_lock(&driver->dci_mutex); list_for_each_safe(start, temp, &driver->dci_client_list) { entry = list_entry(start, struct diag_dci_client_tbl, track); if (entry->client_info.token != DCI_LOCAL_PROC) @@ -1403,6 +1404,7 @@ void diag_dci_channel_open_work(struct work_struct *work) client_log_mask_ptr += 514; } } + mutex_unlock(&driver->dci_mutex); mutex_lock(&dci_log_mask_mutex); /* Update the appropriate dirty bits in the cumulative mask */ @@ -2888,8 +2890,6 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry) if (!entry) return DIAG_DCI_NOT_SUPPORTED; - mutex_lock(&driver->dci_mutex); - token = entry->client_info.token; /* * Remove the entry from the list before freeing the buffers @@ -3000,8 +3000,6 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry) } queue_work(driver->diag_real_time_wq, &driver->diag_real_time_work); - mutex_unlock(&driver->dci_mutex); - return DIAG_DCI_NO_ERROR; } diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index c6e57f36fe3b..edc104acb777 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -421,9 +421,11 @@ static int diag_remove_client_entry(struct file *file) * This will specially help in case of ungraceful exit of any DCI client * This call will remove any pending registrations of such client */ + mutex_lock(&driver->dci_mutex); dci_entry = dci_lookup_client_entry_pid(current->tgid); if (dci_entry) diag_dci_deinit_client(dci_entry); + mutex_unlock(&driver->dci_mutex); diag_close_logging_process(current->tgid); @@ -1982,32 +1984,46 @@ long diagchar_compat_ioctl(struct file *filp, mutex_unlock(&driver->dci_mutex); return DIAG_DCI_NOT_SUPPORTED; } - mutex_unlock(&driver->dci_mutex); result = diag_dci_deinit_client(dci_client); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_SUPPORT: result = diag_ioctl_dci_support(ioarg); break; case DIAG_IOCTL_DCI_HEALTH_STATS: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_dci_health_stats(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_LOG_STATUS: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_dci_log_status(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_EVENT_STATUS: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_dci_event_status(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_CLEAR_LOGS: + mutex_lock(&driver->dci_mutex); if (copy_from_user((void *)&client_id, (void __user *)ioarg, - sizeof(int))) + sizeof(int))) { + mutex_unlock(&driver->dci_mutex); return -EFAULT; + } result = diag_dci_clear_log_mask(client_id); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_CLEAR_EVENTS: + mutex_lock(&driver->dci_mutex); if (copy_from_user(&client_id, (void __user *)ioarg, - sizeof(int))) + sizeof(int))) { + mutex_unlock(&driver->dci_mutex); return -EFAULT; + } result = diag_dci_clear_event_mask(client_id); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_LSM_DEINIT: result = diag_ioctl_lsm_deinit(); @@ -2029,7 +2045,9 @@ long diagchar_compat_ioctl(struct file *filp, result = 1; break; case DIAG_IOCTL_VOTE_REAL_TIME: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_vote_real_time(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_GET_REAL_TIME: result = diag_ioctl_get_real_time(ioarg); @@ -2091,32 +2109,44 @@ long diagchar_ioctl(struct file *filp, mutex_unlock(&driver->dci_mutex); return DIAG_DCI_NOT_SUPPORTED; } - mutex_unlock(&driver->dci_mutex); result = diag_dci_deinit_client(dci_client); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_SUPPORT: result = diag_ioctl_dci_support(ioarg); break; case DIAG_IOCTL_DCI_HEALTH_STATS: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_dci_health_stats(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_LOG_STATUS: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_dci_log_status(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_EVENT_STATUS: result = diag_ioctl_dci_event_status(ioarg); break; case DIAG_IOCTL_DCI_CLEAR_LOGS: + mutex_lock(&driver->dci_mutex); if (copy_from_user((void *)&client_id, (void __user *)ioarg, - sizeof(int))) + sizeof(int))) { + mutex_unlock(&driver->dci_mutex); return -EFAULT; + } result = diag_dci_clear_log_mask(client_id); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_DCI_CLEAR_EVENTS: + mutex_lock(&driver->dci_mutex); if (copy_from_user(&client_id, (void __user *)ioarg, - sizeof(int))) + sizeof(int))) { + mutex_unlock(&driver->dci_mutex); return -EFAULT; + } result = diag_dci_clear_event_mask(client_id); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_LSM_DEINIT: result = diag_ioctl_lsm_deinit(); @@ -2138,7 +2168,9 @@ long diagchar_ioctl(struct file *filp, result = 1; break; case DIAG_IOCTL_VOTE_REAL_TIME: + mutex_lock(&driver->dci_mutex); result = diag_ioctl_vote_real_time(ioarg); + mutex_unlock(&driver->dci_mutex); break; case DIAG_IOCTL_GET_REAL_TIME: result = diag_ioctl_get_real_time(ioarg);