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

Commit 66b4fb54 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "lsm: check payload size validity before using it as array index"

parents 3a8fc653 5574e747
Loading
Loading
Loading
Loading
+37 −8
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2017, 2019 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
@@ -195,7 +195,8 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd,
}

static void lsm_event_handler(uint32_t opcode, uint32_t token,
			      void *payload, void *priv)
			      void *payload, uint16_t client_size,
				void *priv)
{
	unsigned long flags;
	struct lsm_priv *prtd = priv;
@@ -265,6 +266,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
	}

	case LSM_SESSION_EVENT_DETECTION_STATUS:
		if (client_size < 3 * sizeof(uint8_t)) {
			dev_err(rtd->dev,
					"%s: client_size has invalid size[%d]\n",
					__func__, client_size);
			return;
		}
		status = (uint16_t)((uint8_t *)payload)[0];
		payload_size = (uint16_t)((uint8_t *)payload)[2];
		index = 4;
@@ -274,6 +281,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
	break;

	case LSM_SESSION_EVENT_DETECTION_STATUS_V2:
		if (client_size < 2 * sizeof(uint8_t)) {
			dev_err(rtd->dev,
					"%s: client_size has invalid size[%d]\n",
					__func__, client_size);
			return;
		}
		status = (uint16_t)((uint8_t *)payload)[0];
		payload_size = (uint16_t)((uint8_t *)payload)[1];
		index = 2;
@@ -283,6 +296,12 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
		break;

	case LSM_SESSION_EVENT_DETECTION_STATUS_V3:
		if (client_size < 2 * (sizeof(uint32_t) + sizeof(uint8_t))) {
			dev_err(rtd->dev,
					"%s: client_size has invalid size[%d]\n",
					__func__, client_size);
			return;
		}
		event_ts_lsw = ((uint32_t *)payload)[0];
		event_ts_msw = ((uint32_t *)payload)[1];
		status = (uint16_t)((uint8_t *)payload)[8];
@@ -321,12 +340,22 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
		prtd->event_status->payload_size = payload_size;

		if (likely(prtd->event_status)) {
			if (client_size >= (payload_size + index)) {
				memcpy(prtd->event_status->payload,
					&((uint8_t *)payload)[index],
					payload_size);
				prtd->event_avail = 1;
			spin_unlock_irqrestore(&prtd->event_lock, flags);
				spin_unlock_irqrestore(&prtd->event_lock,
								flags);
				wake_up(&prtd->event_wait);
			} else {
				spin_unlock_irqrestore(&prtd->event_lock,
								flags);
				dev_err(rtd->dev,
						"%s: Failed to copy memory with invalid size = %d\n",
						__func__, payload_size);
				return;
			}
		} else {
			spin_unlock_irqrestore(&prtd->event_lock, flags);
			dev_err(rtd->dev,
+14 −4
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2018, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2019, 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
@@ -195,7 +195,8 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
		struct lsm_cmd_read_done read_done;

		token = data->token;
		if (data->payload_size > sizeof(read_done)) {
		if (data->payload_size > sizeof(read_done) ||
				data->payload_size < 6 * sizeof(payload[0])) {
			pr_err("%s: read done error payload size %d expected size %zd\n",
				__func__, data->payload_size,
				sizeof(read_done));
@@ -213,6 +214,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
		if (client->cb)
			client->cb(data->opcode, data->token,
					(void *)&read_done,
					sizeof(read_done),
					client->priv);
		return 0;
	} else if (data->opcode == APR_BASIC_RSP_RESULT) {
@@ -238,6 +240,11 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)
					__func__, token, client->session);
				return -EINVAL;
			}
			if (data->payload_size < 2 * sizeof(payload[0])) {
				pr_err("%s: payload has invalid size[%d]\n",
					__func__, data->payload_size);
				return -EINVAL;
			}
			client->cmd_err_code = payload[1];
			if (client->cmd_err_code)
				pr_err("%s: cmd 0x%x failed status %d\n",
@@ -258,7 +265,7 @@ static int q6lsm_callback(struct apr_client_data *data, void *priv)

	if (client->cb)
		client->cb(data->opcode, data->token, data->payload,
			   client->priv);
				data->payload_size, client->priv);

	return 0;
}
@@ -1492,6 +1499,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
			 "proc 0x%x SID 0x%x\n", __func__, data->opcode,
			 data->reset_event, data->reset_proc, sid);

		if (sid < LSM_MIN_SESSION_ID || sid > LSM_MAX_SESSION_ID)
			pr_err("%s: Invalid session %d\n", __func__, sid);
		apr_reset(lsm_common.apr);
		lsm_common.apr = NULL;
		atomic_set(&lsm_common.apr_users, 0);
@@ -1557,7 +1566,8 @@ static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
	}
	if (client->cb)
		client->cb(data->opcode, data->token,
			   data->payload, client->priv);
			   data->payload, data->payload_size,
			   client->priv);
	return 0;
}

+2 −2
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2017, 2019 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
@@ -26,7 +26,7 @@
#define LSM_MAX_NUM_CHANNELS 8

typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
		       uint32_t *payload, void *priv);
		       uint32_t *payload, uint16_t client_size, void *priv);

struct lsm_sound_model {
	dma_addr_t      phys;