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

Commit dedb3ae3 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "diag: Prevent out-of-bound access while processing userspace data"

parents ae80e9d7 726f26d2
Loading
Loading
Loading
Loading
+20 −17
Original line number Diff line number Diff line
@@ -641,7 +641,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
	struct diag_build_mask_req_t *req = NULL;
	struct diag_msg_build_mask_t rsp;

	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
	if (!src_buf || !dest_buf || dest_len <= 0 ||
		src_len < sizeof(struct diag_build_mask_req_t)) {
		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);
@@ -703,7 +703,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
	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 ||
	if (!src_buf || !dest_buf || dest_len <= 0 ||
	    !mask_info || (src_len < sizeof(struct diag_build_mask_req_t))) {
		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,
@@ -782,8 +782,8 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
	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) {
	if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
		(src_len < sizeof(struct diag_msg_build_mask_t))) {
		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);
@@ -867,7 +867,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
			break;
		}
		mask_size = mask_size * sizeof(uint32_t);
		memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
		if (mask_size && src_len >= header_len + mask_size)
			memcpy(mask->ptr + offset, src_buf + header_len,
				mask_size);
		mutex_unlock(&mask->lock);
		mask_info->status = DIAG_CTRL_MASK_VALID;
		break;
@@ -930,8 +932,8 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
	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) {
	if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
		(src_len < sizeof(struct diag_msg_config_rsp_t))) {
		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);
@@ -1054,8 +1056,8 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
	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) {
	if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
		src_len < sizeof(struct diag_event_mask_config_t)) {
		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);
@@ -1078,6 +1080,7 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
	}

	mutex_lock(&mask_info->lock);
	if (src_len >= header_len + mask_len)
		memcpy(mask_info->ptr, src_buf + header_len, mask_len);
	mask_info->status = DIAG_CTRL_MASK_VALID;
	mutex_unlock(&mask_info->lock);
@@ -1127,8 +1130,8 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
	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) {
	if (!src_buf || !dest_buf || src_len <= sizeof(uint8_t) ||
		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);
@@ -1201,8 +1204,8 @@ static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
	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 ||
	    !mask_info) {
	if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
		src_len < sizeof(struct diag_log_config_req_t)) {
		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);
@@ -1343,8 +1346,8 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
	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 ||
	    !mask_info) {
	if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
		src_len < sizeof(struct diag_log_config_req_t)) {
		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);
@@ -1418,7 +1421,7 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
			mask->range_tools = mask_size;
		}
		req->num_items = mask->num_items_tools;
		if (mask_size > 0)
		if (mask_size > 0 && src_len >= read_len + mask_size)
			memcpy(mask->ptr, src_buf + read_len, mask_size);
		DIAG_LOG(DIAG_DEBUG_MASKS,
			 "copying log mask, e %d num %d range %d size %d\n",
+11 −4
Original line number Diff line number Diff line
@@ -1179,15 +1179,19 @@ static int diag_process_userspace_remote(int proc, void *buf, int len)
}
#endif

static int mask_request_validate(unsigned char mask_buf[])
static int mask_request_validate(unsigned char mask_buf[], int len)
{
	uint8_t packet_id;
	uint8_t subsys_id;
	uint16_t ss_cmd;

	if (len <= 0)
		return 0;
	packet_id = mask_buf[0];

	if (packet_id == DIAG_CMD_DIAG_SUBSYS_DELAY) {
		if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
			return 0;
		subsys_id = mask_buf[1];
		ss_cmd = *(uint16_t *)(mask_buf + 2);
		switch (subsys_id) {
@@ -1203,6 +1207,8 @@ static int mask_request_validate(unsigned char mask_buf[])
			return 0;
		}
	} else if (packet_id == 0x4B) {
		if (len < 2*sizeof(uint8_t) + sizeof(uint16_t))
			return 0;
		subsys_id = mask_buf[1];
		ss_cmd = *(uint16_t *)(mask_buf + 2);
		/* Packets with SSID which are allowed */
@@ -3209,6 +3215,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
	}

	/* Check for proc_type */
	if (len >= sizeof(int))
		remote_proc = diag_get_remote(*(int *)user_space_data);
	if (remote_proc) {
		token_offset = sizeof(int);
@@ -3223,7 +3230,7 @@ static int diag_user_process_raw_data(const char __user *buf, int len)
	}
	if (driver->mask_check) {
		if (!mask_request_validate(user_space_data +
						token_offset)) {
						token_offset, len)) {
			pr_alert("diag: mask request Invalid\n");
			diagmem_free(driver, user_space_data, mempool);
			user_space_data = NULL;
@@ -3301,7 +3308,7 @@ static int diag_user_process_userspace_data(const char __user *buf, int len)
	/* Check masks for On-Device logging */
	if (driver->mask_check) {
		if (!mask_request_validate(driver->user_space_data_buf +
					   token_offset)) {
					   token_offset, len)) {
			pr_alert("diag: mask request Invalid\n");
			return -EFAULT;
		}