]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: fix loop bound and OOB in devicetree_get_compatible()
authorMilan Kyselica <mil.kyselica@gmail.com>
Sat, 11 Apr 2026 08:26:13 +0000 (10:26 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 13 Apr 2026 10:33:56 +0000 (12:33 +0200)
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
src/boot/devicetree.c

index 85fc07c49f38b659bd69a796bc5ea933d7fbb940..a9dccd2a57c56590dae7483032e99e0b066edae9 100644 (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: