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

Commit 296ae399 authored by Hardik Arya's avatar Hardik Arya
Browse files

soc: qcom: glink_spi_xprt: Validate fifo read index of remote side



Since message received from spi cannot be trusted there is possibility
of out-of-bound read if received read_id is not in range of fifo.
The patch validate rx_fifo_read index of edge info for remote side.

Change-Id: I3d3fa749935f477e5f98f986adc24e6e6a682d4d
Signed-off-by: default avatarHardik Arya <harya@codeaurora.org>
parent 378dc16e
Loading
Loading
Loading
Loading
+30 −3
Original line number Diff line number Diff line
/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 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
@@ -484,6 +484,13 @@ static int glink_spi_xprt_rx_cmd(struct edge_info *einfo, void *dst,
	int ret;

	read_id = einfo->rx_fifo_read;
	if ((read_id > (einfo->rx_fifo_start + einfo->fifo_size)) ||
		(read_id < einfo->rx_fifo_start)) {
		pr_err("%s: Invalid rx_fifo_read: %d, start: %d, size: %d\n",
			__func__, read_id, einfo->rx_fifo_start,
			einfo->fifo_size);
		return -EINVAL;
	}
	do {
		if ((read_id + size_to_read) >=
		    (einfo->rx_fifo_start + einfo->fifo_size))
@@ -722,11 +729,11 @@ static void process_rx_cmd(struct edge_info *einfo,
	struct rx_short_data_desc {
		unsigned char data[SHORT_PKT_SIZE];
	};
	struct command *cmd;
	struct command *cmd = NULL;
	struct intent_desc *intents;
	struct rx_desc *rx_descp;
	struct rx_short_data_desc *rx_sd_descp;
	int offset = 0;
	uint64_t offset = 0;
	int rcu_id;
	uint16_t rcid;
	uint16_t name_len;
@@ -742,6 +749,8 @@ static void process_rx_cmd(struct edge_info *einfo,
	}

	while (offset < rx_size) {
		if (offset + sizeof(*cmd) > rx_size)
			goto err;
		cmd = (struct command *)(rx_data + offset);
		offset += sizeof(*cmd);
		switch (cmd->id) {
@@ -760,7 +769,12 @@ static void process_rx_cmd(struct edge_info *einfo,
		case OPEN_CMD:
			rcid = cmd->param1;
			name_len = (uint16_t)(cmd->param2 & 0xFFFF);
			if (name_len > GLINK_NAME_SIZE)
				goto err;
			prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
			if (offset + ALIGN(name_len, FIFO_ALIGNMENT) >
				rx_size)
				goto err;
			name = (char *)(rx_data + offset);
			offset += ALIGN(name_len, FIFO_ALIGNMENT);
			einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
@@ -786,6 +800,8 @@ static void process_rx_cmd(struct edge_info *einfo,

		case RX_INTENT_CMD:
			for (i = 0; i < cmd->param2; i++) {
				if (offset + sizeof(*intents) > rx_size)
					goto err;
				intents = (struct intent_desc *)
						(rx_data + offset);
				offset += sizeof(*intents);
@@ -821,6 +837,8 @@ static void process_rx_cmd(struct edge_info *einfo,
		case TX_DATA_CONT_CMD:
		case TRACER_PKT_CMD:
		case TRACER_PKT_CONT_CMD:
			if (offset + sizeof(*rx_descp) > rx_size)
				goto err;
			rx_descp = (struct rx_desc *)(rx_data + offset);
			offset += sizeof(*rx_descp);
			process_rx_data(einfo, cmd->id, cmd->param1,
@@ -830,6 +848,8 @@ static void process_rx_cmd(struct edge_info *einfo,
			break;

		case TX_SHORT_DATA_CMD:
			if (offset + sizeof(*rx_sd_descp) > rx_size)
				goto err;
			rx_sd_descp = (struct rx_short_data_desc *)
							(rx_data + offset);
			offset += sizeof(*rx_sd_descp);
@@ -858,6 +878,13 @@ static void process_rx_cmd(struct edge_info *einfo,
		}
	}
	srcu_read_unlock(&einfo->use_ref, rcu_id);
	return;
err:
	srcu_read_unlock(&einfo->use_ref, rcu_id);
	if (cmd)
		pr_err("%s: invalid size of rx_data: %d, cmd : %d\n",
			__func__, rx_size, cmd->id);
	return;
}

/**