sd-bus: add depth limit to message_skip_fields() to prevent stack overflow
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).
This commit is contained in:
@@ -3904,7 +3904,8 @@ static int message_skip_fields(
|
|||||||
sd_bus_message *m,
|
sd_bus_message *m,
|
||||||
size_t *ri,
|
size_t *ri,
|
||||||
uint32_t array_size,
|
uint32_t array_size,
|
||||||
const char **signature) {
|
const char **signature,
|
||||||
|
unsigned depth) {
|
||||||
|
|
||||||
size_t original_index;
|
size_t original_index;
|
||||||
int r;
|
int r;
|
||||||
@@ -3913,6 +3914,9 @@ static int message_skip_fields(
|
|||||||
assert(ri);
|
assert(ri);
|
||||||
assert(signature);
|
assert(signature);
|
||||||
|
|
||||||
|
if (depth >= BUS_CONTAINER_DEPTH)
|
||||||
|
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), "Maximum container nesting depth reached, refusing.");
|
||||||
|
|
||||||
original_index = *ri;
|
original_index = *ri;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -3993,7 +3997,7 @@ static int message_skip_fields(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -4007,7 +4011,7 @@ static int message_skip_fields(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@@ -4025,7 +4029,7 @@ static int message_skip_fields(
|
|||||||
strncpy(sig, *signature + 1, l);
|
strncpy(sig, *signature + 1, l);
|
||||||
sig[l] = '\0';
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -4198,7 +4202,7 @@ static int message_parse_fields(sd_bus_message *m, bool got_ctrunc) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
r = message_skip_fields(m, &ri, UINT32_MAX, &signature);
|
r = message_skip_fields(m, &ri, UINT32_MAX, &signature, 0);
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
Reference in New Issue
Block a user