From bdc8e579d71d3ea875383e134b945129d2eb22ca Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 6 Apr 2020 19:19:30 -0700 Subject: [PATCH 1/2] power: supply: qti-battery-charger: Fix buffer handling in handle_message() Currently, prop_id (u32) and val (u32) are obtained for all messages in handle_message(). However, the response for notification request doesn't have the same payload but only an u32 return code. Because of this, an unintentional memory read for u32 is being made even though it is not used. Fix this by getting prop_id and val only for response messages that are intended to get battery/USB/wireless power supply properties. CRs-Fixed: 2655408 Change-Id: I4d17d965f911eb6a4357e29117191f78830e9e5c Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qti_battery_charger.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/power/supply/qti_battery_charger.c b/drivers/power/supply/qti_battery_charger.c index 94efdc19cb87..e5ac38cac3b6 100644 --- a/drivers/power/supply/qti_battery_charger.c +++ b/drivers/power/supply/qti_battery_charger.c @@ -317,10 +317,9 @@ int qti_battery_charger_get_prop(const char *name, } EXPORT_SYMBOL(qti_battery_charger_get_prop); -static bool validate_message(void *data, size_t len) +static bool validate_message(struct battery_charger_resp_msg *resp_msg, + size_t len) { - struct battery_charger_resp_msg *resp_msg = data; - if (len != sizeof(*resp_msg)) { pr_err("Incorrect response length %zu for opcode %#x\n", len, resp_msg->hdr.opcode); @@ -342,7 +341,6 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data, { struct battery_charger_resp_msg *resp_msg = data; struct battery_model_resp_msg *model_resp_msg = data; - u32 prop_id = resp_msg->property_id, val = resp_msg->value; struct psy_state *pst; bool ack_set = false; @@ -358,24 +356,27 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data, } /* Other response should be of same type as they've u32 value */ - if (validate_message(data, len) && prop_id < pst->prop_count) { - pst->prop[prop_id] = val; + if (validate_message(resp_msg, len) && + resp_msg->property_id < pst->prop_count) { + pst->prop[resp_msg->property_id] = resp_msg->value; ack_set = true; } break; case BC_USB_STATUS_GET: pst = &bcdev->psy_list[PSY_TYPE_USB]; - if (validate_message(data, len) && prop_id < pst->prop_count) { - pst->prop[prop_id] = val; + if (validate_message(resp_msg, len) && + resp_msg->property_id < pst->prop_count) { + pst->prop[resp_msg->property_id] = resp_msg->value; ack_set = true; } break; case BC_WLS_STATUS_GET: pst = &bcdev->psy_list[PSY_TYPE_WLS]; - if (validate_message(data, len) && prop_id < pst->prop_count) { - pst->prop[prop_id] = val; + if (validate_message(resp_msg, len) && + resp_msg->property_id < pst->prop_count) { + pst->prop[resp_msg->property_id] = resp_msg->value; ack_set = true; } From a91100b97143112759815acd8ae8da6fbda4916d Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Thu, 2 Apr 2020 20:08:36 -0700 Subject: [PATCH 2/2] soc: qcom: pmic_glink: Verify the message length Currently, data received from the remote subsystem is delivered to the clients as-is if they've registered for receiving it. This can cause unintended extraneous buffer reads if the length of the received message is too small. Verify that the message length is at least the PMIC Glink header size. Change-Id: I3774d9d5331794c509bda89f40f4ead2e0ed3843 Signed-off-by: Subbaraman Narayanamurthy --- drivers/soc/qcom/pmic_glink.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c index 8fc6f37ee218..441729e40609 100644 --- a/drivers/soc/qcom/pmic_glink.c +++ b/drivers/soc/qcom/pmic_glink.c @@ -304,6 +304,12 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data, struct pmic_glink_buf *pbuf; unsigned long flags; + if (len < sizeof(struct pmic_glink_hdr)) { + pr_err("Received length %d less than header size: %zu\n", len, + sizeof(struct pmic_glink_hdr)); + return -EINVAL; + } + pbuf = kzalloc(sizeof(*pbuf) + len, GFP_ATOMIC); if (!pbuf) return -ENOMEM;