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: <20260112142009.1006236-67-herve.codina@bootlin.com>
Date: Mon, 12 Jan 2026 15:19:56 +0100
From: Herve Codina <herve.codina@...tlin.com>
To: David Gibson <david@...son.dropbear.id.au>,
	Rob Herring <robh@...nel.org>,
	Krzysztof Kozlowski <krzk@...nel.org>,
	Conor Dooley <conor+dt@...nel.org>
Cc: Ayush Singh <ayush@...gleboard.org>,
	Geert Uytterhoeven <geert@...ux-m68k.org>,
	devicetree-compiler@...r.kernel.org,
	devicetree@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	devicetree-spec@...r.kernel.org,
	Hui Pu <hui.pu@...ealthcare.com>,
	Ian Ray <ian.ray@...ealthcare.com>,
	Luca Ceresoli <luca.ceresoli@...tlin.com>,
	Thomas Petazzoni <thomas.petazzoni@...tlin.com>,
	Herve Codina <herve.codina@...tlin.com>
Subject: [RFC PATCH 66/77] dtc: Add support for namespace labels references

Namespace labels references can only be present in addons and involves
import/exported symbols.

They allow to 'jump' from node to node based on exported symbols defined
at each node.

When a label reference contains a dot ('.') char, it becomes a namespace
labels reference.

For instance &foo.bar.baz is a namespace label reference. The resolution
of this reference is performed in a recursive way.
   - Get the node referenced by foo.
   - From this node get the node referenced by bar in exported symbols
     from foo.
   - From this node get the node referenced by baz in exported symbols
     from bar.
   - ...

The first item (foo) involves import symbols defined in the addon and
export symbols defined in the node the addon is applied to.

Other items involves only exported symbols in referenced nodes to
perform the resolution chain.

We leave the addon thanks to the first item and import symbols. Other
items allow to perform jumps from node to node in the base device-tree
without leaving it.

The full resolution can be summarized with the following diagram:

  (addon DT)
  &foo.bar.baz
   |    |   |
   |    |   +--------------------------------------------+
   |    |                                                |
   |    +-------------------------------+                |
   |                                    |                |
   |   (addon DT)                       |                |
   +-> /import/ foo: --+                |                |
                       |                |                |
                       |                |                |
  addon applied at     |                |                |
  target node in the   |                |                |
  base DT              |                |                |
    |                  |                |                |
    |   (base DT)      |                |                |
    +---> target {     v                |                |
             /export/ foo: &n1;         |                |
                            |           |                |
                            |           |                |
                            v (base DT) |                |
                            n1 {        v                |
                              /export/ bar: &n2;         |
                                             |           |
                                             v (base DT) |
                                             n2 {        v
                                               /export/ baz: &n3;
                                                              |
                                                              |
                                                              v
                                                              n3 { ... };

'&foo.bar.baz' references, in the end, the n3 node from the base DT.

Implement support for namespace references parsing in dtc.

The resolution part is out of dtc. Indeed, dtc has no support for
applying an addon.

Signed-off-by: Herve Codina <herve.codina@...tlin.com>
---
 dtc-lexer.l  | 13 +++++++++++++
 dtc-parser.y | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/dtc-lexer.l b/dtc-lexer.l
index 540bfdf..14b5488 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -232,6 +232,12 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
 			return DT_LABEL_REF;
 		}
 
+<*>\&{LABEL}(\.{LABEL})+	{	/* namespace label reference */
+			DPRINT("Ref namespace: %s\n", yytext+1);
+			yylval.labelref = xstrdup(yytext+1);
+			return DT_LABEL_NAMESPACE_REF;
+		}
+
 <*>"&{"{PATHCHAR}*\}	{	/* new-style path reference */
 			yytext[yyleng-1] = '\0';
 			DPRINT("Ref: %s\n", yytext+2);
@@ -246,6 +252,13 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
 			return DT_ORPHAN_PATH_REF;
 		}
 
+<*>"&{\$"{LABEL}(\.{LABEL})+([/]{PATHCHAR}*)?\}  {	/* orphan path reference */
+			yytext[yyleng-1] = '\0';
+			DPRINT("Ref (namespace) orphan path: %s\n", yytext+1);
+			yylval.labelref = xstrdup(yytext+2);
+			return DT_ORPHAN_PATH_REF;
+		}
+
 <BYTESTRING>[0-9a-fA-F]{2} {
 			yylval.byte = strtol(yytext, NULL, 16);
 			DPRINT("Byte: %02x\n", (int)yylval.byte);
diff --git a/dtc-parser.y b/dtc-parser.y
index 9d619cd..8c63e83 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -32,6 +32,11 @@ static bool is_ref_relative(const char *ref)
 	return ref[0] != '/' && strchr(&ref[1], '/');
 }
 
+static bool is_ref_namespace(const char *ref)
+{
+	return strchr(ref, '.');
+}
+
 static struct node *parser_get_node_by_ref(struct node *dt, struct node *orphanlist,
 					   const char *ref)
 {
@@ -110,6 +115,7 @@ static struct node *parser_get_node_by_ref(struct node *dt, struct node *orphanl
 %token <data> DT_STRING
 %token <labelref> DT_LABEL
 %token <labelref> DT_LABEL_REF
+%token <labelref> DT_LABEL_NAMESPACE_REF
 %token <labelref> DT_PATH_REF
 %token <labelref> DT_ORPHAN_PATH_REF
 %token DT_INCBIN
@@ -260,7 +266,7 @@ importdef:
 		}
 	;
 
-dt_ref: DT_LABEL_REF | DT_PATH_REF;
+dt_ref: DT_LABEL_REF | DT_PATH_REF | DT_LABEL_NAMESPACE_REF;
 
 devicetree:
 	  '/' nodedef
@@ -281,6 +287,9 @@ devicetree:
 			else if (is_ref_relative($1))
 				ERROR(&@2, "Label-relative reference %s not supported in plugin nor addon", $1);
 
+			if (!(last_header_flags & DTSF_ADDON) && is_ref_namespace($1))
+				ERROR(&@2, "Namespaced label reference %s supported only in addon", $1);
+
 			if (last_header_flags & DTSF_PLUGIN) {
 				$$ = plugin_add_orphan_node(
 						name_node(build_node(NULL, NULL, NULL, NULL),
@@ -300,6 +309,10 @@ devicetree:
 			if ((last_header_flags & (DTSF_PLUGIN | DTSF_ADDON)) && is_ref_relative($3))
 				ERROR(&@2, "Label-relative reference %s not supported in plugin nor addon", $3);
 
+			if (!(last_header_flags & DTSF_ADDON) && is_ref_namespace($3))
+				ERROR(&@2, "Namespaced label reference %s supported only in addon", $3);
+
+
 			if (target) {
 				add_label(&target->labels, $2);
 				merge_nodes(target, $4);
@@ -346,6 +359,25 @@ devicetree:
 			}
 			$$ = $1;
 		}
+	| devicetree DT_LABEL_NAMESPACE_REF nodedef
+		{
+			struct node *target = parser_get_node_by_ref(
+						$1, parser_orphanlist, $2);
+
+			if (!(last_header_flags & DTSF_ADDON))
+				ERROR(&@2, "Namespaced label reference %s supported only in addon", $2);
+
+			if (target) {
+				merge_nodes(target, $3);
+			} else {
+				if (last_header_flags & DTSF_ADDON)
+					addon_add_orphan_node(&parser_orphanlist,
+							      orphan_node($3, $2));
+				else
+					ERROR(&@2, "Label or path %s not found", $2);
+			}
+			$$ = $1;
+		}
 	| devicetree DT_DEL_NODE dt_ref ';'
 		{
 			struct node *target = parser_get_node_by_ref(
@@ -422,6 +454,10 @@ exportlist:
 exportdef:
 	DT_EXPORT DT_LABEL dt_ref ';'
 		{
+			/* Only an addon can use namespaced labels references */
+			if (!(last_header_flags & DTSF_ADDON) && is_ref_namespace($3))
+				ERROR(&@2, "Namespaced label reference %s supported only in addon", $3);
+
 			$$ = build_exportsym($2, $3, 0, &@$);
 			free($2);
 			free($3);
@@ -477,6 +513,9 @@ propdata:
 		}
 	| propdataprefix dt_ref
 		{
+			if (!(last_header_flags & DTSF_ADDON) && is_ref_namespace($2))
+				ERROR(&@2, "Namespaced label reference %s supported only in addon", $2);
+
 			$1 = data_add_marker($1, TYPE_STRING, $2);
 			$$ = data_add_marker($1, REF_PATH, $2);
 		}
@@ -582,13 +621,17 @@ arrayprefix:
 		{
 			uint64_t val = ~0ULL >> (64 - $1.bits);
 
-			if ($1.bits == 32)
+			if ($1.bits == 32) {
+				if (!(last_header_flags & DTSF_ADDON) && is_ref_namespace($2))
+					ERROR(&@2, "Namespaced label reference %s supported only in addon", $2);
+
 				$1.data = data_add_marker($1.data,
 							  REF_PHANDLE,
 							  $2);
-			else
+			} else {
 				ERROR(&@2, "References are only allowed in "
 					    "arrays with 32-bit elements.");
+			}
 
 			$$.data = data_append_integer($1.data, val, $1.bits);
 		}
-- 
2.52.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ