boot: fix loop bound and OOB in devicetree_get_compatible()

The loop used the byte offset end (struct_off + struct_size) as the
iteration limit, but cursor[i] indexes uint32_t words. This reads
past the struct block when end > size_words.

Use size_words (struct_size / sizeof(uint32_t)) which is the correct
number of words to iterate over.

Also fix a pre-existing OOB in the FDT_BEGIN_NODE handler: the guard
i >= size_words is always false inside the loop (since the loop
condition already ensures i < size_words), so cursor[++i] at the
boundary reads one word past the struct block. Use i + 1 >= size_words
to check before incrementing.

Fixes: https://github.com/systemd/systemd/issues/41590
This commit is contained in:
Milan Kyselica
2026-04-13 12:33:56 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent c3c9cc7adb
commit 2c664b9531
+2 -2
View File
@@ -141,10 +141,10 @@ static const char* devicetree_get_compatible(const void *dtb) {
size_t size_words = struct_size / sizeof(uint32_t);
size_t len, name_off, len_words, s;
for (size_t i = 0; i < end; i++) {
for (size_t i = 0; i < size_words; i++) {
switch (be32toh(cursor[i])) {
case FDT_BEGIN_NODE:
if (i >= size_words || cursor[++i] != 0)
if (i + 1 >= size_words || cursor[++i] != 0)
return NULL;
break;
case FDT_NOP: