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

Commit 3b63d875 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 initializing msg mask"

parents 960a9b09 c2234e93
Loading
Loading
Loading
Loading
+66 −20
Original line number Diff line number Diff line
@@ -336,12 +336,13 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)
	int header_len = sizeof(struct diag_ctrl_msg_mask);
	uint8_t *buf = NULL, *temp = NULL;
	uint8_t upd = 0;
	uint8_t msg_mask_tbl_count_local;
	uint8_t msg_mask_tbl_count_local = 0;
	uint32_t mask_size = 0, pd_mask = 0;
	struct diag_mask_info *mask_info = NULL;
	struct diag_msg_mask_t *mask = NULL;
	struct diag_ctrl_msg_mask header;
	struct diagfwd_info *fwd_info = NULL;
	struct diag_md_session_t *md_session_info = NULL;

	if (peripheral >= NUM_PERIPHERALS)
		return;
@@ -357,14 +358,19 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)

	if (driver->md_session_mask != 0) {
		if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
			if (driver->md_session_map[peripheral])
			if (driver->md_session_map[peripheral]) {
				mask_info =
				driver->md_session_map[peripheral]->msg_mask;
				md_session_info =
					driver->md_session_map[peripheral];
			}
		} else if (driver->md_session_mask & pd_mask) {
			upd = diag_mask_to_pd_value(driver->md_session_mask);
			if (upd && driver->md_session_map[upd])
			if (upd && driver->md_session_map[upd]) {
				mask_info =
				driver->md_session_map[upd]->msg_mask;
				md_session_info = driver->md_session_map[upd];
			}
		} else {
			DIAG_LOG(DIAG_DEBUG_MASKS,
			"asking for mask update with unknown session mask\n");
@@ -383,6 +389,9 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)
		return;
	}
	buf = mask_info->update_buf;
	if (md_session_info)
		msg_mask_tbl_count_local = md_session_info->msg_mask_tbl_count;
	else
		msg_mask_tbl_count_local = driver->msg_mask_tbl_count;
	mutex_unlock(&driver->msg_mask_lock);
	mutex_lock(&mask_info->lock);
@@ -565,6 +574,7 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
{
	int i;
	int write_len = 0;
	uint8_t msg_mask_tbl_count = 0;
	struct diag_msg_mask_t *mask_ptr = NULL;
	struct diag_msg_ssid_query_t rsp;
	struct diag_ssid_range_t ssid_range;
@@ -594,15 +604,17 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
		return 0;
	}
	mutex_lock(&driver->msg_mask_lock);
	msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count :
		driver->msg_mask_tbl_count;
	rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
	rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
	rsp.status = MSG_STATUS_SUCCESS;
	rsp.padding = 0;
	rsp.count = driver->msg_mask_tbl_count;
	rsp.count = msg_mask_tbl_count;
	memcpy(dest_buf, &rsp, sizeof(rsp));
	write_len += sizeof(rsp);
	mask_ptr = (struct diag_msg_mask_t *)mask_info->ptr;
	for (i = 0; i <  driver->msg_mask_tbl_count; i++, mask_ptr++) {
	for (i = 0; i < msg_mask_tbl_count; i++, mask_ptr++) {
		if (write_len + sizeof(ssid_range) > dest_len) {
			pr_err("diag: In %s, Truncating response due to size limitations of rsp buffer\n",
			       __func__);
@@ -679,6 +691,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
	int i;
	int write_len = 0;
	uint32_t mask_size = 0;
	uint8_t msg_mask_tbl_count = 0;
	struct diag_msg_mask_t *mask = NULL;
	struct diag_build_mask_req_t *req = NULL;
	struct diag_msg_build_mask_t rsp;
@@ -709,6 +722,8 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
	}

	mutex_lock(&driver->msg_mask_lock);
	msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count :
			driver->msg_mask_tbl_count;
	req = (struct diag_build_mask_req_t *)src_buf;
	rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
	rsp.sub_cmd = DIAG_CMD_OP_GET_MSG_MASK;
@@ -724,7 +739,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
		mutex_unlock(&driver->md_session_lock);
		return -EINVAL;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
	for (i = 0; i < msg_mask_tbl_count; i++, mask++) {
		if (!mask->ptr)
			continue;
		if ((req->ssid_first < mask->ssid_first) ||
@@ -760,6 +775,7 @@ 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;
	struct diag_md_session_t *info = NULL;
	uint8_t msg_mask_tbl_count = 0;

	mutex_lock(&driver->md_session_lock);
	info = diag_md_session_get_pid(pid);
@@ -792,10 +808,13 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
		mutex_unlock(&driver->md_session_lock);
		return -EINVAL;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {

	msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count :
			driver->msg_mask_tbl_count;
	for (i = 0; i < msg_mask_tbl_count; i++, mask++) {
		if (!mask->ptr)
			continue;
		if (i < (driver->msg_mask_tbl_count - 1)) {
		if (i < (msg_mask_tbl_count - 1)) {
			mask_next = mask;
			mask_next++;
		} else
@@ -905,6 +924,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
	struct diag_msg_mask_t *mask = NULL;
	struct diag_mask_info *mask_info = NULL;
	struct diag_md_session_t *info = NULL;
	uint8_t msg_mask_tbl_count = 0;

	mutex_lock(&driver->md_session_lock);
	info = diag_md_session_get_pid(pid);
@@ -939,9 +959,11 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
		mutex_unlock(&driver->md_session_lock);
		return -EINVAL;
	}
	msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count :
			driver->msg_mask_tbl_count;
	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++) {
	for (i = 0; i < msg_mask_tbl_count; i++, mask++) {
		if (mask && mask->ptr) {
			mutex_lock(&mask->lock);
			memset(mask->ptr, req->rt_mask,
@@ -1755,7 +1777,6 @@ static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len,
		}
		kmemleak_not_leak(mask_info->update_buf);
	}
	mutex_init(&mask_info->lock);
	return 0;
}

@@ -1778,9 +1799,10 @@ int diag_log_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
	struct diag_log_mask_t *src_mask = NULL;
	struct diag_log_mask_t *dest_mask = NULL;

	if (!src)
	if (!src || !dest)
		return -EINVAL;

	mutex_init(&dest->lock);
	err = __diag_mask_init(dest, LOG_MASK_SIZE, APPS_BUF_SIZE);
	if (err)
		return err;
@@ -1842,9 +1864,11 @@ static int diag_msg_mask_init(void)
{
	int err = 0, i;

	mutex_init(&msg_mask.lock);
	err = __diag_mask_init(&msg_mask, MSG_MASK_SIZE, APPS_BUF_SIZE);
	if (err)
		return err;

	err = diag_create_msg_mask_table();
	if (err) {
		pr_err("diag: Unable to create msg masks, err: %d\n", err);
@@ -1859,7 +1883,8 @@ static int diag_msg_mask_init(void)
	return 0;
}

int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
int diag_msg_mask_copy(struct diag_md_session_t *new_session,
	struct diag_mask_info *dest, struct diag_mask_info *src)
{
	int i, err = 0, mask_size = 0;
	struct diag_msg_mask_t *src_mask = NULL;
@@ -1869,17 +1894,25 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
	if (!src || !dest)
		return -EINVAL;

	err = __diag_mask_init(dest, MSG_MASK_SIZE, APPS_BUF_SIZE);
	if (err)
		return err;
	mutex_init(&dest->lock);
	mutex_lock(&dest->lock);
	mutex_lock(&driver->msg_mask_lock);
	new_session->msg_mask_tbl_count =
		driver->msg_mask_tbl_count;
	err = __diag_mask_init(dest,
		(new_session->msg_mask_tbl_count *
		sizeof(struct diag_msg_mask_t)), APPS_BUF_SIZE);
	if (err) {
		mutex_unlock(&driver->msg_mask_lock);
		mutex_unlock(&dest->lock);
		return err;
	}
	src_mask = (struct diag_msg_mask_t *)src->ptr;
	dest_mask = (struct diag_msg_mask_t *)dest->ptr;

	dest->mask_len = src->mask_len;
	dest->status = src->status;
	for (i = 0; i < driver->msg_mask_tbl_count; i++) {
	for (i = 0; i < new_session->msg_mask_tbl_count; i++) {
		range.ssid_first = src_mask->ssid_first;
		range.ssid_last = src_mask->ssid_last;
		err = diag_create_msg_mask_table_entry(dest_mask, &range);
@@ -1898,10 +1931,12 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
	return err;
}

void diag_msg_mask_free(struct diag_mask_info *mask_info)
void diag_msg_mask_free(struct diag_mask_info *mask_info,
	struct diag_md_session_t *session_info)
{
	int i;
	struct diag_msg_mask_t *mask = NULL;
	uint8_t msg_mask_tbl_count = 0;

	if (!mask_info || !mask_info->ptr)
		return;
@@ -1915,7 +1950,10 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info)
		mutex_unlock(&mask_info->lock);
		return;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
	msg_mask_tbl_count = (session_info) ?
		session_info->msg_mask_tbl_count :
		driver->msg_mask_tbl_count;
	for (i = 0; i < msg_mask_tbl_count; i++, mask++) {
		kfree(mask->ptr);
		mask->ptr = NULL;
	}
@@ -1946,6 +1984,7 @@ static int diag_build_time_mask_init(void)
	int err = 0;

	/* There is no need for update buffer for Build Time masks */
	mutex_init(&msg_bt_mask.lock);
	err = __diag_mask_init(&msg_bt_mask, MSG_MASK_SIZE, 0);
	if (err)
		return err;
@@ -1978,6 +2017,7 @@ static int diag_log_mask_init(void)
{
	int err = 0, i;

	mutex_init(&log_mask.lock);
	err = __diag_mask_init(&log_mask, LOG_MASK_SIZE, APPS_BUF_SIZE);
	if (err)
		return err;
@@ -2011,6 +2051,7 @@ static int diag_event_mask_init(void)
{
	int err = 0, i;

	mutex_init(&event_mask.lock);
	err = __diag_mask_init(&event_mask, EVENT_MASK_SIZE, APPS_BUF_SIZE);
	if (err)
		return err;
@@ -2032,6 +2073,7 @@ int diag_event_mask_copy(struct diag_mask_info *dest,
	if (!src || !dest)
		return -EINVAL;

	mutex_init(&dest->lock);
	err = __diag_mask_init(dest, EVENT_MASK_SIZE, APPS_BUF_SIZE);
	if (err)
		return err;
@@ -2068,6 +2110,7 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
	struct diag_mask_info *mask_info = NULL;
	struct diag_msg_mask_t *mask = NULL;
	unsigned char *ptr = NULL;
	uint8_t msg_mask_tbl_count = 0;

	if (!buf || count == 0)
		return -EINVAL;
@@ -2092,7 +2135,10 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
		mutex_unlock(&mask_info->lock);
		return -EINVAL;
	}
	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {

	msg_mask_tbl_count = (info) ? info->msg_mask_tbl_count :
			driver->msg_mask_tbl_count;
	for (i = 0; i < msg_mask_tbl_count; i++, mask++) {
		if (!mask->ptr)
			continue;
		ptr = mask_info->update_buf;
+4 −3
Original line number Diff line number Diff line
@@ -160,12 +160,13 @@ int diag_masks_init(void);
void diag_masks_exit(void);
int diag_log_mask_copy(struct diag_mask_info *dest,
		       struct diag_mask_info *src);
int diag_msg_mask_copy(struct diag_mask_info *dest,
		       struct diag_mask_info *src);
int diag_msg_mask_copy(struct diag_md_session_t *new_session,
	struct diag_mask_info *dest, struct diag_mask_info *src);
int diag_event_mask_copy(struct diag_mask_info *dest,
			 struct diag_mask_info *src);
void diag_log_mask_free(struct diag_mask_info *mask_info);
void diag_msg_mask_free(struct diag_mask_info *mask_info);
void diag_msg_mask_free(struct diag_mask_info *mask_info,
	struct diag_md_session_t *session_info);
void diag_event_mask_free(struct diag_mask_info *mask_info);
int diag_process_apps_masks(unsigned char *buf, int len, int pid);
void diag_send_updates_peripheral(uint8_t peripheral);
+1 −0
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ struct diag_md_session_t {
	int pid;
	int peripheral_mask;
	uint8_t hdlc_disabled;
	uint8_t msg_mask_tbl_count;
	struct timer_list hdlc_reset_timer;
	struct diag_mask_info *msg_mask;
	struct diag_mask_info *log_mask;
+9 −4
Original line number Diff line number Diff line
@@ -1264,7 +1264,8 @@ static void diag_md_session_exit(void)
			diag_log_mask_free(session_info->log_mask);
			kfree(session_info->log_mask);
			session_info->log_mask = NULL;
			diag_msg_mask_free(session_info->msg_mask);
			diag_msg_mask_free(session_info->msg_mask,
				session_info);
			kfree(session_info->msg_mask);
			session_info->msg_mask = NULL;
			diag_event_mask_free(session_info->event_mask);
@@ -1335,7 +1336,9 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
			 "return value of event copy. err %d\n", err);
		goto fail_peripheral;
	}
	err = diag_msg_mask_copy(new_session->msg_mask, &msg_mask);
	new_session->msg_mask_tbl_count = 0;
	err = diag_msg_mask_copy(new_session, new_session->msg_mask,
		&msg_mask);
	if (err) {
		DIAG_LOG(DIAG_DEBUG_USERSPACE,
			 "return value of msg copy. err %d\n", err);
@@ -1371,7 +1374,8 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
	diag_event_mask_free(new_session->event_mask);
	kfree(new_session->event_mask);
	new_session->event_mask = NULL;
	diag_msg_mask_free(new_session->msg_mask);
	diag_msg_mask_free(new_session->msg_mask,
		new_session);
	kfree(new_session->msg_mask);
	new_session->msg_mask = NULL;
	kfree(new_session);
@@ -1399,7 +1403,8 @@ static void diag_md_session_close(int pid)
	diag_log_mask_free(session_info->log_mask);
	kfree(session_info->log_mask);
	session_info->log_mask = NULL;
	diag_msg_mask_free(session_info->msg_mask);
	diag_msg_mask_free(session_info->msg_mask,
		session_info);
	kfree(session_info->msg_mask);
	session_info->msg_mask = NULL;
	diag_event_mask_free(session_info->event_mask);