Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4cc5a44 authored by Hardik Arya's avatar Hardik Arya
Browse files

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



Currently there is a possibility of accessing freed mdlog
session info and it's attributes after closing the session.
The patch adds protection while accessing mdlog session info
for preventing use-after-free issue.

CRs-Fixed: 2133028
Change-Id: Iba603bc2d75f84a604df2627e8fcb2a18acf4637
Signed-off-by: default avatarHardik Arya <harya@codeaurora.org>
parent 91dc07c0
Loading
Loading
Loading
Loading
+219 −51
Original line number Diff line number Diff line
/* 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
@@ -482,8 +482,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;
@@ -491,19 +490,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;
@@ -525,13 +535,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;
@@ -586,8 +595,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;
@@ -596,6 +604,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 ||
@@ -603,11 +615,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 (!diag_apps_responds())
	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()) {
		mutex_unlock(&driver->md_session_lock);
		return 0;
	}

	mutex_lock(&driver->msg_mask_lock);
	req = (struct diag_build_mask_req_t *)src_buf;
@@ -618,6 +638,13 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
	rsp.status = MSG_STATUS_FAIL;
	rsp.padding = 0;
	mask = (struct diag_msg_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->msg_mask_lock);
		mutex_unlock(&driver->md_session_lock);
		return -EINVAL;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
		if ((req->ssid_first < mask->ssid_first) ||
		    (req->ssid_first > mask->ssid_last_tools)) {
@@ -635,13 +662,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;
@@ -655,6 +681,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 ||
@@ -662,6 +692,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;
	}

@@ -669,6 +706,14 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
	mutex_lock(&mask_info->lock);
	mutex_lock(&driver->msg_mask_lock);
	mask = (struct diag_msg_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->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++) {
		if (i < (driver->msg_mask_tbl_count - 1)) {
			mask_next = mask;
@@ -709,6 +754,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;
@@ -729,6 +775,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);

@@ -760,8 +807,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;
@@ -770,6 +816,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 ||
@@ -777,6 +827,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;
	}

@@ -786,6 +843,14 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
	mutex_lock(&driver->msg_mask_lock);

	mask = (struct diag_msg_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->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 :
					   DIAG_CTRL_MASK_ALL_DISABLED;
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -796,7 +861,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);

@@ -822,8 +887,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;
@@ -858,8 +922,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;
@@ -868,21 +931,31 @@ 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;
	mask_len = EVENT_COUNT_TO_BYTES(req->num_bits);
	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;
	}

@@ -890,6 +963,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);

@@ -916,21 +990,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;
	}

@@ -944,6 +1027,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);

@@ -965,8 +1049,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;
@@ -979,6 +1062,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 ||
@@ -986,11 +1073,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;
@@ -1007,6 +1103,12 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
	write_len += rsp_header_len;

	log_item = (struct diag_log_mask_t *)mask_info->ptr;
	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++) {
		if (log_item->equip_id != req->equip_id)
			continue;
@@ -1046,28 +1148,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;
	}

@@ -1090,7 +1191,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;
@@ -1105,6 +1206,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 ||
@@ -1112,13 +1217,25 @@ 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;
	}

	req = (struct diag_log_config_req_t *)src_buf;
	read_len += req_header_len;
	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;
	}
	if (req->equip_id >= MAX_EQUIP_ID) {
		pr_err("diag: In %s, Invalid logging mask request, equip_id: %d\n",
		       __func__, req->equip_id);
@@ -1179,6 +1296,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);

@@ -1217,14 +1335,17 @@ 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;
	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 ||
@@ -1232,17 +1353,29 @@ 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++) {
		mutex_lock(&mask->lock);
		memset(mask->ptr, 0, mask->range);
		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);

@@ -1500,7 +1633,7 @@ static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len,

static void __diag_mask_exit(struct diag_mask_info *mask_info)
{
	if (!mask_info)
	if (!mask_info || !mask_info->ptr)
		return;

	mutex_lock(&mask_info->lock);
@@ -1557,11 +1690,17 @@ void diag_log_mask_free(struct diag_mask_info *mask_info)
	int i;
	struct diag_log_mask_t *mask = NULL;

	if (!mask_info)
	if (!mask_info || !mask_info->ptr)
		return;

	mutex_lock(&mask_info->lock);
	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(&mask_info->lock);
		return;
	}
	for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
		kfree(mask->ptr);
		mask->ptr = NULL;
@@ -1636,11 +1775,18 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info)
	int i;
	struct diag_msg_mask_t *mask = NULL;

	if (!mask_info)
	if (!mask_info || !mask_info->ptr)
		return;
	mutex_lock(&mask_info->lock);
	mutex_lock(&driver->msg_mask_lock);
	mask = (struct diag_msg_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->msg_mask_lock);
		mutex_unlock(&mask_info->lock);
		return;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
		kfree(mask->ptr);
		mask->ptr = NULL;
@@ -1807,6 +1953,11 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
	if (!mask_info)
		return -EIO;

	if (!mask_info->ptr || !mask_info->update_buf) {
		pr_err("diag: In %s, invalid input mask_info->ptr: %pK, mask_info->update_buf: %pK\n",
			__func__, mask_info->ptr, mask_info->update_buf);
		return -EINVAL;
	}
	mutex_lock(&driver->diag_maskclear_mutex);
	if (driver->mask_clear) {
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
@@ -1819,6 +1970,13 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
	mutex_lock(&driver->msg_mask_lock);

	mask = (struct diag_msg_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->msg_mask_lock);
		mutex_unlock(&mask_info->lock);
		return -EINVAL;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
		ptr = mask_info->update_buf;
		len = 0;
@@ -1879,8 +2037,20 @@ int diag_copy_to_user_log_mask(char __user *buf, size_t count,
	if (!mask_info)
		return -EIO;

	if (!mask_info->ptr || !mask_info->update_buf) {
		pr_err("diag: In %s, invalid input mask_info->ptr: %pK, mask_info->update_buf: %pK\n",
			__func__, mask_info->ptr, mask_info->update_buf);
		return -EINVAL;
	}

	mutex_lock(&mask_info->lock);
	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(&mask_info->lock);
		return -EINVAL;
	}
	for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
		ptr = mask_info->update_buf;
		len = 0;
@@ -1933,14 +2103,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;
@@ -1990,7 +2158,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;
}
+2 −3
Original line number Diff line number Diff line
/* 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,
+10 −5
Original line number Diff line number Diff line
/* Copyright (c) 2014-2015, 2016 The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2015, 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
@@ -130,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;
@@ -147,9 +148,14 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx)
	if (peripheral > NUM_PERIPHERALS)
		return -EINVAL;

	mutex_lock(&driver->md_session_lock);
	session_info = diag_md_session_get_peripheral(peripheral);
	if (!session_info)
	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];

@@ -187,8 +193,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;

+2 −2
Original line number Diff line number Diff line
/* 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);
+2 −2
Original line number Diff line number Diff line
/* 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
@@ -630,7 +630,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);

void diag_record_stats(int type, int flag);

Loading