]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-bus: add depth limit to message_skip_fields() to prevent stack overflow
authorTristanInSec <tristan.mtn@gmail.com>
Tue, 19 May 2026 21:33:06 +0000 (17:33 -0400)
committerTristanInSec <tristan.mtn@gmail.com>
Tue, 19 May 2026 21:33:06 +0000 (17:33 -0400)
message_skip_fields() recurses for each nested variant ('v') type in
D-Bus message header fields. A crafted message with deeply nested
variants (e.g., a variant containing a variant containing a variant...)
causes unbounded stack growth, leading to stack overflow and crash.

Add a depth parameter that increments on each recursive call and
rejects messages exceeding BUS_CONTAINER_DEPTH with -EBADMSG. This
matches the existing depth limits enforced elsewhere in the sd-bus
message processing (e.g., bus_message_enter_container).

src/libsystemd/sd-bus/bus-message.c

index 017ffb7a6127aa3f1b0d88b3d62e4a84fd74d60c..a719253fa73e6a696ecc507c669d51e726e5d487 100644 (file)
@@ -3904,7 +3904,8 @@ static int message_skip_fields(
                 sd_bus_message *m,
                 size_t *ri,
                 uint32_t array_size,
-                const char **signature) {
+                const char **signature,
+                unsigned depth) {
 
         size_t original_index;
         int r;
@@ -3913,6 +3914,9 @@ static int message_skip_fields(
         assert(ri);
         assert(signature);
 
+        if (depth >= BUS_CONTAINER_DEPTH)
+                return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Maximum container nesting depth reached, refusing.");
+
         original_index = *ri;
 
         for (;;) {
@@ -3993,7 +3997,7 @@ static int message_skip_fields(
                                 if (r < 0)
                                         return r;
 
-                                r = message_skip_fields(m, ri, nas, (const char**) &s);
+                                r = message_skip_fields(m, ri, nas, (const char**) &s, depth + 1);
                                 if (r < 0)
                                         return r;
                         }
@@ -4007,7 +4011,7 @@ static int message_skip_fields(
                         if (r < 0)
                                 return r;
 
-                        r = message_skip_fields(m, ri, UINT32_MAX, &s);
+                        r = message_skip_fields(m, ri, UINT32_MAX, &s, depth + 1);
                         if (r < 0)
                                 return r;
 
@@ -4025,7 +4029,7 @@ static int message_skip_fields(
                                 strncpy(sig, *signature + 1, l);
                                 sig[l] = '\0';
 
-                                r = message_skip_fields(m, ri, UINT32_MAX, (const char**) &s);
+                                r = message_skip_fields(m, ri, UINT32_MAX, (const char**) &s, depth + 1);
                                 if (r < 0)
                                         return r;
                         }
@@ -4198,7 +4202,7 @@ static int message_parse_fields(sd_bus_message *m, bool got_ctrunc) {
                         break;
 
                 default:
-                        r = message_skip_fields(m, &ri, UINT32_MAX, &signature);
+                        r = message_skip_fields(m, &ri, UINT32_MAX, &signature, 0);
                 }
                 if (r < 0)
                         return r;