fman_if_init() and fman_if_init_onic() read the devicetree
'cell-index' property and store it unchecked into
__if->__if.mac_idx. This value is later used as an index into the
fixed-size mac_idx[] lookup table in fman_if_vsp_init(), so a
cell-index value greater than or equal to the number of entries in
that table results in an out-of-bounds read.
Add an explicit upper-bound check (FMAN_MAX_MAC_IDX_NUM) in both
fman_if_init() and fman_if_init_onic() before the mac_idx assignment,
and a static_assert in fman_if_vsp_init() to keep mac_idx[] in sync
with FMAN_MAX_MAC_IDX_NUM if it is ever resized.
Fixes: a0edbb8a8e52 ("bus/dpaa: add OH port mode")
Fixes: 7e5f49ae767d ("bus/dpaa: add ONIC port mode")
Cc: [email protected]
Signed-off-by: Gagandeep Singh <[email protected]>
---
drivers/bus/dpaa/base/fman/fman.c | 19 +++++++++++++++++++
drivers/bus/dpaa/include/fman.h | 5 +++++
2 files changed, 24 insertions(+)
diff --git a/drivers/bus/dpaa/base/fman/fman.c
b/drivers/bus/dpaa/base/fman/fman.c
index 67f77265ca..223cd6958d 100644
--- a/drivers/bus/dpaa/base/fman/fman.c
+++ b/drivers/bus/dpaa/base/fman/fman.c
@@ -205,6 +205,9 @@ static void fman_if_vsp_init(struct __fman_if *__if)
size_t lenp;
const uint8_t mac_idx[] = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1};
+ static_assert(RTE_DIM(mac_idx) == FMAN_MAX_MAC_IDX_NUM,
+ "mac_idx[] out of sync with FMAN_MAX_MAC_IDX_NUM");
+
if (__if->__if.mac_idx <= 8) {
for_each_compatible_node(dev, NULL,
"fsl,fman-port-1g-rx-extended-args") {
@@ -544,6 +547,14 @@ fman_if_init(const struct device_node *dpa_node, int fd)
cell_idx_host = of_read_number(cell_idx,
lenp / sizeof(phandle));
+ if (cell_idx_host >= FMAN_MAX_MAC_IDX_NUM) {
+ FMAN_ERR(-EINVAL,
+ "%s: cell-index(%" PRIu64 ") >= max(%d)",
+ oh_node->full_name, cell_idx_host,
+ FMAN_MAX_MAC_IDX_NUM);
+ goto err;
+ }
+
__if->__if.mac_idx = cell_idx_host;
}
@@ -957,6 +968,14 @@ static int fman_if_init_onic(const struct device_node
*dpa_node)
assert(lenp == sizeof(*cell_idx));
cell_idx_host = of_read_number(cell_idx, lenp / sizeof(phandle));
+
+ if (cell_idx_host >= FMAN_MAX_MAC_IDX_NUM) {
+ FMAN_ERR(-EINVAL, "%s: cell-index(%" PRIu64 ") >= max(%d)",
+ tx_oh_node->full_name, cell_idx_host,
+ FMAN_MAX_MAC_IDX_NUM);
+ goto err;
+ }
+
__if->__if.mac_idx = cell_idx_host;
fman_node = of_get_parent(fman_tx_oh_node);
diff --git a/drivers/bus/dpaa/include/fman.h b/drivers/bus/dpaa/include/fman.h
index f642faf3b3..f499f9ebbf 100644
--- a/drivers/bus/dpaa/include/fman.h
+++ b/drivers/bus/dpaa/include/fman.h
@@ -68,6 +68,11 @@
#define FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES 4
#define FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS 3
+/*
+ * Maximum number of MAC/offline port indexes.
+ */
+#define FMAN_MAX_MAC_IDX_NUM 11
+
/* Represents the different flavour of network interface */
enum fman_mac_type {
fman_offline_internal = 0,
--
2.25.1