lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <02f3524f5e3974e73223bda9f4d15cba322ba169.1762235099.git.charan.kalla@oss.qualcomm.com>
Date: Tue,  4 Nov 2025 14:21:03 +0530
From: Charan Teja Kalla <charan.kalla@....qualcomm.com>
To: robin.murphy@....com, will@...nel.org, joro@...tes.org, robh@...nel.org,
        dmitry.baryshkov@....qualcomm.com, konrad.dybcio@....qualcomm.com,
        bjorn.andersson@....qualcomm.com, bod@...nel.org, conor+dt@...nel.org,
        krzk+dt@...nel.org, saravanak@...gle.com,
        prakash.gupta@....qualcomm.com, vikash.garodia@....qualcomm.com
Cc: iommu@...ts.linux.dev, linux-kernel@...r.kernel.org,
        devicetree@...r.kernel.org,
        Charan Teja Kalla <charan.kalla@....qualcomm.com>
Subject: [PATCH 4/6] of: detect and handle legacy iommu-map parsing

of_map_id currently ignores the value of #property-cells and assumes
it's always 1. iommu-map is one of the two currently known users (the
other being msi-map where such issues haven't showed up *so far*).
The arm-smmu-v2 bindings (as an example) allow 2 cells, leading to
the map containing incomplete data.

There have long existed DTs ignoring this loss, where the map only
contained the first cell, so care is taken to try and preserve
compatibility with these - the format for such occurences is as follows:

iommu-map = <FUNC_ID1 &iommu_provider cell1 length>,
	    <FUNC_ID2 &iommu_provider cell1 length>;

If this 'legacy' scheme is used, we can check whether there's exactly
4n entries in the array and if the second entry in each group of 4 is
(the same) phandle and length = 1[1]. The only outstanding case would be
if the iommu-map references two separate iommu providers, but that's
highly unlikely.

Implement the above logic to make passing more than one cell possible.

[1] https://lore.kernel.org/all/8d88cd9d-16e8-43f9-8eb3-89862da1d0c1@arm.com/

Signed-off-by: Charan Teja Kalla <charan.kalla@....qualcomm.com>
---
 drivers/of/base.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index e5ba8a318769..997b2deb96f0 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2045,6 +2045,60 @@ int of_find_last_cache_level(unsigned int cpu)
 	return cache_level;
 }
 
+/**
+ * of_iommu_map_id_legacy_cell_count - Determine the cell count for iommu-map.
+ *
+ * @map: pointer to the iommu-map property data that needs to be translated.
+ * @map_len: length of @map in bytes.
+ * @cell_count: value of #iommu-cells.
+ *
+ * It is the legacy case where the tuple representing iommu-map is always
+ * multiple of 4 and #iommu-cells > 1.
+ *
+ * Return: > 0 for success, 0 for failure.
+ */
+static u32 of_iommu_map_id_legacy_cell_count(const __be32 *map, int map_len)
+{
+	u32 phandle1, phandle2;
+
+	phandle1 = be32_to_cpup(map + 1);
+
+	for (map_len -= 4 * sizeof(*map), map += 4; map_len > 0;
+		map_len -= 4 * sizeof(*map), map += 4) {
+		u32 len;
+
+		phandle2 = be32_to_cpup(map + 1);
+		len = be32_to_cpup(map + 3);
+		if (phandle1 != phandle2 || len != 1)
+			break;
+	}
+
+	if (!map_len)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * of_iommu_map_id_cell_count - Determine the cell count for iommu-map parsing.
+ *
+ * @map: pointer to the iommu-map property that needs to be translated.
+ * @map_len: length of @map in bytes.
+ *
+ * Use #iommu-cells property while parsing iommu-map. Detect and use legacy
+ * case where iommu-map is parsed as if cells = 1.
+ *
+ * Return: number of cells that the caller should be considered while parsing
+ * the @map. It is > 0 for success, 0 for failure.
+ */
+static int of_iommu_map_id_cell_count(const __be32 *map, int map_len)
+{
+	if (map_len % 4 != 0)
+		return 0;
+
+	return of_iommu_map_id_legacy_cell_count(map, map_len);
+}
+
 /**
  * of_map_id_cell_count - parse the cell count.
  *
@@ -2082,7 +2136,10 @@ static int of_map_id_cell_count(const __be32 *map, const char *map_name,
 		return 0;
 	}
 
-	return 1;
+	if (cells > 1 && !strcmp(map_name, "iommu-map"))
+		return of_iommu_map_id_cell_count(map, map_len);
+
+	return cells;
 }
 
 /*
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ