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

Commit e76df881 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 is calculated based on the head and tail
indices for that SMD FIFO. If the indices are corrupted, then the
calculated pointer may be outside of the FIFO and may even be outside of
the range 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: Ie5578f6aee73ea2b1435fea7c2a0a6dda14bff82
Signed-off-by: default avatarZaheerulla Meer <zmeer@codeaurora.org>
parent e4dda9ff
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,
								head));

	*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,