mirror of
https://github.com/systemd/systemd.git
synced 2026-11-08 06:16:55 +00:00
test: add test for variant recursion depth limit in message_skip_fields()
Craft a raw D-Bus message with an unknown header field containing BUS_CONTAINER_DEPTH+1 nested variants and verify that message parsing rejects it with -EBADMSG rather than recursing until stack overflow. (cherry picked from commitddb221c3b2) (cherry picked from commit50df1d7659) (cherry picked from commit527eb93d4b)
This commit is contained in:
1 parent
5f939b1e8a
commit
23bd58ceb4
1 file changed
+54
@@ -19,6 +19,7 @@ REENABLE_WARNING
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-internal.h"
|
||||
#include "bus-label.h"
|
||||
#include "bus-message.h"
|
||||
#include "bus-util.h"
|
||||
@@ -99,6 +100,58 @@ static void test_bus_label_escape_one(const char *a, const char *b) {
|
||||
assert_se(streq(a, y));
|
||||
}
|
||||
|
||||
static void test_bus_nested_variant_depth_limit(void) {
|
||||
/* Craft a raw D-Bus message with an unknown header field whose value is a variant
|
||||
* containing a variant containing a variant... nested beyond BUS_CONTAINER_DEPTH.
|
||||
* Without the depth limit in message_skip_fields(), this causes unbounded recursion
|
||||
* and stack overflow. With the fix, it should be rejected with -EBADMSG. */
|
||||
|
||||
_cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
const unsigned depth = BUS_CONTAINER_DEPTH + 1; /* one past the limit */
|
||||
|
||||
/* Each nesting level in the fields area is: 1 byte sig_len + 1 byte 'v' + 1 byte NUL = 3 bytes.
|
||||
* The innermost level has sig_len=1, 'u', NUL, then 4 bytes for the uint32 value.
|
||||
* The field header is: 1 byte field_code + 1 byte sig_len + 1 byte 'v' + 1 byte NUL = 4 bytes. */
|
||||
size_t fields_size = 4 + (depth * 3) + 4; /* field header + nested variant sigs + uint32 */
|
||||
size_t padded_fields = ALIGN8(fields_size);
|
||||
size_t total = sizeof(BusMessageHeader) + padded_fields;
|
||||
|
||||
_cleanup_free_ void *buf = ASSERT_PTR(malloc0(total));
|
||||
|
||||
BusMessageHeader *h = buf;
|
||||
*h = (BusMessageHeader) {
|
||||
.endian = BUS_NATIVE_ENDIAN,
|
||||
.type = SD_BUS_MESSAGE_METHOD_CALL,
|
||||
.version = 1,
|
||||
.serial = 1,
|
||||
.fields_size = (uint32_t) fields_size,
|
||||
};
|
||||
|
||||
uint8_t *p = (uint8_t *) buf + sizeof(BusMessageHeader);
|
||||
|
||||
/* Unknown field code (triggers default: in message_parse_fields) */
|
||||
*p++ = 0xFF;
|
||||
/* Field signature: variant */
|
||||
*p++ = 1; /* sig length */
|
||||
*p++ = 'v';
|
||||
*p++ = '\0';
|
||||
|
||||
/* Nested variant signatures: each level declares its content is another variant */
|
||||
for (unsigned i = 0; i < depth; i++) {
|
||||
*p++ = 1; /* sig length */
|
||||
*p++ = 'v';
|
||||
*p++ = '\0';
|
||||
}
|
||||
|
||||
/* Innermost value: a uint32 */
|
||||
memset(p, 0, 4);
|
||||
|
||||
ASSERT_OK(sd_bus_new(&bus));
|
||||
|
||||
ASSERT_ERROR(bus_message_from_malloc(bus, buf, total, NULL, 0, NULL, &m), EBADMSG);
|
||||
}
|
||||
|
||||
static void test_bus_label_escape(void) {
|
||||
test_bus_label_escape_one("foo123bar", "foo123bar");
|
||||
test_bus_label_escape_one("foo.bar", "foo_2ebar");
|
||||
@@ -415,6 +468,7 @@ int main(int argc, char *argv[]) {
|
||||
test_bus_path_encode();
|
||||
test_bus_path_encode_unique();
|
||||
test_bus_path_encode_many();
|
||||
test_bus_nested_variant_depth_limit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user