summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-03-30 07:20:35 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-30 07:20:34 -0700
commit1743983a435e023b1ef27726e9943a61eaeb8633 (patch)
tree3a61bac477078e82e6af35f0532013398144fd83
parent74611ac55aa86ee954afb32e4fd981d12d3e0a37 (diff)
parent898a25d9ade3682252f994a474a20bdf87b67d89 (diff)
Merge "diag: Fix race condition while accessing mdlog session info"
-rw-r--r--drivers/char/diag/diagchar.h1
-rw-r--r--drivers/char/diag/diagchar_core.c20
-rw-r--r--drivers/char/diag/diagfwd_cntl.c6
3 files changed, 21 insertions, 6 deletions
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9d235b7abc58..dbbd5514cdcc 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -418,6 +418,7 @@ struct diag_md_session_t {
struct diag_mask_info *msg_mask;
struct diag_mask_info *log_mask;
struct diag_mask_info *event_mask;
+ struct thread_info *md_client_thread_info;
struct task_struct *task;
};
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 335064352789..009a2a4f90a2 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1237,11 +1237,10 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
mutex_unlock(&driver->md_session_lock);
return -ENOMEM;
}
-
new_session->peripheral_mask = 0;
new_session->pid = current->tgid;
new_session->task = current;
-
+ new_session->md_client_thread_info = current_thread_info();
new_session->log_mask = kzalloc(sizeof(struct diag_mask_info),
GFP_KERNEL);
if (!new_session->log_mask) {
@@ -1359,7 +1358,6 @@ static void diag_md_session_close(struct diag_md_session_t *session_info)
struct diag_md_session_t *diag_md_session_get_pid(int pid)
{
int i;
-
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] &&
driver->md_session_map[i]->pid == pid)
@@ -1475,7 +1473,10 @@ static int diag_md_session_check(int curr_mode, int req_mode,
* If this session owns all the requested peripherals, then
* call function to switch the modes/masks for the md_session
*/
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
+
if (!session_info) {
*change_mode = 1;
return 0;
@@ -1504,7 +1505,9 @@ static int diag_md_session_check(int curr_mode, int req_mode,
* owned by this md session
*/
change_mask = driver->md_session_mask & param->peripheral_mask;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (session_info) {
if ((session_info->peripheral_mask & change_mask)
@@ -1892,8 +1895,9 @@ static int diag_ioctl_hdlc_toggle(unsigned long ioarg)
{
uint8_t hdlc_support;
struct diag_md_session_t *session_info = NULL;
-
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (copy_from_user(&hdlc_support, (void __user *)ioarg,
sizeof(uint8_t)))
return -EFAULT;
@@ -2603,7 +2607,9 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
} else {
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
+ mutex_lock(&driver->md_session_lock);
info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
ret = diag_process_apps_pkt(user_space_data, len, info);
if (ret == 1)
diag_send_error_rsp((void *)(user_space_data), len,
@@ -2671,7 +2677,9 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
/* send masks to local processor now */
if (!remote_proc) {
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (!session_info) {
pr_err("diag:In %s request came from invalid md session pid:%d",
__func__, current->tgid);
@@ -2832,7 +2840,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
/* place holder for number of data field */
ret += sizeof(int);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
exit_stat = diag_md_copy_to_user(buf, &ret, count,
session_info);
goto exit;
@@ -2846,7 +2856,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE;
driver->data_ready[index] ^= HDLC_SUPPORT_TYPE;
COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
if (session_info)
COPY_USER_SPACE_OR_EXIT(buf+4,
session_info->hdlc_disabled,
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 62c8d0028af9..96f4a15a5d67 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, 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
@@ -124,7 +124,9 @@ void diag_notify_md_client(uint8_t peripheral, int data)
info.si_signo = SIGCONT;
if (driver->md_session_map[peripheral] &&
driver->md_session_map[peripheral]->task) {
- if (driver->md_session_map[peripheral]->pid ==
+ if (driver->md_session_map[peripheral]->
+ md_client_thread_info->task != NULL
+ && driver->md_session_map[peripheral]->pid ==
driver->md_session_map[peripheral]->task->tgid) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"md_session %d pid = %d, md_session %d task tgid = %d\n",