This allows marking messages that contain "sensitive" data with a flag.
If it's set then the messages are erased from memory when the message is
freed.
Similar, a flag may be set on vtable entries: incoming/outgoing message
matching the entry will then automatically be flagged this way.
This is supposed to be an easy method to mark messages containing
potentially sensitive data (such as passwords) for proper destruction.
(Note that this of course is only is as safe as the broker in between is
doing something similar. But let's at least not be the ones at fault
here.)
LIBSYSTEMD_245 {
global:
+ sd_bus_message_sensitive;
sd_event_add_child_pidfd;
sd_event_source_get_child_pidfd;
sd_event_source_get_child_pidfd_own;
assert(m);
assert(part);
- if (part->memfd >= 0)
+ if (part->memfd >= 0) {
+ /* erase if requested, but ony if the memfd is not sealed yet, i.e. is writable */
+ if (m->sensitive && !m->sealed)
+ explicit_bzero_safe(part->data, part->size);
+
close_and_munmap(part->memfd, part->mmap_begin, part->mapped);
- else if (part->munmap_this)
+ } else if (part->munmap_this)
+ /* We don't erase sensitive data here, since the data is memory mapped from someone else, and
+ * we just don't know if it's OK to write to it */
munmap(part->mmap_begin, part->mapped);
- else if (part->free_this)
- free(part->data);
+ else {
+ /* Erase this if that is requested. Since this is regular memory we know we can write it. */
+ if (m->sensitive)
+ explicit_bzero_safe(part->data, part->size);
+
+ if (part->free_this)
+ free(part->data);
+ }
if (part != &m->body)
free(part);
static sd_bus_message* message_free(sd_bus_message *m) {
assert(m);
+ message_reset_parts(m);
+
if (m->free_header)
free(m->header);
- message_reset_parts(m);
-
/* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user
* reference to the bus message also is considered a reference to the bus connection itself. */
t->dont_send = !!(call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED);
t->enforced_reply_signature = call->enforced_reply_signature;
+ /* let's copy the sensitive flag over. Let's do that as a safety precaution to keep a transaction
+ * wholly sensitive if already the incoming message was sensitive. This is particularly useful when a
+ * vtable record sets the SD_BUS_VTABLE_SENSITIVE flag on a method call, since this means it applies
+ * to both the message call and the reply. */
+ t->sensitive = call->sensitive;
+
*m = TAKE_PTR(t);
return 0;
}
m->priority = priority;
return 0;
}
+
+_public_ int sd_bus_message_sensitive(sd_bus_message *m) {
+ assert_return(m, -EINVAL);
+
+ m->sensitive = true;
+ return 0;
+}
bool free_header:1;
bool free_fds:1;
bool poisoned:1;
+ bool sensitive:1;
/* The first and last bytes of the message */
struct bus_header *header;
if (require_fallback && !c->parent->is_fallback)
return 0;
+ if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
+ r = sd_bus_message_sensitive(m);
+ if (r < 0)
+ return r;
+ }
+
r = check_access(bus, m, c, &error);
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
if (require_fallback && !c->parent->is_fallback)
return 0;
+ if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
+ r = sd_bus_message_sensitive(m);
+ if (r < 0)
+ return r;
+ }
+
r = vtable_property_get_userdata(bus, m->path, c, &u, &error);
if (r <= 0)
return bus_maybe_reply_error(m, r, &error);
if (r < 0)
return r;
+ if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
+ r = sd_bus_message_sensitive(reply);
+ if (r < 0)
+ return r;
+ }
+
if (is_get) {
/* Note that we do not protect against reexecution
* here (using the last_iteration check, see below),
assert(c);
assert(v);
+ if (FLAGS_SET(c->vtable->flags, SD_BUS_VTABLE_SENSITIVE)) {
+ r = sd_bus_message_sensitive(reply);
+ if (r < 0)
+ return r;
+ }
+
r = sd_bus_message_open_container(reply, 'e', "sv");
if (r < 0)
return r;
SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 5,
SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION = 1ULL << 6,
SD_BUS_VTABLE_PROPERTY_EXPLICIT = 1ULL << 7,
+ SD_BUS_VTABLE_SENSITIVE = 1ULL << 8, /* covers both directions: method call + reply */
_SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40
};
int sd_bus_message_verify_type(sd_bus_message *m, char type, const char *contents);
int sd_bus_message_at_end(sd_bus_message *m, int complete);
int sd_bus_message_rewind(sd_bus_message *m, int complete);
+int sd_bus_message_sensitive(sd_bus_message *m);
/* Bus management */