diag: dci: Add protection while de-initializing clients

Currently, while de-initializing dci clients, there is
a possibility to access stale entries. This patch fixes
this issue by adding proper protection mechanism.

CRs-Fixed: 960958 968445
Change-Id: I829c9497eeb356662a6531592c66108e615ce6e4
Signed-off-by: Mohit Aggarwal <maggarwa@codeaurora.org>
This commit is contained in:
Mohit Aggarwal 2016-01-25 16:23:45 +05:30 committed by David Keitel
parent 91212fa8e0
commit 30e8985110
2 changed files with 22 additions and 7 deletions

View file

@ -2816,13 +2816,14 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry)
if (!entry)
return DIAG_DCI_NOT_SUPPORTED;
token = entry->client_info.token;
mutex_lock(&driver->dci_mutex);
token = entry->client_info.token;
/*
* Remove the entry from the list before freeing the buffers
* to ensure that we don't have any invalid access.
*/
if (!list_empty(&entry->track))
list_del(&entry->track);
driver->num_dci_client--;
/*
@ -2852,6 +2853,7 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry)
req_entry = list_entry(start, struct dci_pkt_req_entry_t,
track);
if (req_entry->client_id == entry->client_info.client_id) {
if (!list_empty(&req_entry->track))
list_del(&req_entry->track);
kfree(req_entry);
}
@ -2861,6 +2863,7 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry)
mutex_lock(&entry->write_buf_mutex);
list_for_each_entry_safe(buf_entry, temp, &entry->list_write_buf,
buf_track) {
if (!list_empty(&buf_entry->buf_track))
list_del(&buf_entry->buf_track);
if (buf_entry->buf_type == DCI_BUF_SECONDARY) {
mutex_lock(&buf_entry->data_mutex);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -1968,12 +1968,18 @@ long diagchar_compat_ioctl(struct file *filp,
result = diag_ioctl_dci_reg(ioarg);
break;
case DIAG_IOCTL_DCI_DEINIT:
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;
}
dci_client = diag_dci_get_client_entry(client_id);
if (!dci_client)
if (!dci_client) {
mutex_unlock(&driver->dci_mutex);
return DIAG_DCI_NOT_SUPPORTED;
}
mutex_unlock(&driver->dci_mutex);
result = diag_dci_deinit_client(dci_client);
break;
case DIAG_IOCTL_DCI_SUPPORT:
@ -2071,12 +2077,18 @@ long diagchar_ioctl(struct file *filp,
result = diag_ioctl_dci_reg(ioarg);
break;
case DIAG_IOCTL_DCI_DEINIT:
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;
}
dci_client = diag_dci_get_client_entry(client_id);
if (!dci_client)
if (!dci_client) {
mutex_unlock(&driver->dci_mutex);
return DIAG_DCI_NOT_SUPPORTED;
}
mutex_unlock(&driver->dci_mutex);
result = diag_dci_deinit_client(dci_client);
break;
case DIAG_IOCTL_DCI_SUPPORT: