[PATCH v2] Input: tegra-kbc - check the pin numbers from the device tree

Guanglei Zhu posted 1 patch 2 hours ago
drivers/input/keyboard/tegra-kbc.c | 8 ++++++++
1 file changed, 8 insertions(+)
[PATCH v2] Input: tegra-kbc - check the pin numbers from the device tree
Posted by Guanglei Zhu 2 hours ago
The row and column pin lists are read straight from the device tree
and used to index the pin configuration array:

	for (i = 0; i < num_rows; i++) {
		kbc->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW;
		kbc->pin_cfg[rows_cfg[i]].num = i;
	}

The helper only limits how many entries it reads, not what they
contain. Not all Tegra variants have KBC_MAX_GPIO pins - Tegra114,
for example, has 11 rows + 8 columns = 19 - and the setup loop only
initializes pin_cfg[] up to kbc->num_rows_and_columns, so a device
tree that names a pin the variant does not have makes the row and
column stores write over pin_cfg entries that were never touched,
and the later check_pin_cfg() walk reads that stale data back as
valid configuration.

Reject pin numbers the variant does not have.

Fixes: 88390243a993 ("Input: tegra-kbc - add support for rows/columns configuration from dt")
Cc: stable@vger.kernel.org
Signed-off-by: Guanglei Zhu <zhugl3@xiaopeng.com>
---
v2: validate against kbc->num_rows_and_columns instead of
    KBC_MAX_GPIO, per review - Tegra114 only has 19 KBC pins and
    the setup loop above only initializes pin_cfg[] up to
    num_rows_and_columns, so pins in [19, 24) must be rejected too.

 drivers/input/keyboard/tegra-kbc.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index bc1c80a..657260d 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -522,6 +522,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
 	}
 
 	for (i = 0; i < num_rows; i++) {
+		if (rows_cfg[i] >= kbc->num_rows_and_columns) {
+			dev_err(kbc->dev, "invalid row pin %u\n", rows_cfg[i]);
+			return -EINVAL;
+		}
 		kbc->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW;
 		kbc->pin_cfg[rows_cfg[i]].num = i;
 	}
@@ -538,6 +542,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc)
 	}
 
 	for (i = 0; i < num_cols; i++) {
+		if (cols_cfg[i] >= kbc->num_rows_and_columns) {
+			dev_err(kbc->dev, "invalid col pin %u\n", cols_cfg[i]);
+			return -EINVAL;
+		}
 		kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL;
 		kbc->pin_cfg[cols_cfg[i]].num = i;
 	}
-- 
2.43.0