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

Commit dd93fd94 authored by Katish Paran's avatar Katish Paran Committed by Gerrit - the friendly Code Review server
Browse files

diag: dci: Add mutex protection while accessing client details



Currently while extracting events and logs information from
the data read over peripherals, the clients details are accessed
without mutex protection. As the client access may happen from
multiple context, mutex protection is needed. This patch
resolves the same.

Change-Id: I9bd115e1cd9eebc625f4a68854d554ff874d866d
Signed-off-by: default avatarKatish Paran <kparan@codeaurora.org>
parent d3846f3c
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -343,6 +343,7 @@ void diag_dci_wakeup_clients()
	struct list_head *start, *temp;
	struct diag_dci_client_tbl *entry = NULL;

	mutex_lock(&driver->dci_mutex);
	list_for_each_safe(start, temp, &driver->dci_client_list) {
		entry = list_entry(start, struct diag_dci_client_tbl, track);

@@ -358,6 +359,7 @@ void diag_dci_wakeup_clients()
						     DCI_DATA_TYPE);
		}
	}
	mutex_unlock(&driver->dci_mutex);
}

void dci_data_drain_work_fn(struct work_struct *work)
@@ -368,6 +370,7 @@ void dci_data_drain_work_fn(struct work_struct *work)
	struct diag_dci_buf_peripheral_t *proc_buf = NULL;
	struct diag_dci_buffer_t *buf_temp = NULL;

	mutex_lock(&driver->dci_mutex);
	list_for_each_safe(start, temp, &driver->dci_client_list) {
		entry = list_entry(start, struct diag_dci_client_tbl, track);
		for (i = 0; i < entry->num_buffers; i++) {
@@ -397,6 +400,7 @@ void dci_data_drain_work_fn(struct work_struct *work)
						     DCI_DATA_TYPE);
		}
	}
	mutex_unlock(&driver->dci_mutex);
	dci_timer_in_progress = 0;
}

@@ -562,6 +566,8 @@ start:
		buf += header_len + dci_pkt_len; /* advance to next DCI pkt */
	}
end:
	if (err)
		return;
	/* wake up all sleeping DCI clients which have some data */
	diag_dci_wakeup_clients();
	dci_check_drain_timer();
@@ -623,6 +629,8 @@ void diag_dci_process_peripheral_data(struct diagfwd_info *p_info, void *buf,
		buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
	}

	if (err)
		return;
	/* wake up all sleeping DCI clients which have some data */
	diag_dci_wakeup_clients();
	dci_check_drain_timer();
@@ -970,9 +978,11 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
		return;
	}

	mutex_lock(&driver->dci_mutex);
	req_entry = diag_dci_get_request_entry(tag);
	if (!req_entry) {
		pr_err("diag: No matching client for DCI data\n");
		pr_err_ratelimited("diag: No matching client for DCI data\n");
		mutex_unlock(&driver->dci_mutex);
		return;
	}

@@ -980,18 +990,17 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
	if (!entry) {
		pr_err("diag: In %s, couldn't find client entry, id:%d\n",
						__func__, req_entry->client_id);
		mutex_unlock(&driver->dci_mutex);
		return;
	}

	save_req_uid = req_entry->uid;
	/* Remove the headers and send only the response to this function */
	mutex_lock(&driver->dci_mutex);
	delete_flag = diag_dci_remove_req_entry(temp, rsp_len, req_entry);
	if (delete_flag < 0) {
		mutex_unlock(&driver->dci_mutex);
		return;
	}
	mutex_unlock(&driver->dci_mutex);

	mutex_lock(&entry->buffers[data_source].buf_mutex);
	rsp_buf = entry->buffers[data_source].buf_cmd;
@@ -1011,6 +1020,7 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
			pr_err("diag: DCI realloc failed\n");
			mutex_unlock(&rsp_buf->data_mutex);
			mutex_unlock(&entry->buffers[data_source].buf_mutex);
			mutex_unlock(&driver->dci_mutex);
			return;
		} else {
			rsp_buf->data = temp_buf;
@@ -1039,6 +1049,7 @@ void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source,
	 */
	dci_add_buffer_to_list(entry, rsp_buf);
	mutex_unlock(&entry->buffers[data_source].buf_mutex);
	mutex_unlock(&driver->dci_mutex);
}

static void copy_dci_event(unsigned char *buf, int len,
@@ -1174,6 +1185,7 @@ void extract_dci_events(unsigned char *buf, int len, int data_source, int token)
		   the event data */
		total_event_len = 2 + 10 + payload_len_field + payload_len;
		/* parse through event mask tbl of each client and check mask */
		mutex_lock(&driver->dci_mutex);
		list_for_each_safe(start, temp, &driver->dci_client_list) {
			entry = list_entry(start, struct diag_dci_client_tbl,
									track);
@@ -1185,6 +1197,7 @@ void extract_dci_events(unsigned char *buf, int len, int data_source, int token)
					       entry, data_source);
			}
		}
		mutex_unlock(&driver->dci_mutex);
	}
}

@@ -1276,6 +1289,7 @@ void extract_dci_log(unsigned char *buf, int len, int data_source, int token)
	}

	/* parse through log mask table of each client and check mask */
	mutex_lock(&driver->dci_mutex);
	list_for_each_safe(start, temp, &driver->dci_client_list) {
		entry = list_entry(start, struct diag_dci_client_tbl, track);
		if (entry->client_info.token != token)
@@ -1287,6 +1301,7 @@ void extract_dci_log(unsigned char *buf, int len, int data_source, int token)
			copy_dci_log(buf, len, entry, data_source);
		}
	}
	mutex_unlock(&driver->dci_mutex);
}

void diag_dci_channel_open_work(struct work_struct *work)
+23 −9
Original line number Diff line number Diff line
@@ -2393,7 +2393,10 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
		goto exit;
	}

exit:
	mutex_unlock(&driver->diagchar_mutex);
	if (driver->data_ready[index] & DCI_DATA_TYPE) {
		mutex_lock(&driver->dci_mutex);
		/* Copy the type of data being passed */
		data_type = driver->data_ready[index] & DCI_DATA_TYPE;
		list_for_each_safe(start, temp, &driver->dci_client_list) {
@@ -2403,20 +2406,31 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
				continue;
			if (!entry->in_service)
				continue;
			COPY_USER_SPACE_OR_EXIT(buf + ret, data_type,
								sizeof(int));
			COPY_USER_SPACE_OR_EXIT(buf + ret,
					entry->client_info.token, sizeof(int));
			if (copy_to_user(buf + ret, &data_type, sizeof(int))) {
				mutex_unlock(&driver->dci_mutex);
				goto end;
			}
			ret += sizeof(int);
			if (copy_to_user(buf + ret, &entry->client_info.token,
				sizeof(int))) {
				mutex_unlock(&driver->dci_mutex);
				goto end;
			}
			ret += sizeof(int);
			copy_dci_data = 1;
			exit_stat = diag_copy_dci(buf, count, entry, &ret);
			mutex_lock(&driver->diagchar_mutex);
			driver->data_ready[index] ^= DCI_DATA_TYPE;
			if (exit_stat == 1)
				goto exit;
			mutex_unlock(&driver->diagchar_mutex);
			if (exit_stat == 1) {
				mutex_unlock(&driver->dci_mutex);
				goto end;
			}
		goto exit;
		}
exit:
	mutex_unlock(&driver->diagchar_mutex);
		mutex_unlock(&driver->dci_mutex);
		goto end;
	}
end:
	/*
	 * Flush any read that is currently pending on DCI data and
	 * command channnels. This will ensure that the next read is not