fix message bound issues

This commit is contained in:
hippoz 2023-01-11 18:44:38 +02:00
parent ce164d8d5d
commit 55b1a9b760
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
2 changed files with 46 additions and 9 deletions

View file

@ -288,6 +288,11 @@ ssize_t bus_client_recv(bus_t *s, int i, void *buf, size_t n)
int bus_broadcast_message(bus_t *s, wire_message_t *msg, wire_context_t *ctx, char *sender_unique_name)
{
uint32_t body_end = ctx->byte_cursor + msg->body_length;
if (body_end >= ctx->data_len) {
return -1;
}
int left = s->clients_count;
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
if (s->clients[i].match_count <= 0) {
@ -320,6 +325,10 @@ int bus_broadcast_message(bus_t *s, wire_message_t *msg, wire_context_t *ctx, ch
}
}
}
// We rely on the byte_cursor being at the end of the message upon processing.
ctx->byte_cursor = body_end;
return 0;
}
@ -330,12 +339,12 @@ int bus_unicast_message(bus_t *s, wire_message_t *msg, wire_context_t *ctx, char
return -1;
}
uint8_t reply_data[4096];
memset(reply_data, 0, 4096);
uint8_t reply_data[8192];
memset(reply_data, 0, 8192);
wire_context_t reply_ctx = {
.byte_cursor = 0,
.data = reply_data,
.data_len = 4096,
.data_len = 8192,
};
TRYST(wire_compose_unicast_reply(&reply_ctx, ctx, msg, sender_unique_name));
@ -511,6 +520,8 @@ int handle_remove_match(bus_t *s, int i, wire_message_t *msg, wire_context_t *ct
int handle_get_connection_stats(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
(void)ctx;
TRYPTR(wire_get_name_string(ctx));
// TODO: stub (always returns empty array)
printf("FIXME: STUB: GetConnectionStats\n");
@ -628,6 +639,11 @@ int bus_client_process_message(bus_t *s, int i, wire_context_t *ctx)
return -1;
}
uint32_t body_end = ctx->byte_cursor + msg.body_length;
if (body_end >= ctx->data_len) {
return -1;
}
wire_message_field_t *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION];
wire_message_field_t *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER];
@ -645,12 +661,12 @@ int bus_client_process_message(bus_t *s, int i, wire_context_t *ctx)
const bus_method_handler_t *handler = &bus_method_handlers[j];
if (strcmp(handler->name, member_field->t.str) == 0) {
TRYST(handler->handler(s, i, &msg, ctx, &reply_ctx));
return 0;
goto end_nonfatal;
}
}
printf("FIXME: daemon method '%s' is not implemented or invalid\n", member_field->t.str);
_process_message_reply_error("org.freedesktop.DBus.Error.UnknownMethod");
return 0;
goto end_nonfatal;
}
// message needs to be routed
@ -663,15 +679,32 @@ int bus_client_process_message(bus_t *s, int i, wire_context_t *ctx)
if (destination_field->present) {
if (bus_unicast_message(s, &msg, ctx, destination_field->t.str, s->names[client->unique_name_index].name) < 0) {
_process_message_reply_error("xyz.hippoz.jitterbug.UnicastFailed");
return 0;
goto end_nonfatal;
}
} else {
if (bus_broadcast_message(s, &msg, ctx, s->names[client->unique_name_index].name) < 0) {
_process_message_reply_error("xyz.hippoz.jitterbug.BroadcastFailed");
return 0;
goto end_nonfatal;
}
}
end_nonfatal:
if (ctx->byte_cursor != body_end) {
// The code above did not properly consume the entire message while parsing.
// This is bad, because we expect the byte_cursor after this function to be
// exactly at the end of a message. We rely on this invariant for message
// boundries. We can obviously just set the byte_cursor to the body_end
// that we have calculated and move on, however, not consuming the entire
// message is nonetheless a bug that should be fixed, or an indicator of
// another bug or something going wrong.
// In this case, I've decided to set the byte_cursor to the end of the
// body and print an error message. In the future, we may want to have
// separate debug builds, and maybe exit the program if we are in a
// debug build and we encounter something like this.
fprintf(stderr, "notice: parsing code did not consume the entire message (expected: %d, actual: %d)\n", body_end, ctx->byte_cursor);
ctx->byte_cursor = body_end;
}
return 0;
}
@ -685,7 +718,8 @@ int bus_client_drain_messages(bus_t *s, int ci, uint8_t *data, uint32_t data_len
TRYST(bus_client_process_message(s, ci, &ctx));
for (int i = 0; i < 10; i++) {
int i = 0;
for (; i < 10; i++) {
if (ctx.byte_cursor >= ctx.data_len || ctx.data[ctx.byte_cursor] != 'l') {
// no more messages
break;
@ -696,6 +730,8 @@ int bus_client_drain_messages(bus_t *s, int ci, uint8_t *data, uint32_t data_len
TRYST(bus_client_process_message(s, ci, &ctx));
}
printf("processed %d messages - cursor:%d; data_len:%ld\n", i + 1, ctx.byte_cursor, ctx.data_len);
return 0;
}
@ -706,7 +742,7 @@ int bus_turn(bus_t *s)
static const char auth_ok[] = "OK aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n";
static const char auth_list[] = "REJECTED EXTERNAL\r\n";
static const char auth_data[] = "DATA\r\n";
static const int data_buffer_len = 8192;
static const int data_buffer_len = 16384;
// We can keep a padding of null bytes for the data buffer. In the event that, for
// example, a string function is called on a char array without a proper ending null

1
wire.c
View file

@ -383,6 +383,7 @@ int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_me
memcpy(&c->data[c->byte_cursor], &msg_c->data[msg_c->byte_cursor], msg->body_length);
c->byte_cursor += msg->body_length;
msg_c->byte_cursor += msg->body_length;
return 0;
}