From cd04f7fab9902abcf5adbc2f83b42fa3c3d032f9 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Mon, 10 May 2021 10:31:41 -0700 Subject: [PATCH] ANDROID: usb: typec: ucsi: Ensure bounds check when accessing src_pdos Currently, when reading the following properties under ucsi-source-psy-*, src_pdos array is accessed but it only checks for the condition num_pdos > 0. - voltage_max - voltage_now - current_max In the case if a PPM passes num_pdos greater than UCSI_MAX_PDOS, an OOB access can be made. Fix it by checking the upper bound for src_pdos which is UCSI_MAX_PDOS. This issue is detected by enabling UBSAN. Bug: 186400956 Fixes: 992a60ed0d5e ("usb: typec: ucsi: register with power_supply class") Fixes: 4dbc6a4ef06d ("usb: typec: ucsi: save power data objects in PD mode") Change-Id: Id0aca674208b23329be089671cba873baca930cf Signed-off-by: Subbaraman Narayanamurthy --- drivers/usb/typec/ucsi/psy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c index 571a51e16234..387ba85764b1 100644 --- a/drivers/usb/typec/ucsi/psy.c +++ b/drivers/usb/typec/ucsi/psy.c @@ -69,7 +69,7 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connector *con, switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { case UCSI_CONSTAT_PWR_OPMODE_PD: - if (con->num_pdos > 0) { + if (con->num_pdos > 0 && con->num_pdos <= UCSI_MAX_PDOS) { pdo = con->src_pdos[con->num_pdos - 1]; val->intval = pdo_fixed_voltage(pdo) * 1000; } else { @@ -98,7 +98,7 @@ static int ucsi_psy_get_voltage_now(struct ucsi_connector *con, switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { case UCSI_CONSTAT_PWR_OPMODE_PD: index = rdo_index(con->rdo); - if (index > 0) { + if (index > 0 && index <= UCSI_MAX_PDOS) { pdo = con->src_pdos[index - 1]; val->intval = pdo_fixed_voltage(pdo) * 1000; } else { @@ -125,7 +125,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con, switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) { case UCSI_CONSTAT_PWR_OPMODE_PD: - if (con->num_pdos > 0) { + if (con->num_pdos > 0 && con->num_pdos <= UCSI_MAX_PDOS) { pdo = con->src_pdos[con->num_pdos - 1]; val->intval = pdo_max_current(pdo) * 1000; } else {