From: Lennart Poettering Date: Mon, 2 Dec 2013 14:28:20 +0000 (+0100) Subject: bus: when replying to an incoming message and the vtable contains the expected return... X-Git-Tag: v209~1162 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=6717d473506800363af9d2bafbf263ee054e856d bus: when replying to an incoming message and the vtable contains the expected return signature generate an error if the response message doesn't match it --- diff --git a/TODO b/TODO index cfabfca9f..d2e5348ba 100644 --- a/TODO +++ b/TODO @@ -124,7 +124,6 @@ Features: - implement monitor logic - properly map matches with well-known names against messages with unique names - when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed - - enforce signatures on response messages - see if we can drop more message validation on the sending side - support "const" properties as flag - add API to clone sd_bus_message objects diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index a1e6c9f97..dc8569447 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -568,6 +568,7 @@ static int message_new_reply( } t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED); + t->enforced_reply_signature = call->enforced_reply_signature; *m = t; return 0; @@ -3962,6 +3963,13 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) { if (m->poisoned) return -ESTALE; + /* In vtables the return signature of method calls is listed, + * let's check if they match if this is a response */ + if (m->header->type == SD_BUS_MESSAGE_METHOD_RETURN && + m->enforced_reply_signature && + !streq(strempty(m->root_container.signature), m->enforced_reply_signature)) + return -ENOMSG; + /* If there's a non-trivial signature set, then add it in here */ if (!isempty(m->root_container.signature)) { r = message_append_field_signature(m, SD_BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL); diff --git a/src/libsystemd-bus/bus-message.h b/src/libsystemd-bus/bus-message.h index 72a79f792..34dbc5d56 100644 --- a/src/libsystemd-bus/bus-message.h +++ b/src/libsystemd-bus/bus-message.h @@ -116,6 +116,11 @@ struct sd_bus_message { char *peeked_signature; + /* If set replies to this message must carry the signature + * specified here to successfully seal. This is initialized + * from the vtable data */ + const char *enforced_reply_signature; + usec_t timeout; char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c index 05a62f4a3..7cd34c991 100644 --- a/src/libsystemd-bus/bus-objects.c +++ b/src/libsystemd-bus/bus-objects.c @@ -312,6 +312,11 @@ static int method_callbacks_run( "Invalid arguments '%s' to call %s.%s(), expecting '%s'.", signature, c->interface, c->member, strempty(c->vtable->x.method.signature)); + /* Keep track what the signature of the reply to this message + * should be, so that this can be enforced when sealing the + * reply. */ + m->enforced_reply_signature = strempty(c->vtable->x.method.result); + if (c->vtable->x.method.handler) { r = c->vtable->x.method.handler(bus, m, u, &error); return bus_maybe_reply_error(m, r, &error); diff --git a/src/libsystemd-bus/test-bus-objects.c b/src/libsystemd-bus/test-bus-objects.c index 95278e36e..0ab7a148d 100644 --- a/src/libsystemd-bus/test-bus-objects.c +++ b/src/libsystemd-bus/test-bus-objects.c @@ -61,6 +61,9 @@ static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_ log_info("AlterSomething() called, got %s, returning %s", s, n); + /* This should fail, since the return type doesn't match */ + assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG); + r = sd_bus_reply_method_return(m, "s", n); assert_se(r >= 0);