Merge "diag: Fix possible use-after-free issue for mdlog session info"
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index f510c14..223bc03 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, 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
@@ -536,8 +536,7 @@
}
static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int write_len = 0;
@@ -545,23 +544,30 @@
struct diag_msg_ssid_query_t rsp;
struct diag_ssid_range_t ssid_range;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- if (!diag_apps_responds())
+ if (!diag_apps_responds()) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
mutex_lock(&driver->msg_mask_lock);
rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
@@ -583,12 +589,12 @@
write_len += sizeof(ssid_range);
}
mutex_unlock(&driver->msg_mask_lock);
+ mutex_unlock(&driver->md_session_lock);
return write_len;
}
static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i = 0;
int write_len = 0;
@@ -641,8 +647,7 @@
}
static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int write_len = 0;
@@ -651,6 +656,10 @@
struct diag_build_mask_req_t *req = NULL;
struct diag_msg_build_mask_t rsp;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -658,15 +667,19 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- if (!diag_apps_responds())
+ if (!diag_apps_responds()) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
mutex_lock(&driver->msg_mask_lock);
req = (struct diag_build_mask_req_t *)src_buf;
@@ -681,6 +694,7 @@
pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
__func__, mask->ptr);
mutex_unlock(&driver->msg_mask_lock);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -700,12 +714,12 @@
memcpy(dest_buf, &rsp, sizeof(rsp));
write_len += sizeof(rsp);
mutex_unlock(&driver->msg_mask_lock);
+ mutex_unlock(&driver->md_session_lock);
return write_len;
}
static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
uint32_t mask_size = 0, offset = 0;
uint32_t *temp = NULL;
@@ -716,6 +730,10 @@
struct diag_msg_build_mask_t rsp;
struct diag_mask_info *mask_info = NULL;
struct diag_msg_mask_t *mask_next = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -723,11 +741,13 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -740,6 +760,7 @@
__func__, mask->ptr);
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -782,6 +803,7 @@
mutex_unlock(&mask->lock);
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
return -ENOMEM;
}
mask->ptr = temp;
@@ -802,6 +824,7 @@
}
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(MSG_MASKS_TYPE);
@@ -842,8 +865,7 @@
}
static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i, write_len = 0, peripheral;
int header_len = sizeof(struct diag_msg_config_rsp_t);
@@ -851,6 +873,10 @@
struct diag_msg_config_rsp_t *req = NULL;
struct diag_msg_mask_t *mask = NULL;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &msg_mask : info->msg_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -858,11 +884,13 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -877,6 +905,7 @@
__func__, mask->ptr);
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
@@ -889,7 +918,7 @@
}
mutex_unlock(&driver->msg_mask_lock);
mutex_unlock(&mask_info->lock);
-
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(MSG_MASKS_TYPE);
@@ -923,8 +952,7 @@
}
static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int write_len = 0;
uint32_t mask_size;
@@ -959,26 +987,30 @@
}
static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i, write_len = 0, mask_len = 0, peripheral;
int header_len = sizeof(struct diag_event_mask_config_t);
struct diag_event_mask_config_t rsp;
struct diag_event_mask_config_t *req;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
req = (struct diag_event_mask_config_t *)src_buf;
@@ -986,6 +1018,7 @@
if (mask_len <= 0 || mask_len > event_mask.mask_len) {
pr_err("diag: In %s, invalid event mask len: %d\n", __func__,
mask_len);
+ mutex_unlock(&driver->md_session_lock);
return -EIO;
}
@@ -993,6 +1026,7 @@
memcpy(mask_info->ptr, src_buf + header_len, mask_len);
mask_info->status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(EVENT_MASKS_TYPE);
@@ -1027,25 +1061,29 @@
}
static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int write_len = 0, i, peripheral;
uint8_t toggle = 0;
struct diag_event_report_t header;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &event_mask : info->event_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
!mask_info) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -1059,6 +1097,7 @@
memset(mask_info->ptr, 0, mask_info->mask_len);
}
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(EVENT_MASKS_TYPE);
@@ -1088,8 +1127,7 @@
}
static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int status = LOG_STATUS_INVALID;
@@ -1102,6 +1140,10 @@
struct diag_log_config_req_t *req;
struct diag_log_config_rsp_t rsp;
struct diag_mask_info *mask_info = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1109,16 +1151,20 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- if (!diag_apps_responds())
+ if (!diag_apps_responds()) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
req = (struct diag_log_config_req_t *)src_buf;
read_len += req_header_len;
@@ -1138,6 +1184,7 @@
if (!log_item->ptr) {
pr_err("diag: Invalid input in %s, mask: %pK\n",
__func__, log_item);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
@@ -1179,28 +1226,27 @@
rsp.status = status;
memcpy(dest_buf, &rsp, rsp_header_len);
+ mutex_unlock(&driver->md_session_lock);
return write_len;
}
static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
int i;
int write_len = 0;
struct diag_log_config_rsp_t rsp;
- struct diag_mask_info *mask_info = NULL;
struct diag_log_mask_t *mask = (struct diag_log_mask_t *)log_mask.ptr;
+ if (!mask)
+ return -EINVAL;
+
if (!diag_apps_responds())
return 0;
- mask_info = (!info) ? &log_mask : info->log_mask;
- if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
- !mask_info) {
- pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
- __func__, src_buf, src_len, dest_buf, dest_len,
- mask_info);
+ if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+ pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
+ __func__, src_buf, src_len, dest_buf, dest_len);
return -EINVAL;
}
@@ -1223,7 +1269,7 @@
static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ int pid)
{
int i, peripheral, write_len = 0;
int status = LOG_STATUS_SUCCESS;
@@ -1236,6 +1282,10 @@
struct diag_log_mask_t *mask = NULL;
struct diag_mask_info *mask_info = NULL;
unsigned char *temp_buf = NULL;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1243,11 +1293,13 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
@@ -1257,6 +1309,7 @@
if (!mask->ptr) {
pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
__func__, mask->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (req->equip_id >= MAX_EQUIP_ID) {
@@ -1319,6 +1372,7 @@
break;
}
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(LOG_MASKS_TYPE);
@@ -1365,13 +1419,16 @@
}
static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info)
+ unsigned char *dest_buf, int dest_len, int pid)
{
struct diag_mask_info *mask_info = NULL;
struct diag_log_mask_t *mask = NULL;
struct diag_log_config_rsp_t header;
int write_len = 0, i, peripheral;
+ struct diag_md_session_t *info = NULL;
+
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1379,17 +1436,20 @@
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (!mask_info->ptr) {
pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
__func__, mask_info->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
mask = (struct diag_log_mask_t *)mask_info->ptr;
if (!mask->ptr) {
pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
__func__, mask->ptr);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
@@ -1398,6 +1458,7 @@
mutex_unlock(&mask->lock);
}
mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
+ mutex_unlock(&driver->md_session_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(LOG_MASKS_TYPE);
@@ -2144,13 +2205,11 @@
}
}
-int diag_process_apps_masks(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+int diag_process_apps_masks(unsigned char *buf, int len, int pid)
{
int size = 0, sub_cmd = 0;
int (*hdlr)(unsigned char *src_buf, int src_len,
- unsigned char *dest_buf, int dest_len,
- struct diag_md_session_t *info) = NULL;
+ unsigned char *dest_buf, int dest_len, int pid) = NULL;
if (!buf || len <= 0)
return -EINVAL;
@@ -2200,7 +2259,7 @@
if (hdlr)
size = hdlr(buf, len, driver->apps_rsp_buf,
- DIAG_MAX_RSP_SIZE, info);
+ DIAG_MAX_RSP_SIZE, pid);
return (size > 0) ? size : 0;
}
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index 1a52f94..6edeee9 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018 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
@@ -167,8 +167,7 @@
void diag_log_mask_free(struct diag_mask_info *mask_info);
void diag_msg_mask_free(struct diag_mask_info *mask_info);
void diag_event_mask_free(struct diag_mask_info *mask_info);
-int diag_process_apps_masks(unsigned char *buf, int len,
- struct diag_md_session_t *info);
+int diag_process_apps_masks(unsigned char *buf, int len, int pid);
void diag_send_updates_peripheral(uint8_t peripheral);
extern int diag_create_msg_mask_table_entry(struct diag_msg_mask_t *msg_mask,
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 9cecb03..ce0c7bb 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, 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
@@ -129,11 +129,10 @@
int diag_md_write(int id, unsigned char *buf, int len, int ctx)
{
- int i;
+ int i, peripheral, pid = 0;
uint8_t found = 0;
unsigned long flags;
struct diag_md_info *ch = NULL;
- int peripheral;
struct diag_md_session_t *session_info = NULL;
if (id < 0 || id >= NUM_DIAG_MD_DEV || id >= DIAG_NUM_PROC)
@@ -146,10 +145,14 @@
if (peripheral < 0)
return -EINVAL;
- session_info =
- diag_md_session_get_peripheral(peripheral);
- if (!session_info)
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_peripheral(peripheral);
+ if (!session_info) {
+ mutex_unlock(&driver->md_session_lock);
return -EIO;
+ }
+ pid = session_info->pid;
+ mutex_unlock(&driver->md_session_lock);
ch = &diag_md[id];
if (!ch)
@@ -192,8 +195,7 @@
found = 0;
for (i = 0; i < driver->num_clients && !found; i++) {
- if ((driver->client_map[i].pid !=
- session_info->pid) ||
+ if ((driver->client_map[i].pid != pid) ||
(driver->client_map[i].pid == 0))
continue;
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index 1cf7f52..060f03f 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018 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
@@ -221,7 +221,7 @@
if (!atomic_read(&ch->connected) &&
driver->usb_connected && diag_mask_param())
- diag_clear_masks(NULL);
+ diag_clear_masks(0);
if (ch && ch->ops && ch->ops->close)
ch->ops->close(ch->ctxt, DIAG_USB_MODE);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9de40b0..3cecebf 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -714,7 +714,7 @@
void diag_cmd_remove_reg_by_proc(int proc);
int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry);
int diag_mask_param(void);
-void diag_clear_masks(struct diag_md_session_t *info);
+void diag_clear_masks(int pid);
uint8_t diag_mask_to_pd_value(uint32_t peripheral_mask);
int diag_query_pd(char *process_name);
int diag_search_peripheral_by_pd(uint8_t pd_val);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 0158549..694b483 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, 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
@@ -167,7 +167,7 @@
void *diag_ipc_log;
#endif
-static void diag_md_session_close(struct diag_md_session_t *session_info);
+static void diag_md_session_close(int pid);
/*
* Returns the next delayed rsp id. If wrapping is enabled,
@@ -243,12 +243,13 @@
timer_in_progress = 0;
mutex_lock(&apps_data_mutex);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (!hdlc_disabled)
diag_drain_apps_data(&hdlc_data);
else
@@ -422,7 +423,7 @@
{
return diag_mask_clear_param;
}
-void diag_clear_masks(struct diag_md_session_t *info)
+void diag_clear_masks(int pid)
{
int ret;
char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0};
@@ -431,14 +432,14 @@
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag: %s: masks clear request upon %s\n", __func__,
- ((info) ? "ODL exit" : "USB Disconnection"));
+ ((pid) ? "ODL exit" : "USB Disconnection"));
ret = diag_process_apps_masks(cmd_disable_log_mask,
- sizeof(cmd_disable_log_mask), info);
+ sizeof(cmd_disable_log_mask), pid);
ret = diag_process_apps_masks(cmd_disable_msg_mask,
- sizeof(cmd_disable_msg_mask), info);
+ sizeof(cmd_disable_msg_mask), pid);
ret = diag_process_apps_masks(cmd_disable_event_mask,
- sizeof(cmd_disable_event_mask), info);
+ sizeof(cmd_disable_event_mask), pid);
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag:%s: masks cleared successfully\n", __func__);
}
@@ -451,21 +452,23 @@
struct diag_md_session_t *session_info = NULL;
struct diag_logging_mode_param_t params;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_pid(pid);
- if (!session_info)
+ if (!session_info) {
+ mutex_unlock(&driver->md_session_lock);
return;
+ }
+ session_mask = session_info->peripheral_mask;
+ mutex_unlock(&driver->md_session_lock);
if (diag_mask_clear_param)
- diag_clear_masks(session_info);
+ diag_clear_masks(pid);
mutex_lock(&driver->diag_maskclear_mutex);
driver->mask_clear = 1;
mutex_unlock(&driver->diag_maskclear_mutex);
mutex_lock(&driver->diagchar_mutex);
- session_mask = session_info->peripheral_mask;
- diag_md_session_close(session_info);
-
p_mask =
diag_translate_kernel_to_user_mask(session_mask);
@@ -489,7 +492,9 @@
}
}
}
-
+ mutex_lock(&driver->md_session_lock);
+ diag_md_session_close(pid);
+ mutex_unlock(&driver->md_session_lock);
diag_switch_logging(¶ms);
mutex_unlock(&driver->diagchar_mutex);
}
@@ -1024,11 +1029,13 @@
if (driver->hdlc_encode_buf_len != 0)
return -EAGAIN;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled) {
if (len < 4) {
pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
@@ -1386,15 +1393,16 @@
return err;
}
-static void diag_md_session_close(struct diag_md_session_t *session_info)
+static void diag_md_session_close(int pid)
{
int i;
uint8_t found = 0;
+ struct diag_md_session_t *session_info = NULL;
+ session_info = diag_md_session_get_pid(pid);
if (!session_info)
return;
- mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] != session_info)
continue;
@@ -1420,13 +1428,14 @@
driver->md_session_mode = (found) ? DIAG_MD_PERIPHERAL : DIAG_MD_NONE;
kfree(session_info);
session_info = NULL;
- mutex_unlock(&driver->md_session_lock);
DIAG_LOG(DIAG_DEBUG_USERSPACE, "cleared up session\n");
}
struct diag_md_session_t *diag_md_session_get_pid(int pid)
{
int i;
+ if (pid <= 0)
+ return NULL;
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] &&
driver->md_session_map[i]->pid == pid)
@@ -1442,10 +1451,12 @@
return driver->md_session_map[peripheral];
}
-static int diag_md_peripheral_switch(struct diag_md_session_t *session_info,
+static int diag_md_peripheral_switch(int pid,
int peripheral_mask, int req_mode) {
int i, bit = 0;
+ struct diag_md_session_t *session_info = NULL;
+ session_info = diag_md_session_get_pid(pid);
if (!session_info)
return -EINVAL;
if (req_mode != DIAG_USB_MODE || req_mode != DIAG_MEMORY_DEVICE_MODE)
@@ -1455,25 +1466,20 @@
* check that md_session_map for i == session_info,
* if not then race condition occurred and bail
*/
- mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
bit = MD_PERIPHERAL_MASK(i) & peripheral_mask;
if (!bit)
continue;
if (req_mode == DIAG_USB_MODE) {
- if (driver->md_session_map[i] != session_info) {
- mutex_unlock(&driver->md_session_lock);
+ if (driver->md_session_map[i] != session_info)
return -EINVAL;
- }
driver->md_session_map[i] = NULL;
driver->md_session_mask &= ~bit;
session_info->peripheral_mask &= ~bit;
} else {
- if (driver->md_session_map[i] != NULL) {
- mutex_unlock(&driver->md_session_lock);
+ if (driver->md_session_map[i] != NULL)
return -EINVAL;
- }
driver->md_session_map[i] = session_info;
driver->md_session_mask |= bit;
session_info->peripheral_mask |= bit;
@@ -1482,7 +1488,6 @@
}
driver->md_session_mode = DIAG_MD_PERIPHERAL;
- mutex_unlock(&driver->md_session_lock);
DIAG_LOG(DIAG_DEBUG_USERSPACE, "Changed Peripherals:0x%x to mode:%d\n",
peripheral_mask, req_mode);
}
@@ -1491,7 +1496,7 @@
const struct diag_logging_mode_param_t *param,
uint8_t *change_mode)
{
- int i, bit = 0, err = 0;
+ int i, bit = 0, err = 0, peripheral_mask = 0;
int change_mask = 0;
struct diag_md_session_t *session_info = NULL;
@@ -1515,12 +1520,13 @@
if (req_mode == DIAG_USB_MODE) {
if (curr_mode == DIAG_USB_MODE)
return 0;
+ mutex_lock(&driver->md_session_lock);
if (driver->md_session_mode == DIAG_MD_NONE
&& driver->md_session_mask == 0 && driver->logging_mask) {
*change_mode = 1;
+ mutex_unlock(&driver->md_session_lock);
return 0;
}
-
/*
* curr_mode is either DIAG_MULTI_MODE or DIAG_MD_MODE
* Check if requested peripherals are already in usb mode
@@ -1532,8 +1538,10 @@
if (bit & driver->logging_mask)
change_mask |= bit;
}
- if (!change_mask)
+ if (!change_mask) {
+ mutex_unlock(&driver->md_session_lock);
return 0;
+ }
/*
* Change is needed. Check if this md_session has set all the
@@ -1542,29 +1550,29 @@
* 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;
+ mutex_unlock(&driver->md_session_lock);
return 0;
}
- if ((change_mask & session_info->peripheral_mask)
+ peripheral_mask = session_info->peripheral_mask;
+ if ((change_mask & peripheral_mask)
!= change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
*change_mode = 1;
/* If all peripherals are being set to USB Mode, call close */
- if (~change_mask & session_info->peripheral_mask) {
- err = diag_md_peripheral_switch(session_info,
+ if (~change_mask & peripheral_mask) {
+ err = diag_md_peripheral_switch(current->tgid,
change_mask, DIAG_USB_MODE);
} else
- diag_md_session_close(session_info);
-
+ diag_md_session_close(current->tgid);
+ mutex_unlock(&driver->md_session_lock);
return err;
} else if (req_mode == DIAG_MEMORY_DEVICE_MODE) {
@@ -1573,21 +1581,23 @@
* been set. Check that requested peripherals already set are
* owned by this md session
*/
- change_mask = driver->md_session_mask & param->peripheral_mask;
mutex_lock(&driver->md_session_lock);
+ change_mask = driver->md_session_mask & param->peripheral_mask;
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)
!= change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
- err = diag_md_peripheral_switch(session_info,
+ err = diag_md_peripheral_switch(current->tgid,
change_mask, DIAG_USB_MODE);
+ mutex_unlock(&driver->md_session_lock);
} else {
+ mutex_unlock(&driver->md_session_lock);
if (change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
@@ -2047,19 +2057,17 @@
{
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;
mutex_lock(&driver->hdlc_disable_mutex);
- if (session_info) {
- mutex_lock(&driver->md_session_lock);
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_pid(current->tgid);
+ if (session_info)
session_info->hdlc_disabled = hdlc_support;
- mutex_unlock(&driver->md_session_lock);
- } else
+ else
driver->hdlc_disabled = hdlc_support;
+ mutex_unlock(&driver->md_session_lock);
mutex_unlock(&driver->hdlc_disable_mutex);
diag_update_md_clients(HDLC_SUPPORT_TYPE);
@@ -2885,7 +2893,6 @@
int remote_proc = 0;
const int mempool = POOL_TYPE_COPY;
unsigned char *user_space_data = NULL;
- struct diag_md_session_t *info = NULL;
if (!buf || len <= 0 || len > CALLBACK_BUF_SIZE) {
pr_err_ratelimited("diag: In %s, invalid buf %pK len: %d\n",
@@ -2936,13 +2943,11 @@
} 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);
+ ret = diag_process_apps_pkt(user_space_data, len,
+ current->tgid);
if (ret == 1)
diag_send_error_rsp((void *)(user_space_data), len,
- info);
+ current->tgid);
}
fail:
diagmem_free(driver, user_space_data, mempool);
@@ -3008,24 +3013,25 @@
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);
+ mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
+ mutex_unlock(&driver->md_session_lock);
if (!hdlc_disabled)
diag_process_hdlc_pkt((void *)
(driver->user_space_data_buf),
- len, session_info);
+ len, current->tgid);
else
diag_process_non_hdlc_pkt((char *)
(driver->user_space_data_buf),
- len, session_info);
+ len, current->tgid);
return 0;
}
@@ -3102,11 +3108,13 @@
mutex_lock(&apps_data_mutex);
mutex_lock(&driver->hdlc_disable_mutex);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled)
ret = diag_process_apps_data_non_hdlc(user_space_data, len,
pkt_type);
@@ -3177,9 +3185,9 @@
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);
+ mutex_unlock(&driver->md_session_lock);
goto exit;
} else if (driver->data_ready[index] & USER_SPACE_DATA_TYPE) {
/* In case, the thread wakes up and the logging mode is not
@@ -3199,14 +3207,16 @@
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_ERR(buf+4,
session_info->hdlc_disabled,
sizeof(uint8_t));
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
}
+ mutex_unlock(&driver->md_session_lock);
goto exit;
}
@@ -3226,12 +3236,16 @@
if (driver->data_ready[index] & MSG_MASKS_TYPE) {
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
write_len = diag_copy_to_user_msg_mask(buf + ret, count,
session_info);
+ mutex_unlock(&driver->md_session_lock);
if (write_len > 0)
ret += write_len;
driver->data_ready[index] ^= MSG_MASKS_TYPE;
@@ -3242,25 +3256,32 @@
if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
COPY_USER_SPACE_OR_ERR(buf, data_type, 4);
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
-
+ }
if (session_info && session_info->event_mask &&
session_info->event_mask->ptr) {
COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
*(session_info->event_mask->ptr),
session_info->event_mask->mask_len);
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
} else {
COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
*(event_mask.ptr),
event_mask.mask_len);
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
}
+ mutex_unlock(&driver->md_session_lock);
driver->data_ready[index] ^= EVENT_MASKS_TYPE;
atomic_dec(&driver->data_ready_notif[index]);
goto exit;
@@ -3269,13 +3290,17 @@
if (driver->data_ready[index] & LOG_MASKS_TYPE) {
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(APPS_DATA);
COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
- if (ret == -EFAULT)
+ if (ret == -EFAULT) {
+ mutex_unlock(&driver->md_session_lock);
goto exit;
+ }
write_len = diag_copy_to_user_log_mask(buf + ret, count,
session_info);
+ mutex_unlock(&driver->md_session_lock);
if (write_len > 0)
ret += write_len;
driver->data_ready[index] ^= LOG_MASKS_TYPE;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 166bd16..33048e1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -242,7 +242,7 @@
}
static void pack_rsp_and_send(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
int err;
int retry_count = 0, i, rsp_ctxt;
@@ -250,6 +250,7 @@
unsigned long flags;
unsigned char *rsp_ptr = driver->encoded_rsp_buf;
struct diag_pkt_frame_t header;
+ struct diag_md_session_t *session_info = NULL, *info = NULL;
if (!rsp_ptr || !buf)
return;
@@ -260,6 +261,11 @@
return;
}
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_pid(pid);
+ info = (session_info) ? session_info :
+ diag_md_session_get_peripheral(APPS_DATA);
+
/*
* Explicitly check for the Peripheral Modem here
* is necessary till a way to identify a peripheral
@@ -279,6 +285,7 @@
}
} else
rsp_ctxt = driver->rsp_buf_ctxt;
+ mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
@@ -302,8 +309,11 @@
* draining responses when we are in Memory Device Mode.
*/
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
- driver->logging_mode == DIAG_MULTI_MODE)
+ driver->logging_mode == DIAG_MULTI_MODE) {
+ mutex_lock(&driver->md_session_lock);
chk_logging_wakeup();
+ mutex_unlock(&driver->md_session_lock);
+ }
}
if (driver->rsp_buf_busy) {
pr_err("diag: unable to get hold of response buffer\n");
@@ -332,13 +342,14 @@
}
static void encode_rsp_and_send(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
unsigned char *rsp_ptr = driver->encoded_rsp_buf;
int err, i, rsp_ctxt, retry_count = 0;
unsigned long flags;
+ struct diag_md_session_t *session_info = NULL, *info = NULL;
if (!rsp_ptr || !buf)
return;
@@ -349,6 +360,11 @@
return;
}
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_pid(pid);
+ info = (session_info) ? session_info :
+ diag_md_session_get_peripheral(APPS_DATA);
+
/*
* Explicitly check for the Peripheral Modem here
* is necessary till a way to identify a peripheral
@@ -368,7 +384,7 @@
}
} else
rsp_ctxt = driver->rsp_buf_ctxt;
-
+ mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
* take one or two iterations. When this loops till UINT_MAX, it
@@ -391,8 +407,11 @@
* draining responses when we are in Memory Device Mode.
*/
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
- driver->logging_mode == DIAG_MULTI_MODE)
+ driver->logging_mode == DIAG_MULTI_MODE) {
+ mutex_lock(&driver->md_session_lock);
chk_logging_wakeup();
+ mutex_unlock(&driver->md_session_lock);
+ }
}
if (driver->rsp_buf_busy) {
@@ -424,22 +443,23 @@
}
static void diag_send_rsp(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
- struct diag_md_session_t *session_info = NULL;
+ struct diag_md_session_t *session_info = NULL, *info = NULL;
uint8_t hdlc_disabled;
-
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
session_info = (info) ? info :
diag_md_session_get_peripheral(APPS_DATA);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled)
- pack_rsp_and_send(buf, len, session_info);
+ pack_rsp_and_send(buf, len, pid);
else
- encode_rsp_and_send(buf, len, session_info);
+ encode_rsp_and_send(buf, len, pid);
}
void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type)
@@ -506,6 +526,7 @@
int i, j;
mutex_lock(&driver->diagchar_mutex);
+ mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] != NULL)
for (j = 0; j < driver->num_clients; j++) {
@@ -521,6 +542,7 @@
}
}
}
+ mutex_unlock(&driver->md_session_lock);
wake_up_interruptible(&driver->wait_q);
mutex_unlock(&driver->diagchar_mutex);
}
@@ -982,7 +1004,7 @@
}
void diag_send_error_rsp(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
/* -1 to accommodate the first byte 0x13 */
if (len > (DIAG_MAX_RSP_SIZE - 1)) {
@@ -992,13 +1014,12 @@
*(uint8_t *)driver->apps_rsp_buf = DIAG_CMD_ERROR;
memcpy((driver->apps_rsp_buf + sizeof(uint8_t)), buf, len);
- diag_send_rsp(driver->apps_rsp_buf, len + 1, info);
+ diag_send_rsp(driver->apps_rsp_buf, len + 1, pid);
}
-int diag_process_apps_pkt(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
{
- int i;
+ int i, p_mask = 0;
int mask_ret;
int write_len = 0;
unsigned char *temp = NULL;
@@ -1007,14 +1028,15 @@
struct diag_cmd_reg_t *reg_item = NULL;
struct diagfwd_info *fwd_info = NULL;
uint32_t pd_mask = 0;
+ struct diag_md_session_t *info = NULL;
if (!buf)
return -EIO;
/* Check if the command is a supported mask command */
- mask_ret = diag_process_apps_masks(buf, len, info);
+ mask_ret = diag_process_apps_masks(buf, len, pid);
if (mask_ret > 0) {
- diag_send_rsp(driver->apps_rsp_buf, mask_ret, info);
+ diag_send_rsp(driver->apps_rsp_buf, mask_ret, pid);
return 0;
}
@@ -1036,7 +1058,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
@@ -1045,18 +1067,22 @@
if (temp_entry) {
reg_item = container_of(temp_entry, struct diag_cmd_reg_t,
entry);
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (info) {
+ p_mask = info->peripheral_mask;
+ mutex_unlock(&driver->md_session_lock);
MD_PERIPHERAL_PD_MASK(TYPE_CMD, reg_item->proc,
pd_mask);
if ((MD_PERIPHERAL_MASK(reg_item->proc) &
- info->peripheral_mask) ||
- (pd_mask & info->peripheral_mask))
+ p_mask) || (pd_mask & p_mask))
write_len = diag_send_data(reg_item, buf, len);
} else {
+ mutex_unlock(&driver->md_session_lock);
if (MD_PERIPHERAL_MASK(reg_item->proc) &
driver->logging_mask) {
mutex_unlock(&driver->cmd_reg_mutex);
- diag_send_error_rsp(buf, len, info);
+ diag_send_error_rsp(buf, len, pid);
return write_len;
}
else
@@ -1074,13 +1100,13 @@
for (i = 0; i < 4; i++)
*(driver->apps_rsp_buf+i) = *(buf+i);
*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
- diag_send_rsp(driver->apps_rsp_buf, 8, info);
+ diag_send_rsp(driver->apps_rsp_buf, 8, pid);
return 0;
} else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
len = diag_process_stm_cmd(buf, driver->apps_rsp_buf);
if (len > 0) {
- diag_send_rsp(driver->apps_rsp_buf, len, info);
+ diag_send_rsp(driver->apps_rsp_buf, len, pid);
return 0;
}
return len;
@@ -1093,7 +1119,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
/* Check for time sync switch command */
@@ -1104,7 +1130,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
/* Check for diag id command */
@@ -1115,14 +1141,14 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0)
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
/* Check for download command */
else if ((chk_apps_master()) && (*buf == 0x3A)) {
/* send response back */
driver->apps_rsp_buf[0] = *buf;
- diag_send_rsp(driver->apps_rsp_buf, 1, info);
+ diag_send_rsp(driver->apps_rsp_buf, 1, pid);
msleep(5000);
/* call download API */
msm_set_restart_mode(RESTART_DLOAD);
@@ -1142,7 +1168,7 @@
for (i = 0; i < 13; i++)
driver->apps_rsp_buf[i+3] = 0;
- diag_send_rsp(driver->apps_rsp_buf, 16, info);
+ diag_send_rsp(driver->apps_rsp_buf, 16, pid);
return 0;
}
}
@@ -1151,7 +1177,7 @@
(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_enabled;
- diag_send_rsp(driver->apps_rsp_buf, 5, info);
+ diag_send_rsp(driver->apps_rsp_buf, 5, pid);
return 0;
}
/* Wrap the Delayed Rsp ID */
@@ -1160,7 +1186,7 @@
wrap_enabled = true;
memcpy(driver->apps_rsp_buf, buf, 4);
driver->apps_rsp_buf[4] = wrap_count;
- diag_send_rsp(driver->apps_rsp_buf, 6, info);
+ diag_send_rsp(driver->apps_rsp_buf, 6, pid);
return 0;
}
/* Mobile ID Rsp */
@@ -1171,7 +1197,7 @@
driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0) {
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
}
@@ -1191,7 +1217,7 @@
for (i = 0; i < 55; i++)
driver->apps_rsp_buf[i] = 0;
- diag_send_rsp(driver->apps_rsp_buf, 55, info);
+ diag_send_rsp(driver->apps_rsp_buf, 55, pid);
return 0;
}
/* respond to 0x7c command */
@@ -1204,14 +1230,14 @@
chk_config_get_id();
*(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
*(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
- diag_send_rsp(driver->apps_rsp_buf, 14, info);
+ diag_send_rsp(driver->apps_rsp_buf, 14, pid);
return 0;
}
}
write_len = diag_cmd_chk_stats(buf, len, driver->apps_rsp_buf,
DIAG_MAX_RSP_SIZE);
if (write_len > 0) {
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
return 0;
}
write_len = diag_cmd_disable_hdlc(buf, len, driver->apps_rsp_buf,
@@ -1223,7 +1249,7 @@
* before disabling HDLC encoding on Apps processor.
*/
mutex_lock(&driver->hdlc_disable_mutex);
- diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+ diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
/*
* Set the value of hdlc_disabled after sending the response to
* the tools. This is required since the tools is expecting a
@@ -1231,10 +1257,13 @@
*/
pr_debug("diag: In %s, disabling HDLC encoding\n",
__func__);
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (info)
info->hdlc_disabled = 1;
else
driver->hdlc_disabled = 1;
+ mutex_unlock(&driver->md_session_lock);
diag_update_md_clients(HDLC_SUPPORT_TYPE);
mutex_unlock(&driver->hdlc_disable_mutex);
return 0;
@@ -1243,13 +1272,12 @@
/* We have now come to the end of the function. */
if (chk_apps_only())
- diag_send_error_rsp(buf, len, info);
+ diag_send_error_rsp(buf, len, pid);
return 0;
}
-void diag_process_hdlc_pkt(void *data, unsigned int len,
- struct diag_md_session_t *info)
+void diag_process_hdlc_pkt(void *data, unsigned int len, int pid)
{
int err = 0;
int ret = 0;
@@ -1309,7 +1337,7 @@
}
err = diag_process_apps_pkt(driver->hdlc_buf,
- driver->hdlc_buf_len, info);
+ driver->hdlc_buf_len, pid);
if (err < 0)
goto fail;
} else {
@@ -1326,7 +1354,7 @@
* recovery algorithm. Send an error response if the
* packet is not in expected format.
*/
- diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, info);
+ diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, pid);
driver->hdlc_buf_len = 0;
end:
mutex_unlock(&driver->diag_hdlc_mutex);
@@ -1423,9 +1451,11 @@
static uint8_t hdlc_reset;
-static void hdlc_reset_timer_start(struct diag_md_session_t *info)
+static void hdlc_reset_timer_start(int pid)
{
+ struct diag_md_session_t *info = NULL;
mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (!hdlc_timer_in_progress) {
hdlc_timer_in_progress = 1;
if (info)
@@ -1467,15 +1497,16 @@
}
static void diag_hdlc_start_recovery(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+ int pid)
{
int i;
static uint32_t bad_byte_counter;
unsigned char *start_ptr = NULL;
struct diag_pkt_frame_t *actual_pkt = NULL;
+ struct diag_md_session_t *info = NULL;
hdlc_reset = 1;
- hdlc_reset_timer_start(info);
+ hdlc_reset_timer_start(pid);
actual_pkt = (struct diag_pkt_frame_t *)buf;
for (i = 0; i < len; i++) {
@@ -1495,10 +1526,13 @@
pr_err("diag: In %s, re-enabling HDLC encoding\n",
__func__);
mutex_lock(&driver->hdlc_disable_mutex);
+ mutex_lock(&driver->md_session_lock);
+ info = diag_md_session_get_pid(pid);
if (info)
info->hdlc_disabled = 0;
else
driver->hdlc_disabled = 0;
+ mutex_unlock(&driver->md_session_lock);
mutex_unlock(&driver->hdlc_disable_mutex);
diag_update_md_clients(HDLC_SUPPORT_TYPE);
@@ -1511,12 +1545,11 @@
mutex_lock(&driver->hdlc_recovery_mutex);
driver->incoming_pkt.processing = 0;
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_process_non_hdlc_pkt(start_ptr, len - i, info);
+ diag_process_non_hdlc_pkt(start_ptr, len - i, pid);
}
}
-void diag_process_non_hdlc_pkt(unsigned char *buf, int len,
- struct diag_md_session_t *info)
+void diag_process_non_hdlc_pkt(unsigned char *buf, int len, int pid)
{
int err = 0;
uint16_t pkt_len = 0;
@@ -1572,11 +1605,11 @@
if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
CONTROL_CHAR) {
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_hdlc_start_recovery(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
mutex_lock(&driver->hdlc_recovery_mutex);
}
err = diag_process_apps_pkt(data_ptr,
- actual_pkt->length, info);
+ actual_pkt->length, pid);
if (err) {
pr_err("diag: In %s, unable to process incoming data packet, err: %d\n",
__func__, err);
@@ -1598,8 +1631,8 @@
pkt_len = actual_pkt->length;
if (actual_pkt->start != CONTROL_CHAR) {
- diag_hdlc_start_recovery(buf, len, info);
- diag_send_error_rsp(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
+ diag_send_error_rsp(buf, len, pid);
goto end;
}
mutex_lock(&driver->hdlc_recovery_mutex);
@@ -1607,7 +1640,7 @@
pr_err("diag: In %s, incoming data is too large for the request buffer %d\n",
__func__, pkt_len);
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_hdlc_start_recovery(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
break;
}
if ((pkt_len + header_len) > (len - read_bytes)) {
@@ -1624,13 +1657,13 @@
if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
CONTROL_CHAR) {
mutex_unlock(&driver->hdlc_recovery_mutex);
- diag_hdlc_start_recovery(buf, len, info);
+ diag_hdlc_start_recovery(buf, len, pid);
mutex_lock(&driver->hdlc_recovery_mutex);
}
else
hdlc_reset = 0;
err = diag_process_apps_pkt(data_ptr,
- actual_pkt->length, info);
+ actual_pkt->length, pid);
if (err) {
mutex_unlock(&driver->hdlc_recovery_mutex);
break;
@@ -1649,9 +1682,9 @@
return -EINVAL;
if (!driver->hdlc_disabled)
- diag_process_hdlc_pkt(buf, len, NULL);
+ diag_process_hdlc_pkt(buf, len, 0);
else
- diag_process_non_hdlc_pkt(buf, len, NULL);
+ diag_process_non_hdlc_pkt(buf, len, 0);
diag_mux_queue_read(ctxt);
return 0;
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 0e0bf2d..687aeb7 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -30,10 +30,8 @@
int diagfwd_init(void);
void diagfwd_exit(void);
-void diag_process_hdlc_pkt(void *data, unsigned int len,
- struct diag_md_session_t *info);
-void diag_process_non_hdlc_pkt(unsigned char *data, int len,
- struct diag_md_session_t *info);
+void diag_process_hdlc_pkt(void *data, unsigned int len, int pid);
+void diag_process_non_hdlc_pkt(unsigned char *data, int len, int pid);
int chk_config_get_id(void);
int chk_apps_only(void);
int chk_apps_master(void);
@@ -45,10 +43,8 @@
int diag_check_common_cmd(struct diag_pkt_header_t *header);
void diag_update_userspace_clients(unsigned int type);
void diag_update_sleeping_process(int process_id, int data_type);
-int diag_process_apps_pkt(unsigned char *buf, int len,
- struct diag_md_session_t *info);
-void diag_send_error_rsp(unsigned char *buf, int len,
- struct diag_md_session_t *info);
+int diag_process_apps_pkt(unsigned char *buf, int len, int pid);
+void diag_send_error_rsp(unsigned char *buf, int len, int pid);
void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type);
int diag_process_stm_cmd(unsigned char *buf, unsigned char *dest_buf);
void diag_md_hdlc_reset_timer_func(unsigned long pid);
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index c7bd2205..c4e6107 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -343,14 +343,13 @@
diag_ws_release();
return;
}
-
- session_info =
- diag_md_session_get_peripheral(peripheral);
+ mutex_lock(&driver->md_session_lock);
+ session_info = diag_md_session_get_peripheral(peripheral);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (hdlc_disabled) {
/* The data is raw and and on APPS side HDLC is disabled */
if (!buf) {
@@ -633,12 +632,13 @@
mutex_lock(&driver->hdlc_disable_mutex);
mutex_lock(&fwd_info->data_mutex);
+ mutex_lock(&driver->md_session_lock);
session_info = diag_md_session_get_peripheral(fwd_info->peripheral);
if (session_info)
hdlc_disabled = session_info->hdlc_disabled;
else
hdlc_disabled = driver->hdlc_disabled;
-
+ mutex_unlock(&driver->md_session_lock);
if (!driver->feature[fwd_info->peripheral].encode_hdlc) {
if (fwd_info->buf_1 && fwd_info->buf_1->data == buf) {
temp_buf = fwd_info->buf_1;