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

Commit 61ead888 authored by Zaheerulla Meer's avatar Zaheerulla Meer
Browse files

msm: smd: Handle corrupted packet header gracefully



SMD library doesn't report error when the SMD packet is of invalid
length(length > 0x7fffffff). When a SMD user(for example SMD_PKT) tries
to read the packet size using an "int" variable the value of packet size
becomes negative resulting into unintended behavior.

Validate the size of the recieved SMD packet.

CRs-Fixed: 579605
Change-Id: Icb12ae6bbb29104f4039209ba142120697271b3a
Signed-off-by: default avatarZaheerulla Meer <zmeer@codeaurora.org>
parent bcb87d5a
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <mach/msm_smd.h>
#include <mach/msm_iomap.h>
#include <mach/subsystem_notif.h>
#include <mach/subsystem_restart.h>
#include <mach/socinfo.h>
#include <mach/proc_comm.h>
#include <mach/msm_ipc_logging.h>
@@ -1218,6 +1219,7 @@ static void update_packet_state(struct smd_channel *ch)
{
	unsigned hdr[5];
	int r;
	const char *peripheral = NULL;

	/* can't do anything if we're in the middle of a packet */
	while (ch->current_packet == 0) {
@@ -1231,6 +1233,17 @@ static void update_packet_state(struct smd_channel *ch)
		BUG_ON(r != SMD_HEADER_SIZE);

		ch->current_packet = hdr[0];
		if (ch->current_packet > (uint32_t)INT_MAX) {
			pr_err("%s: Invalid packet size of %d bytes detected. Edge: %d, Channel : %s, RPTR: %d, WPTR: %d",
				__func__, ch->current_packet, ch->type,
				ch->name, ch->half_ch->get_tail(ch->recv),
				ch->half_ch->get_head(ch->recv));
			peripheral = smd_edge_to_pil_str(ch->type);
			if (peripheral) {
				if (subsystem_restart(peripheral) < 0)
					BUG();
			}
		}
	}
}

@@ -1708,6 +1721,12 @@ static int smd_packet_read(smd_channel_t *ch, void *data, int len, int user_buf)
	if (len < 0)
		return -EINVAL;

	if (ch->current_packet > (uint32_t)INT_MAX) {
		pr_err("%s: Invalid packet size for Edge %d and Channel %s",
			__func__, ch->type, ch->name);
		return -EFAULT;
	}

	if (len > ch->current_packet)
		len = ch->current_packet;

@@ -1732,6 +1751,12 @@ static int smd_packet_read_from_cb(smd_channel_t *ch, void *data, int len,
	if (len < 0)
		return -EINVAL;

	if (ch->current_packet > (uint32_t)INT_MAX) {
		pr_err("%s: Invalid packet size for Edge %d and Channel %s",
			__func__, ch->type, ch->name);
		return -EFAULT;
	}

	if (len > ch->current_packet)
		len = ch->current_packet;

@@ -2340,6 +2365,11 @@ int smd_read_avail(smd_channel_t *ch)
		return -ENODEV;
	}

	if (ch->current_packet > (uint32_t)INT_MAX) {
		pr_err("%s: Invalid packet size for Edge %d and Channel %s",
			__func__, ch->type, ch->name);
		return -EFAULT;
	}
	return ch->read_avail(ch);
}
EXPORT_SYMBOL(smd_read_avail);
@@ -2436,6 +2466,11 @@ int smd_cur_packet_size(smd_channel_t *ch)
		return -ENODEV;
	}

	if (ch->current_packet > (uint32_t)INT_MAX) {
		pr_err("%s: Invalid packet size for Edge %d and Channel %s",
			__func__, ch->type, ch->name);
		return -EFAULT;
	}
	return ch->current_packet;
}
EXPORT_SYMBOL(smd_cur_packet_size);