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

Commit 8591d0f0 authored by Zaheerulla Meer's avatar Zaheerulla Meer
Browse files

soc: qcom: smd: Validate read and write addresses



The address from which data has to be read and the address to which the
SMD data has to be written are calculated based on the head and tail
pointers for that SMD FIFO. As these pointer values depend on SMEM
content, there is a possibility that these values could be invalid due
to corruption of SMEM.

Validate the read and write addresses to be with in the limits of
receive and send FIFO limits respectively.

CRs-Fixed: 550527
Change-Id: Idb8ef3b3ad434fdd099271f760988fde4bd0b143
Signed-off-by: default avatarZaheerulla Meer <zmeer@codeaurora.org>
parent 538c521c
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -1183,12 +1183,18 @@ static unsigned ch_read_buffer(struct smd_channel *ch, void **ptr)
{
	unsigned head = ch->half_ch->get_head(ch->recv);
	unsigned tail = ch->half_ch->get_tail(ch->recv);
	*ptr = (void *) (ch->recv_data + tail);
	unsigned fifo_size = ch->fifo_size;

	BUG_ON(fifo_size >= SZ_1M);
	BUG_ON(head >= fifo_size);
	BUG_ON(tail >= fifo_size);
	BUG_ON(OVERFLOW_ADD_UNSIGNED(uintptr_t, (uintptr_t)ch->recv_data,
								tail));
	*ptr = (void *) (ch->recv_data + tail);
	if (tail <= head)
		return head - tail;
	else
		return ch->fifo_size - tail;
		return fifo_size - tail;
}

static int read_intr_blocked(struct smd_channel *ch)
@@ -1288,16 +1294,23 @@ static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr)
{
	unsigned head = ch->half_ch->get_head(ch->send);
	unsigned tail = ch->half_ch->get_tail(ch->send);
	*ptr = (void *) (ch->send_data + head);
	unsigned fifo_size = ch->fifo_size;

	BUG_ON(fifo_size >= SZ_1M);
	BUG_ON(head >= fifo_size);
	BUG_ON(tail >= fifo_size);
	BUG_ON(OVERFLOW_ADD_UNSIGNED(uintptr_t, (uintptr_t)ch->send_data,
								tail));

	*ptr = (void *) (ch->send_data + head);
	if (head < tail) {
		return tail - head - SMD_FIFO_FULL_RESERVE;
	} else {
		if (tail < SMD_FIFO_FULL_RESERVE)
			return ch->fifo_size + tail - head
			return fifo_size + tail - head
					- SMD_FIFO_FULL_RESERVE;
		else
			return ch->fifo_size - head;
			return fifo_size - head;
	}
}

+0 −11
Original line number Diff line number Diff line
@@ -31,17 +31,6 @@

#include "smem_private.h"

/**
 * OVERFLOW_ADD_UNSIGNED() - check for unsigned overflow
 *
 * @type: type to check for overflow
 * @a: left value to use
 * @b: right value to use
 * @returns: true if a + b will result in overflow; false otherwise
 */
#define OVERFLOW_ADD_UNSIGNED(type, a, b) \
	(((type)~0 - (a)) < (b) ? true : false)

#define MODEM_SBL_VERSION_INDEX 7
#define SMEM_VERSION_INFO_SIZE (32 * 4)
#define SMEM_VERSION 0x000B
+11 −0
Original line number Diff line number Diff line
@@ -40,6 +40,17 @@ enum {

#define SMEM_NUM_SMD_STREAM_CHANNELS        64

/**
 * OVERFLOW_ADD_UNSIGNED() - check for unsigned overflow
 *
 * @type: type to check for overflow
 * @a: left value to use
 * @b: right value to use
 * @returns: true if a + b will result in overflow; false otherwise
 */
#define OVERFLOW_ADD_UNSIGNED(type, a, b) \
	(((type)~0 - (a)) < (b) ? true : false)

enum {
	/* fixed items */
	SMEM_PROC_COMM = 0,