Merge "diag: Fix possible use-after-free issue for mdlog session info"

This commit is contained in:
Linux Build Service Account 2018-02-05 16:30:01 -08:00 committed by Gerrit - the friendly Code Review server
commit a7e3f3f2de
9 changed files with 328 additions and 190 deletions

View file

@ -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
@ -537,8 +537,7 @@ static void diag_send_feature_mask_update(uint8_t peripheral)
}
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;
@ -546,23 +545,30 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
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;
@ -584,12 +590,12 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
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;
@ -642,8 +648,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
}
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;
@ -652,6 +657,10 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
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 ||
@ -659,15 +668,19 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
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;
@ -682,6 +695,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
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++) {
@ -701,12 +715,12 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
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)
{
int i;
int write_len = 0;
@ -720,6 +734,10 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
struct diag_mask_info *mask_info = NULL;
struct diag_msg_mask_t *mask_next = NULL;
uint32_t *temp = 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 ||
@ -727,11 +745,13 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
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;
}
@ -744,6 +764,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
__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++) {
@ -786,6 +807,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
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;
@ -806,6 +828,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
}
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);
@ -839,8 +862,7 @@ end:
}
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;
int write_len = 0;
@ -849,6 +871,10 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
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 ||
@ -856,11 +882,13 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
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;
}
@ -875,6 +903,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
__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 :
@ -887,7 +916,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
}
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);
@ -915,8 +944,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
}
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;
@ -951,8 +979,7 @@ static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len,
}
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;
int write_len = 0;
@ -961,18 +988,23 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
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;
@ -980,6 +1012,7 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
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;
}
@ -987,6 +1020,7 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
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);
@ -1015,26 +1049,30 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
}
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 i;
int write_len = 0;
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;
}
@ -1048,6 +1086,7 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
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);
@ -1071,8 +1110,7 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
}
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;
@ -1085,6 +1123,10 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
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 ||
@ -1092,16 +1134,20 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
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;
@ -1121,6 +1167,7 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
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++) {
@ -1162,28 +1209,27 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
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;
}
@ -1206,7 +1252,7 @@ static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len,
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;
int write_len = 0;
@ -1221,6 +1267,10 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
struct diag_log_mask_t *mask = NULL;
unsigned char *temp_buf = 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) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@ -1228,11 +1278,13 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
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;
}
@ -1242,6 +1294,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
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) {
@ -1304,6 +1357,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
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);
@ -1344,14 +1398,16 @@ end:
}
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;
int i;
int write_len = 0, i;
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 ||
@ -1359,17 +1415,20 @@ static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
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++) {
@ -1378,6 +1437,7 @@ static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
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);
@ -2109,14 +2169,12 @@ void diag_send_updates_peripheral(uint8_t peripheral)
&driver->buffering_mode[peripheral]);
}
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;
int 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;
@ -2166,7 +2224,7 @@ int diag_process_apps_masks(unsigned char *buf, int len,
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;
}

View file

@ -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 @@ int diag_event_mask_copy(struct diag_mask_info *dest,
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,

View file

@ -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
@ -131,7 +131,7 @@ void diag_md_close_all()
int diag_md_write(int id, unsigned char *buf, int len, int ctx)
{
int i;
int i, pid = 0;
uint8_t found = 0;
unsigned long flags;
struct diag_md_info *ch = NULL;
@ -149,10 +149,14 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx)
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)
@ -195,8 +199,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx)
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;

View file

@ -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 @@ static void usb_disconnect(struct diag_usb_info *ch)
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);

View file

@ -676,7 +676,7 @@ void diag_cmd_remove_reg_by_pid(int pid);
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);
void diag_record_stats(int type, int flag);

View file

@ -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
@ -170,7 +170,7 @@ uint16_t diag_debug_mask;
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,
@ -209,6 +209,16 @@ do { \
ret += length; \
} while (0)
#define COPY_USER_SPACE_OR_ERR(buf, data, length) \
do { \
if ((count < ret+length) || (copy_to_user(buf, \
(void *)&data, length))) { \
ret = -EFAULT; \
break; \
} \
ret += length; \
} while (0)
static void drain_timer_func(unsigned long data)
{
queue_work(driver->diag_wq , &(driver->diag_drain_work));
@ -247,12 +257,13 @@ void diag_drain_work_fn(struct work_struct *work)
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
@ -438,7 +449,7 @@ int diag_mask_param(void)
{
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};
@ -447,14 +458,14 @@ void diag_clear_masks(struct diag_md_session_t *info)
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__);
}
@ -467,12 +478,17 @@ static void diag_close_logging_process(const int pid)
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;
@ -480,9 +496,6 @@ static void diag_close_logging_process(const int pid)
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);
@ -506,7 +519,9 @@ static void diag_close_logging_process(const int pid)
}
}
}
mutex_lock(&driver->md_session_lock);
diag_md_session_close(pid);
mutex_unlock(&driver->md_session_lock);
diag_switch_logging(&params);
mutex_unlock(&driver->diagchar_mutex);
@ -1040,11 +1055,13 @@ static int diag_send_raw_data_remote(int proc, void *buf, int len,
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",
@ -1408,15 +1425,16 @@ fail_peripheral:
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;
@ -1442,13 +1460,14 @@ static void diag_md_session_close(struct diag_md_session_t *session_info)
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)
@ -1464,10 +1483,12 @@ struct diag_md_session_t *diag_md_session_get_peripheral(uint8_t peripheral)
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)
@ -1477,25 +1498,20 @@ static int diag_md_peripheral_switch(struct diag_md_session_t *session_info,
* 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;
@ -1504,7 +1520,6 @@ static int diag_md_peripheral_switch(struct diag_md_session_t *session_info,
}
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);
}
@ -1513,7 +1528,7 @@ static int diag_md_session_check(int curr_mode, int req_mode,
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;
@ -1537,12 +1552,13 @@ static int diag_md_session_check(int curr_mode, int req_mode,
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
@ -1554,8 +1570,10 @@ static int diag_md_session_check(int curr_mode, int req_mode,
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
@ -1564,29 +1582,29 @@ 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;
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) {
@ -1595,21 +1613,23 @@ static int diag_md_session_check(int curr_mode, int req_mode,
* 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");
@ -2065,19 +2085,17 @@ 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;
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);
@ -2789,7 +2807,6 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
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",
@ -2840,13 +2857,11 @@ 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);
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);
@ -2912,24 +2927,25 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
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;
}
@ -3006,11 +3022,13 @@ static int diag_user_process_apps_data(const char __user *buf, int len,
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);
@ -3079,9 +3097,9 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
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
@ -3097,11 +3115,16 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
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,
if (session_info) {
COPY_USER_SPACE_OR_ERR(buf+4,
session_info->hdlc_disabled,
sizeof(uint8_t));
if (ret == -EFAULT) {
mutex_unlock(&driver->md_session_lock);
goto exit;
}
}
mutex_unlock(&driver->md_session_lock);
goto exit;
}
@ -3119,10 +3142,16 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
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_EXIT(buf, data_type, sizeof(int));
COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
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;
@ -3133,18 +3162,32 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
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_EXIT(buf, data_type, 4);
COPY_USER_SPACE_OR_ERR(buf, data_type, 4);
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_EXIT(buf + sizeof(int),
COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
*(session_info->event_mask->ptr),
session_info->event_mask->mask_len);
if (ret == -EFAULT) {
mutex_unlock(&driver->md_session_lock);
goto exit;
}
} else {
COPY_USER_SPACE_OR_EXIT(buf + sizeof(int),
COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
*(event_mask.ptr),
event_mask.mask_len);
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;
@ -3153,10 +3196,16 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
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_EXIT(buf, data_type, sizeof(int));
COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
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;

View file

@ -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
@ -242,7 +242,7 @@ void chk_logging_wakeup(void)
}
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 @@ static void pack_rsp_and_send(unsigned char *buf, int len,
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 @@ static void pack_rsp_and_send(unsigned char *buf, int len,
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);
if (info && info->peripheral_mask) {
if (info->peripheral_mask == DIAG_CON_ALL ||
(info->peripheral_mask & (1 << APPS_DATA)) ||
@ -274,6 +280,7 @@ static void pack_rsp_and_send(unsigned char *buf, int len,
}
} else
rsp_ctxt = driver->rsp_buf_ctxt;
mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
@ -297,8 +304,11 @@ static void pack_rsp_and_send(unsigned char *buf, int len,
* 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");
@ -327,13 +337,14 @@ static void pack_rsp_and_send(unsigned char *buf, int len,
}
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;
@ -344,6 +355,11 @@ static void encode_rsp_and_send(unsigned char *buf, int len,
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);
if (info && info->peripheral_mask) {
if (info->peripheral_mask == DIAG_CON_ALL ||
(info->peripheral_mask & (1 << APPS_DATA)) ||
@ -358,7 +374,7 @@ static void encode_rsp_and_send(unsigned char *buf, int len,
}
} 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
@ -381,8 +397,11 @@ static void encode_rsp_and_send(unsigned char *buf, int len,
* 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) {
@ -413,22 +432,23 @@ static void encode_rsp_and_send(unsigned char *buf, int len,
memset(buf, '\0', DIAG_MAX_RSP_SIZE);
}
void diag_send_rsp(unsigned char *buf, int len, struct diag_md_session_t *info)
static void diag_send_rsp(unsigned char *buf, int len, 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)
@ -494,6 +514,7 @@ void diag_update_md_clients(unsigned int type)
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++) {
@ -507,6 +528,7 @@ void diag_update_md_clients(unsigned int type)
}
}
}
mutex_unlock(&driver->md_session_lock);
wake_up_interruptible(&driver->wait_q);
mutex_unlock(&driver->diagchar_mutex);
}
@ -905,7 +927,7 @@ static int diag_cmd_disable_hdlc(unsigned char *src_buf, int src_len,
}
void diag_send_error_rsp(unsigned char *buf, int len,
struct diag_md_session_t *info)
int pid)
{
/* -1 to accomodate the first byte 0x13 */
if (len > (DIAG_MAX_RSP_SIZE - 1)) {
@ -915,27 +937,27 @@ void diag_send_error_rsp(unsigned char *buf, int len,
*(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;
struct diag_cmd_reg_entry_t entry;
struct diag_cmd_reg_entry_t *temp_entry = NULL;
struct diag_cmd_reg_t *reg_item = NULL;
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;
}
@ -957,7 +979,7 @@ int diag_process_apps_pkt(unsigned char *buf, int 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;
}
@ -966,14 +988,18 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
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) {
if (MD_PERIPHERAL_MASK(reg_item->proc) &
info->peripheral_mask)
p_mask = info->peripheral_mask;
mutex_unlock(&driver->md_session_lock);
if (MD_PERIPHERAL_MASK(reg_item->proc) & 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)
diag_send_error_rsp(buf, len, info);
diag_send_error_rsp(buf, len, pid);
else
write_len = diag_send_data(reg_item, buf, len);
}
@ -989,13 +1015,13 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
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;
@ -1008,7 +1034,7 @@ int diag_process_apps_pkt(unsigned char *buf, int 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;
}
/* Check for time sync switch command */
@ -1019,14 +1045,14 @@ int diag_process_apps_pkt(unsigned char *buf, int 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;
}
/* 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);
@ -1046,7 +1072,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
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;
}
}
@ -1055,7 +1081,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
(*(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 */
@ -1064,7 +1090,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
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 */
@ -1075,7 +1101,7 @@ int diag_process_apps_pkt(unsigned char *buf, int 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;
}
}
@ -1095,7 +1121,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
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 */
@ -1108,14 +1134,14 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
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,
@ -1127,7 +1153,7 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
* 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
@ -1135,10 +1161,13 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
*/
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;
@ -1147,13 +1176,12 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
/* 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 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;
@ -1213,7 +1241,7 @@ void diag_process_hdlc_pkt(void *data, unsigned len,
}
err = diag_process_apps_pkt(driver->hdlc_buf,
driver->hdlc_buf_len, info);
driver->hdlc_buf_len, pid);
if (err < 0)
goto fail;
} else {
@ -1230,7 +1258,7 @@ fail:
* 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);
@ -1327,9 +1355,11 @@ static int diagfwd_mux_close(int id, int mode)
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)
@ -1371,15 +1401,16 @@ void diag_md_hdlc_reset_timer_func(unsigned long pid)
}
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++) {
@ -1398,10 +1429,13 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len,
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);
@ -1414,12 +1448,11 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len,
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;
@ -1475,11 +1508,11 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len,
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);
@ -1501,8 +1534,8 @@ start:
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);
@ -1510,7 +1543,7 @@ start:
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)) {
@ -1527,13 +1560,13 @@ start:
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;
@ -1552,9 +1585,9 @@ static int diagfwd_mux_read_done(unsigned char *buf, int len, int ctxt)
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;

View file

@ -30,10 +30,8 @@
int diagfwd_init(void);
void diagfwd_exit(void);
void diag_process_hdlc_pkt(void *data, unsigned 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_cmd_get_mobile_id(unsigned char *src_buf, int src_len,
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);

View file

@ -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
@ -316,14 +316,13 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info,
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) {
@ -638,12 +637,13 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
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;