of: Fix error path in of_parse_phandle_with_args_map()

The current code uses some 'goto put;' to cancel the parsing operation
and can lead to a return code value of 0 even on error cases.

Indeed, some goto calls are done from a loop without setting the ret
value explicitly before the goto call and so the ret value can be set to
0 due to operation done in previous loop iteration. For instance match
can be set to 0 in the previous loop iteration (leading to a new
iteration) but ret can also be set to 0 it the of_property_read_u32()
call succeed. In that case if no match are found or if an error is
detected the new iteration, the return value can be wrongly 0.

Avoid those cases setting the ret value explicitly before the goto
calls.

Fixes: bd6f2fd5a1d5 ("of: Support parsing phandle argument lists through a nexus node")
Cc: stable@vger.kernel.org
Signed-off-by: Herve Codina <herve.codina@bootlin.com>
Link: https://lore.kernel.org/r/20241202165819.158681-1-herve.codina@bootlin.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>

authored by Herve Codina and committed by Rob Herring (Arm) d7dfa7fd 23952171

Changed files
+10 -5
drivers
of
+10 -5
drivers/of/base.c
··· 1471 1471 map_len--; 1472 1472 1473 1473 /* Check if not found */ 1474 - if (!new) 1474 + if (!new) { 1475 + ret = -EINVAL; 1475 1476 goto put; 1477 + } 1476 1478 1477 1479 if (!of_device_is_available(new)) 1478 1480 match = 0; ··· 1484 1482 goto put; 1485 1483 1486 1484 /* Check for malformed properties */ 1487 - if (WARN_ON(new_size > MAX_PHANDLE_ARGS)) 1485 + if (WARN_ON(new_size > MAX_PHANDLE_ARGS) || 1486 + map_len < new_size) { 1487 + ret = -EINVAL; 1488 1488 goto put; 1489 - if (map_len < new_size) 1490 - goto put; 1489 + } 1491 1490 1492 1491 /* Move forward by new node's #<list>-cells amount */ 1493 1492 map += new_size; 1494 1493 map_len -= new_size; 1495 1494 } 1496 - if (!match) 1495 + if (!match) { 1496 + ret = -ENOENT; 1497 1497 goto put; 1498 + } 1498 1499 1499 1500 /* Get the <list>-map-pass-thru property (optional) */ 1500 1501 pass = of_get_property(cur, pass_name, NULL);