static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
assert(p);
+ if (!u || FLAGS_SET(p->flags, SD_BUS_VTABLE_ABSOLUTE_OFFSET))
+ return SIZE_TO_PTR(p->x.method.offset); /* don't add offset on NULL, to make ubsan happy */
+
return (uint8_t*) u + p->x.method.offset;
}
static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
assert(p);
+ if (!u || FLAGS_SET(p->flags, SD_BUS_VTABLE_ABSOLUTE_OFFSET))
+ return SIZE_TO_PTR(p->x.property.offset); /* as above */
+
return (uint8_t*) u + p->x.property.offset;
}
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;
if (v->flags & SD_BUS_VTABLE_HIDDEN)
continue;
+ /* Let's not include properties marked as "explicit" in any message that contains a generic
+ * dump of properties, but only in those generated as a response to an explicit request. */
if (v->flags & SD_BUS_VTABLE_PROPERTY_EXPLICIT)
continue;
+ /* Let's not include properties marked only for invalidation on change (i.e. in contrast to
+ * those whose new values are included in PropertiesChanges message) in any signals. This is
+ * useful to ensure they aren't included in InterfacesAdded messages. */
+ if (reply->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
+ FLAGS_SET(v->flags, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION))
+ continue;
+
r = vtable_append_one_property(bus, reply, path, c, v, userdata, error);
if (r < 0)
return r;
if (r < 0)
return r;
- found_interface = !iface ||
- streq(iface, "org.freedesktop.DBus.Properties") ||
- streq(iface, "org.freedesktop.DBus.Peer") ||
- streq(iface, "org.freedesktop.DBus.Introspectable");
+ found_interface = !iface || STR_IN_SET(iface,
+ "org.freedesktop.DBus.Properties",
+ "org.freedesktop.DBus.Peer",
+ "org.freedesktop.DBus.Introspectable");
LIST_FOREACH(vtables, c, first) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_error *error) {
_cleanup_set_free_free_ Set *s = NULL;
- const char *previous_interface = NULL;
_cleanup_(introspect_free) struct introspect intro = {};
struct node_vtable *c;
bool empty;
if (c->vtable[0].flags & SD_BUS_VTABLE_HIDDEN)
continue;
- if (!streq_ptr(previous_interface, c->interface)) {
- if (previous_interface)
- fputs(" </interface>\n", intro.f);
-
- fprintf(intro.f, " <interface name=\"%s\">\n", c->interface);
- }
-
- r = introspect_write_interface(&intro, c->vtable);
+ r = introspect_write_interface(&intro, c->interface, c->vtable);
if (r < 0)
return r;
-
- previous_interface = c->interface;
}
- if (previous_interface)
- fputs(" </interface>\n", intro.f);
-
if (empty) {
/* Nothing?, let's see if we exist at all, and if not
* refuse to do anything */
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_set_free_free_ Set *s = NULL;
- Iterator i;
char *path;
int r;
if (r < 0)
return r;
- SET_FOREACH(path, s, i) {
+ SET_FOREACH(path, s) {
r = object_manager_serialize_path_and_fallbacks(bus, reply, path, &error);
if (r < 0)
return bus_maybe_reply_error(m, r, &error);
return 0;
if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Get") ||
- sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set"))
+ sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "Set")) {
+ const char *interface = NULL, *property = NULL;
+
+ (void) sd_bus_message_rewind(m, true);
+ (void) sd_bus_message_read_basic(m, 's', &interface);
+ (void) sd_bus_message_read_basic(m, 's', &property);
+
r = sd_bus_reply_method_errorf(
m,
SD_BUS_ERROR_UNKNOWN_PROPERTY,
- "Unknown property or interface.");
- else
+ "Unknown interface %s or property %s.", strnull(interface), strnull(property));
+ } else
r = sd_bus_reply_method_errorf(
m,
SD_BUS_ERROR_UNKNOWN_METHOD,
- "Unknown method '%s' or interface '%s'.", m->member, m->interface);
+ "Unknown method %s or interface %s.", m->member, m->interface);
if (r < 0)
return r;