summaryrefslogtreecommitdiff
path: root/src/libsystemd-bus
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-12-02 15:28:20 +0100
committerLennart Poettering <lennart@poettering.net>2013-12-02 15:29:40 +0100
commit6717d473506800363af9d2bafbf263ee054e856d (patch)
treec25bf710e766bebf53d62303e7e52412de9dddde /src/libsystemd-bus
parent99f37ad86e114b2d1c9eaedf2bc1a0004a265d26 (diff)
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
Diffstat (limited to 'src/libsystemd-bus')
-rw-r--r--src/libsystemd-bus/bus-message.c8
-rw-r--r--src/libsystemd-bus/bus-message.h5
-rw-r--r--src/libsystemd-bus/bus-objects.c5
-rw-r--r--src/libsystemd-bus/test-bus-objects.c3
4 files changed, 21 insertions, 0 deletions
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);