#include "dbus-marshal-gvariant.h"
#include "dbus-marshal-validate.h"
#include "dbus-asv-util.h"
-#include "kdbus.h"
+#include <linux/kdbus.h>
#include "dbus-watch.h"
#include "dbus-errors.h"
#include "dbus-bus.h"
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
-# if defined(__arm__) || defined(__aarch64__)
+# if defined(__arm__)
# define __NR_memfd_create 385
-# elif defined(__i386__)
+# elif defined(__aarch64__)
# define __NR_memfd_create 279
+# elif defined(__i386__)
+# define __NR_memfd_create 356
+# elif defined(__x86_64__)
+# define __NR_memfd_create 319
# else
# error "Architecture not supported"
# endif
((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
((uint8_t *)(iter) >= (uint8_t *)(first)); \
iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size)))
-#define KDBUS_DEFAULT_TIMEOUT_NS 5000000000LU
+#define KDBUS_INFINITE_TIMEOUT_NS 0x3fffffffffffffffLLU
/**
* @defgroup DBusTransportKdbus DBusTransport implementations for kdbus
*/
/** Default Size of the memory area for received non-memfd messages. */
-#define RECEIVE_POOL_SIZE_DEFAULT_SIZE (2 * 1024LU * 1024LU)
+#define RECEIVE_POOL_SIZE_DEFAULT_SIZE (16 * 1024LU * 1024LU)
/** Name of environmental variable to define receive pool size*/
#define RECEIVE_POOL_SIZE_ENV_VAR_NAME "KDBUS_MEMORY_POOL_SIZE"
/** Max size of pool size in megabytes*/
if (errMessage == NULL)
return NULL;
- if (sender)
- dbus_message_set_sender (errMessage, sender);
+ if (sender && !dbus_message_set_sender (errMessage, sender))
+ {
+ _dbus_verbose ("oom");
+ dbus_message_unref (errMessage);
+ return NULL;
+ }
return errMessage;
}
return;
size = strlen (parameter) + strlen (value) + 1;
- if (size > 1024)
+ if (size >= 1024)
return;
- snprintf (buf, size, "%s:%s", parameter, value);
+ snprintf (buf, size + 1, "%s:%s", parameter, value);
_kdbus_bloom_add_data (kdbus, bloom_data, buf, size);
}
size_t size;
size = strlen (parameter) + strlen (value) + 1;
- if (size > 1024)
+ if (size >= 1024)
return;
- snprintf (buf, size, "%s:%s", parameter, value);
+ snprintf (buf, size + 1, "%s:%s", parameter, value);
for (;;)
{
static int
prepare_mfd (int memfd,
- const char *header,
- uint64_t header_size,
const char *body,
uint64_t body_size)
{
- const char *data[] = { header, body };
- uint64_t count[] = { header_size, body_size };
int64_t wr;
- size_t p;
_dbus_verbose ("sending data via memfd\n");
- for (p = 0; p < sizeof (data) / sizeof (data[0]); ++p)
+ while (body_size)
{
- while (count[p])
+ wr = write (memfd, body, body_size);
+ if (wr < 0)
{
- wr = write (memfd, data[p], count[p]);
- if (wr < 0)
- {
- _dbus_verbose ("writing to memfd failed: (%d) %m\n", errno);
- return -1;
- }
- count[p] -= wr;
- data[p] += wr;
+ _dbus_verbose ("writing to memfd failed: (%d) %m\n", errno);
+ return -1;
}
+ body_size -= wr;
+ body += wr;
}
// seal data - kdbus module needs it
{
case ENXIO: /* no such id on the bus */
case ESRCH:
- dbus_set_error (error,
- DBUS_ERROR_NAME_HAS_NO_OWNER,
- "Name \"%s\" does not exist",
- destination);
- break;
-
- case EADDRNOTAVAIL:
- case ECONNRESET:
- /* when well known name is not available on the bus */
if (is_auto_start)
dbus_set_error (error,
DBUS_ERROR_SERVICE_UNKNOWN,
destination);
break;
- case EMLINK:
+ case EADDRNOTAVAIL:
+ dbus_set_error (error,
+ DBUS_ERROR_SERVICE_UNKNOWN,
+ "No support for activation for name: \"%s\"", destination);
+ break;
+
+ case EXFULL:
dbus_set_error (error,
DBUS_ERROR_LIMITS_EXCEEDED,
- NULL,
- "The maximum number of pending replies per connection has been reached");
+ "The memory pool of the receiver is full");
break;
case ENOBUFS:
- case EXFULL:
dbus_set_error (error,
DBUS_ERROR_LIMITS_EXCEEDED,
- "No space in receiver's buffer",
- destination);
+ "Too many pending messages on the receiver side");
+ break;
+
+ case EMSGSIZE:
+ dbus_set_error (error,
+ DBUS_ERROR_LIMITS_EXCEEDED,
+ "The size of the message is excessive");
+ break;
+
+ case EMLINK:
+ dbus_set_error (error,
+ DBUS_ERROR_LIMITS_EXCEEDED,
+ "The maximum number of pending replies per connection has been reached");
+ break;
+
+ case ETIMEDOUT:
+ dbus_set_error (error,
+ DBUS_ERROR_TIMEOUT,
+ "Timeout was reached");
+ break;
+
+ case EPERM:
+ dbus_set_error (error,
+ DBUS_ERROR_ACCESS_DENIED,
+ "Permission denied");
break;
default:
+ dbus_set_error (error,
+ DBUS_ERROR_FAILED,
+ "Something went wrong: %s",
+ _dbus_strerror (ret));
break;
}
}
#endif
-static dbus_bool_t
+#ifdef LIBDBUSPOLICY
+static int
can_send (DBusTransportKdbus *transport,
DBusMessage *message)
{
- dbus_bool_t result = TRUE;
-#ifdef LIBDBUSPOLICY
- {
- int ret = 1;
+ int ret = DBUSPOLICY_RESULT_ALLOW;
if (NULL != transport->policy)
{
dbus_uint32_t reply_serial = dbus_message_get_reply_serial (message);
* Otherwise - check the policy.
*/
if (0 == reply_serial)
- ret = dbuspolicy1_check_out (transport->policy,
- dbus_message_get_destination (message),
- dbus_message_get_sender (message),
- dbus_message_get_path (message),
- dbus_message_get_interface (message),
- dbus_message_get_member (message),
- dbus_message_get_type (message),
- dbus_message_get_error_name (message),
- reply_serial,
- !dbus_message_get_no_reply (message));
+ {
+ /* If method call or unicast signal, check policy */
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
+ (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL &&
+ dbus_message_get_destination (message) != NULL))
+ ret = dbuspolicy1_check_out (transport->policy,
+ dbus_message_get_destination (message),
+ transport->my_DBus_unique_name,
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message),
+ dbus_message_get_type (message),
+ dbus_message_get_error_name (message),
+ reply_serial,
+ !dbus_message_get_no_reply (message));
+ }
}
- result = (1 == ret);
- }
-#endif
- return result;
+ return ret;
}
+#endif
+
+/* function prototypes */
+static int kdbus_message_size (const struct kdbus_msg *msg,
+ int *n_fds);
+static int kdbus_decode_dbus_message (const struct kdbus_msg *msg,
+ char *data,
+ DBusTransportKdbus *kdbus_transport,
+ int *fds,
+ int *n_fds);
static int
kdbus_write_msg_internal (DBusTransportKdbus *transport,
DBusMessage *message,
const char *destination,
- dbus_bool_t check_sync_reply,
+ DBusMessage **sync_reply,
dbus_bool_t check_privileges)
{
struct kdbus_msg *msg = NULL;
int memfd = -1;
const int *unix_fds;
unsigned fds_count;
+ const char* header_data;
DBusError error;
+ const char *destination_name = destination;
dbus_uint64_t items_size;
dbus_uint64_t flags = 0;
dbus_uint64_t timeout_ns_or_cookie_reply = 0;
-
+ dbus_bool_t check_sync_reply = FALSE;
dbus_error_init (&error);
+ if (sync_reply != NULL)
+ check_sync_reply = TRUE;
+
// determine destination and destination id
if (destination)
{
else /* method calls */
{
long tv_sec, tv_usec;
+ int timeout_ms = _dbus_message_get_timeout_ms(message);
_dbus_get_monotonic_time (&tv_sec, &tv_usec);
/* ms us ns */
- timeout_ns_or_cookie_reply = (dbus_uint64_t)tv_sec * 1000ULL * 1000ULL * 1000ULL
- + tv_usec * 1000ULL
- + KDBUS_DEFAULT_TIMEOUT_NS;
+ timeout_ns_or_cookie_reply = 1U | ( /* ensure nonzero */
+ (dbus_uint64_t)tv_sec * 1000ULL * 1000ULL * 1000ULL
+ + tv_usec * 1000ULL + (
+ timeout_ms == -1 ? _DBUS_DEFAULT_TIMEOUT_VALUE * 1000000LLU :
+ timeout_ms == DBUS_TIMEOUT_INFINITE ? KDBUS_INFINITE_TIMEOUT_NS :
+ (uint64_t)timeout_ms * 1000000U
+ )
+ );
flags |= KDBUS_MSG_EXPECT_REPLY;
}
/* build message contents */
item = msg->items;
- if (memfd >= 0)
+ header_data = _dbus_string_get_const_data (header);
+
+ _dbus_verbose ("sending data by vec\n");
+ item = _kdbus_item_add_payload_vec (item,
+ header_size,
+ (uintptr_t)header_data);
+ if (body_size > 0)
{
- if (prepare_mfd (memfd,
- _dbus_string_get_const_data (header), header_size,
- _dbus_string_get_const_data (body), body_size) == -1)
+ const char* body_data = _dbus_string_get_const_data (body);
+ size_t body_offsets_size;
+ const char *footer_ptr;
+
+ /* determine body offsets size */
+ if (ret_size <= 0xFF)
+ body_offsets_size = 1;
+ else if (ret_size <= 0xFFFF)
+ body_offsets_size = 2;
+ else if (ret_size <= 0xFFFFFFFF)
+ body_offsets_size = 4;
+ else
+ body_offsets_size = 8;
+
+ /* check footer size */
+ footer_ptr = body_data + body_size - body_offsets_size -1;
+ while (footer_ptr >= body_data && (*footer_ptr) != 0)
+ footer_ptr--;
+
+ if (footer_ptr < body_data)
{
ret_size = -1;
goto out;
}
- item = _kdbus_item_add_payload_memfd (item,
- 0,
- ret_size,
- memfd);
- }
- else
- {
- const char* header_data = _dbus_string_get_const_data (header);
-
- _dbus_verbose ("sending data by vec\n");
- item = _kdbus_item_add_payload_vec (item,
- header_size,
- (uintptr_t)header_data);
- if (body_size > 0)
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+ if (-1 != debug)
{
- const char* body_data = _dbus_string_get_const_data (body);
+ debug_str ("Header to send:", header);
+ debug_str ("Body to send:", body);
+ }
+#endif
-#ifdef DBUS_ENABLE_VERBOSE_MODE
- if (-1 != debug)
+ if (memfd >= 0)
+ {
+ /* prepare memfd for body */
+ if (-1 == prepare_mfd (memfd,
+ body_data,
+ (uint64_t)((footer_ptr - body_data) * sizeof(char))))
{
- debug_str ("Header to send:", header);
- debug_str ("Body to send:", body);
+ ret_size = -1;
+ goto out;
}
-#endif
+ /* body */
+ item = _kdbus_item_add_payload_memfd (item,
+ 0,
+ (footer_ptr - body_data) * sizeof(char),
+ memfd);
+
+ /* footer */
+ item = _kdbus_item_add_payload_vec (item,
+ (body_data + body_size - footer_ptr) * sizeof(char),
+ (uintptr_t)footer_ptr);
+ }
+ else
+ {
while (body_size > 0)
{
- dbus_uint64_t part_size = body_size;
+ dbus_uint32_t part_size;
- if (part_size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
+ if (body_size < KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
+ part_size = body_size;
+ else
part_size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
+ /* we need to adjust part size if footer does not fit as a whole */
+ if (body_size - part_size > 0 && footer_ptr < (body_data + part_size))
+ part_size = footer_ptr - body_data;
+
_dbus_verbose ("attaching body part\n");
item = _kdbus_item_add_payload_vec (item,
part_size,
body_data += part_size;
body_size -= part_size;
}
- }
- }
+ } /* memfd */
+ } /* body_size */
if (fds_count)
item = _kdbus_item_add_fds (item, unix_fds, fds_count);
setup_bloom_filter_for_message (message, transport->kdbus, filter);
}
- if (check_privileges && !can_send (transport, message))
+#ifdef LIBDBUSPOLICY
+ if (check_privileges)
{
- DBusMessage *reply;
+ int check;
- reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED,
- NULL,
- "Cannot send message - message rejected "
- "due to security policies",
- message);
- if (reply == NULL)
- {
- ret_size = -1;
- }
- else
+ check = can_send (transport, message);
+
+ if (check != DBUSPOLICY_RESULT_ALLOW)
{
- /* puts locally generated reply into received messages queue */
- if (!add_message_to_received (reply, transport->base.connection))
- ret_size = -1;
- }
+ DBusMessage *reply;
- goto out;
- }
+ switch (check)
+ {
+ case DBUSPOLICY_RESULT_DENY:
+ reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
+ "Cannot send message - message rejected due to XML security policies",
+ message);
+ break;
+
+ case DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE:
+ _dbus_assert (destination_name != NULL);
+ if (dbus_message_get_auto_start (message))
+ reply = reply_with_error (DBUS_ERROR_SERVICE_UNKNOWN, NULL,
+ "Cannot send message - destination not known",
+ message);
+ else
+ reply = reply_with_error (DBUS_ERROR_NAME_HAS_NO_OWNER, "Name \"%s\" does not exist",
+ destination_name,
+ message);
+ break;
+
+ case DBUSPOLICY_RESULT_KDBUS_ERROR:
+ reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
+ "Cannot send message - message rejected due to internal libdbuspolicy error (kdbus)",
+ message);
+ break;
+
+ case DBUSPOLICY_RESULT_CYNARA_ERROR:
+ reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
+ "Cannot send message - message rejected due to internal libdbuspolicy error (Cynara)",
+ message);
+ break;
+
+ default:
+ reply = reply_with_error (DBUS_ERROR_ACCESS_DENIED, NULL,
+ "Cannot send message - unknown libdbuspolicy error",
+ message);
+ break;
+ }
+
+ if (reply == NULL)
+ {
+ ret_size = -1;
+ }
+ else
+ {
+ if (check_sync_reply)
+ {
+ *sync_reply = reply;
+ }
+ else
+ {
+ /* puts locally generated reply into received messages queue */
+ if (!add_message_to_received (reply, transport->base.connection))
+ ret_size = -1;
+ }
+ }
+ goto out;
+ } /* ret != DBUSPOLICY_RESULT_ALLOW */
+ } /* check_privileges */
+#endif
if (send_message (transport,
msg,
NULL,
error.message,
message);
+ dbus_error_free(&error);
}
if (reply == NULL)
}
else
{
- /* puts locally generated reply into received messages queue */
- if (!add_message_to_received (reply, transport->base.connection))
- ret_size = -1;
+ if (check_sync_reply)
+ {
+ *sync_reply = reply;
+ }
+ else
+ {
+ /* puts locally generated reply into received messages queue */
+ if (!add_message_to_received (reply, transport->base.connection))
+ ret_size = -1;
+ }
}
+ goto out;
}
- if (-1 != ret_size && check_sync_reply)
- kdbus_close_message (transport, msg_reply);
+ if (check_sync_reply)
+ {
+ DBusString str;
+ int size, ret, *fds;
+ unsigned n_fds;
+ char *data;
+
+ /* check message size */
+ size = kdbus_message_size (msg_reply, &n_fds);
+ if (size <= 0)
+ {
+ ret_size = -1;
+ kdbus_close_message (transport, msg_reply);
+ goto out;
+ }
+
+ /* alloc buffer for decoded message */
+ data = dbus_malloc (sizeof (char) * size);
+ if (data == NULL)
+ {
+ ret_size = -1;
+ kdbus_close_message (transport, msg_reply);
+ goto out;
+ }
+
+ /* alloc palce for fds */
+ fds = dbus_malloc (sizeof (int) * (n_fds + 1));
+ if (fds == NULL)
+ {
+ ret_size = -1;
+ kdbus_close_message (transport, msg_reply);
+ dbus_free (data);
+ goto out;
+ }
- out:
+ /* decode dbus message */
+ ret = kdbus_decode_dbus_message (msg_reply, data,
+ transport, fds, &n_fds);
+ if (ret <= 0)
+ {
+ ret_size = -1;
+ kdbus_close_message (transport, msg_reply);
+ dbus_free (fds);
+ dbus_free (data);
+ goto out;
+ }
+ _dbus_string_init_const_len (&str, data, ret);
+
+ /* create DBusMessage from kmsg */
+ *sync_reply = _dbus_decode_kmsg (&str, msg_reply->src_id, fds, n_fds);
+ if (*sync_reply == NULL)
+ ret_size = -1;
+
+ kdbus_close_message (transport, msg_reply);
+ dbus_free (fds);
+ dbus_free (data);
+ }
+
+out:
if (msg)
_kdbus_free_msg (msg);
if (memfd >= 0)
DBusMessage *message,
const char *destination)
{
- return kdbus_write_msg_internal (transport, message, destination, FALSE, TRUE);
+ return kdbus_write_msg_internal (transport, message, destination, NULL, TRUE);
}
static dbus_uint64_t
* and configures transport.
* As a result unique id on he bus is obtained.
*
- * @see KDBUS_HELLO_* flags in kdbus.h
+ * @see KDBUS_HELLO_* flags in <linux/kdbus.h>
*
* @param transport transport structure
* @param registration_flags aditional flags to modify registration process
int ret;
dbus_uint64_t flags;
+#ifdef LIBDBUSPOLICY
+ void *policy = dbuspolicy1_init_shared (_kdbus_get_path(transport->kdbus),
+ _kdbus_get_fd(transport->kdbus));
+ if (NULL == policy)
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_NO_REPLY,
+ "Did not receive a reply. Possible causes include: couldn't load dbus policy for kdbus transport or the message bus security policy blocked the reply.");
+ return FALSE;
+ }
+
+ transport->policy = policy;
+#endif
+
flags = KDBUS_HELLO_ACCEPT_FD;
if (registration_flags & REGISTER_FLAG_MONITOR)
flags |= KDBUS_HELLO_MONITOR;
if (ret != 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED, "Hello failed: %d", -ret);
+#ifdef LIBDBUSPOLICY
+ dbuspolicy1_free (policy);
+#endif
return FALSE;
}
+#ifdef LIBDBUSPOLICY
+ dbuspolicy1_init_set_pool (transport->policy, _kdbus_get_pool(transport->kdbus));
+#endif
+
transport->my_DBus_unique_name = create_unique_name_from_unique_id (_kdbus_get_id (transport->kdbus));
if (NULL == transport->my_DBus_unique_name)
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "Hello post failed: %d", -ret);
+#ifdef LIBDBUSPOLICY
+ dbuspolicy1_free (policy);
+#endif
return FALSE;
}
}
static dbus_bool_t
-kernel_match_needed (MatchRule *rule)
-{
- int message_type;
-
- /* Allow only NameOwnerChanged member */
- if (strcmp_existing (_match_rule_get_member (rule), "NameOwnerChanged") != 0)
- return FALSE;
-
- /* Allow only signals */
- message_type = _match_rule_get_message_type (rule);
- if (message_type != DBUS_MESSAGE_TYPE_INVALID && message_type != DBUS_MESSAGE_TYPE_SIGNAL)
- return FALSE;
-
- /* Check if from DBus */
- if (strcmp_existing (_match_rule_get_sender (rule), DBUS_SERVICE_DBUS) != 0)
- return FALSE;
-
- if (strcmp_existing (_match_rule_get_interface (rule), DBUS_INTERFACE_DBUS) != 0)
- return FALSE;
-
- if (strcmp_existing (_match_rule_get_path (rule), DBUS_PATH_DBUS) != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static dbus_bool_t
is_bloom_needed (MatchRule *rule)
{
int rule_int;
dbus_bool_t need_bloom = FALSE;
const char *rule_sender;
+ const char *rule_arg0 = NULL;
int ret;
rule_cookie = match_rule_get_cookie (rule);
+ rule_sender = _match_rule_get_sender (rule);
/*
* First check if it is org.freedesktop.DBus's NameOwnerChanged or any
* because it must be converted to special kdbus rule (kdbus has separate rules
* for kdbus (kernel) generated broadcasts).
*/
- if (kernel_match_needed (rule))
+ if (!strcmp_existing (rule_sender, DBUS_SERVICE_DBUS))
{
- ret = _kdbus_add_match_name_change (transport->kdbus,
- 0,
- rule_cookie,
- KDBUS_MATCH_ID_ANY,
- 0,
- KDBUS_MATCH_ID_ANY,
- 0);
- if (0 != ret)
- {
- _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
- ret, _dbus_strerror (ret));
- return FALSE;
- }
+ int message_type = _match_rule_get_message_type (rule);
- ret = _kdbus_add_match_id_change (transport->kdbus,
- 0,
- rule_cookie,
- KDBUS_MATCH_ID_ANY,
- 0);
- if (0 != ret)
+ if ((DBUS_MESSAGE_TYPE_INVALID == message_type || DBUS_MESSAGE_TYPE_SIGNAL == message_type)
+ && !strcmp_existing (_match_rule_get_interface (rule), DBUS_INTERFACE_DBUS)
+ && !strcmp_existing (_match_rule_get_path (rule), DBUS_PATH_DBUS))
{
- _dbus_verbose ("Failed adding match rule for adding id for daemon, error: %d, %s\n",
- ret, _dbus_strerror (ret));
- return FALSE;
- }
+ if (_match_rule_get_args_len(rule) == 1)
+ {
+ rule_arg0 = _match_rule_get_args(rule, 0);
+ if (rule_arg0)
+ {
+ DBusString str;
+ _dbus_string_init_const (&str, rule_arg0);
+ ret = _dbus_validate_bus_name (&str, 0, _dbus_string_get_length (&str));
+ if (!ret)
+ return FALSE;
+ }
+ }
+ if (!strcmp_existing (_match_rule_get_member (rule), "NameOwnerChanged"))
+ {
+ ret = _kdbus_add_match_name_change (transport->kdbus,
+ 0,
+ rule_cookie,
+ KDBUS_MATCH_ID_ANY,
+ 0,
+ KDBUS_MATCH_ID_ANY,
+ 0,
+ rule_arg0);
+ if (0 != ret)
+ {
+ _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
+ ret, _dbus_strerror (ret));
+ return FALSE;
+ }
- _dbus_verbose ("Added match rule for kernel correctly.\n");
+ _dbus_verbose ("Added match rule for kernel correctly.\n");
-/*
- * In case all of sender, interface and path are NULL, the rule
- * says simply about NameHasOwner signal from any object, any interface, any sender.
- * So, we need to consider that.
- * Otherwise, our job is finished here.
- */
- if (_match_rule_get_sender (rule) != NULL
- || _match_rule_get_interface (rule) != NULL
- || _match_rule_get_path (rule) != NULL)
+ ret = _kdbus_add_match_id_change (transport->kdbus,
+ 0,
+ rule_cookie,
+ KDBUS_MATCH_ID_ANY,
+ 0,
+ rule_arg0);
+ if (0 != ret)
+ {
+ _dbus_verbose ("Failed adding match rule for adding id for daemon, error: %d, %s\n",
+ ret, _dbus_strerror (ret));
+ return FALSE;
+ }
+ }
+ else if (strcmp (_match_rule_get_member (rule), "NameAcquired") == 0)
+ {
+ ret = _kdbus_add_match_name_acquired (transport->kdbus,
+ 0,
+ rule_cookie,
+ KDBUS_MATCH_ID_ANY,
+ 0,
+ _kdbus_get_id (transport->kdbus),
+ 0,
+ rule_arg0);
+ if (0 != ret)
+ {
+ _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
+ ret, _dbus_strerror (ret));
+ return FALSE;
+ }
+ }
+ else if (strcmp (_match_rule_get_member (rule), "NameLost") == 0)
+ {
+ ret = _kdbus_add_match_name_lost (transport->kdbus,
+ 0,
+ rule_cookie,
+ _kdbus_get_id (transport->kdbus),
+ 0,
+ KDBUS_MATCH_ID_ANY,
+ 0,
+ rule_arg0);
+ if (0 != ret)
+ {
+ _dbus_verbose ("Failed adding match rule for name removal for daemon, error: %d, %s\n",
+ ret, _dbus_strerror (ret));
+ return FALSE;
+ }
+ }
+ }
+ /* Sender=DBUS_SERVICE_DBUS matches (as opposed to wildcard sender) need no standard rule. */
+ if (rule_sender)
return TRUE;
}
need_bloom = is_bloom_needed (rule);
- rule_sender = _match_rule_get_sender (rule);
if (rule_sender != NULL)
{
DBusString str;
dbus_bool_t res = _dbus_asv_add_byte_array (&array_iter,
"LinuxSecurityLabel",
info.sec_label,
- strlen (info.sec_label)+1);
+ info.sec_label_len);
dbus_free (info.sec_label);
return NULL;
}
+static dbus_bool_t
+_mac_smack_use (void)
+{
+ static int cached_use = -1;
+
+ if (cached_use < 0)
+ cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
+
+ return cached_use;
+}
+
static DBusMessage *
capture_org_freedesktop_DBus_GetConnectionSELinuxSecurityContext (DBusTransportKdbus *transport,
DBusMessage *message,
if (info.sec_label != NULL)
{
- DBusMessage *reply;
+ if (_mac_smack_use())
+ {
+ dbus_set_error (error, DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
+ "Could not determine security context");
+ dbus_free (info.sec_label);
+ }
+ else
+ {
+ DBusMessage *reply;
- reply = reply_fixed_array (message, DBUS_TYPE_BYTE,
- info.sec_label,
- strlen (info.sec_label)+1);
+ reply = reply_fixed_array (message, DBUS_TYPE_BYTE,
+ info.sec_label,
+ info.sec_label_len);
- dbus_free (info.sec_label);
- return reply;
+ dbus_free (info.sec_label);
+ return reply;
+ }
}
else
{
{
if (item->type == KDBUS_ITEM_OWNED_NAME)
{
- DBusError local_error;
char *name_ptr = item->name.name;
- dbus_error_init ( &local_error );
- if (!dbus_validate_bus_name (name_ptr, &local_error))
+ if (!dbus_validate_bus_name (name_ptr, NULL))
continue;
if (flags & KDBUS_LIST_QUEUED)
if (!dbus_message_iter_append_basic (&array_iter,
DBUS_TYPE_STRING,
&name_ptr))
- goto oom_iterator;
+ {
+ if (flags & KDBUS_LIST_QUEUED)
+ free (name_ptr);
+ goto oom_iterator;
+ }
if (flags & KDBUS_LIST_QUEUED)
free (name_ptr);
if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
goto oom_reply;
+ _kdbus_free_mem (transport->kdbus, name_list);
+
return reply;
oom_iterator:
dbus_message_lock (sub_message);
- if (kdbus_write_msg_internal (transport, sub_message, name, FALSE, FALSE) == -1)
+ ret = kdbus_write_msg_internal (transport, sub_message, name, NULL, FALSE);
+
+ dbus_message_unref (sub_message);
+
+ if (ret == -1)
return NULL;
else
{
int ret = 1;
if (!strcmp (destination, DBUS_SERVICE_DBUS))
{
- if (!strcmp (dbus_message_get_interface (message), DBUS_INTERFACE_DBUS))
+ const char *interface = dbus_message_get_interface (message);
+ if (interface && !strcmp (interface, DBUS_INTERFACE_DBUS))
{
DBusError error;
const char *member = dbus_message_get_member (message);
+ _dbus_assert (member != NULL);
+
dbus_error_init (&error);
if (!strcmp (member, "Hello"))
else
ret = 0;
- } /* id DBUS_INTERFACE_DBUS */
+ } /* if DBUS_INTERFACE_DBUS */
} /* if DBUS_SERVICE_DBUS */
return ret;
* @return the length of the kdbus message's payload.
*/
static int
-kdbus_message_size (const struct kdbus_msg *msg)
+kdbus_message_size (const struct kdbus_msg *msg,
+ int *n_fds)
{
const struct kdbus_item *item;
int ret_size = 0;
+ *n_fds = 0;
KDBUS_ITEM_FOREACH (item, msg, items)
{
if (item->size < KDBUS_ITEM_HEADER_SIZE)
case KDBUS_ITEM_PAYLOAD_MEMFD:
ret_size += item->memfd.size;
break;
+ case KDBUS_ITEM_FDS:
+ *n_fds = (item->size - KDBUS_ITEM_HEADER_SIZE) / sizeof (int);
+ break;
default:
break;
}
_dbus_verbose ("%s\n", const_ptr);
}
- dbus_message_set_sender (message, DBUS_SERVICE_DBUS);
+ if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+ goto error;
dbus_message_set_serial (message, get_next_client_serial (transport));
if (!add_message_to_received (message, transport->base.connection))
result = FALSE;
- _dbus_string_init (&names);
+ if (!_dbus_string_init (&names))
+ {
+ _dbus_verbose ("oom:_dbus_string_init");
+ return FALSE;
+ }
KDBUS_ITEM_FOREACH(item, msg, items)
switch (item->type)
if (_dbus_validate_bus_name (&name, 0, _dbus_string_get_length (&name)))
{
if (_dbus_string_get_length (&names) != 0)
- _dbus_string_append_byte (&names, ' ');
-
- _dbus_string_copy (&name,
+ {
+ if (!_dbus_string_append_byte (&names, ' '))
+ {
+ _dbus_string_free (&names);
+ return FALSE;
+ }
+ }
+
+ if (!_dbus_string_copy (&name,
0,
&names,
- _dbus_string_get_length (&names));
+ _dbus_string_get_length (&names)))
+ {
+ _dbus_string_free (&names);
+ return FALSE;
+ }
}
}
break;
if (load_dbus_header (transport, &header, message_data, message_len))
got_header = TRUE;
}
-
- if (got_header && _dbus_header_get_message_type (&header) != DBUS_MESSAGE_TYPE_METHOD_CALL)
+ if (got_header &&
+ _dbus_header_get_message_type (&header) != DBUS_MESSAGE_TYPE_METHOD_CALL &&
+ _dbus_header_get_message_type (&header) != DBUS_MESSAGE_TYPE_SIGNAL)
{
result = TRUE;
}
DBUS_HEADER_FIELD_DESTINATION,
DBUS_TYPE_STRING,
&destination);
+ if (!destination)
+ destination = transport->my_DBus_unique_name;
_dbus_header_get_field_basic (&header,
DBUS_HEADER_FIELD_PATH,
size = item->memfd.size;
_dbus_verbose ("memfd.size : %llu\n", (unsigned long long)size);
- buf = mmap (NULL, size, PROT_READ , MAP_SHARED, item->memfd.fd, 0);
+ buf = mmap (NULL, size, PROT_READ, MAP_PRIVATE, item->memfd.fd, 0);
if (buf == MAP_FAILED)
{
_dbus_verbose ("mmap () fd=%i failed:%m", item->memfd.fd);
{
case KDBUS_ITEM_REPLY_TIMEOUT:
case KDBUS_ITEM_REPLY_DEAD:
- {
- DBusMessage *message = NULL;
- _dbus_verbose (" +%s (%llu bytes) cookie=%llu\n",
- enum_MSG (item->type), item->size, msg->cookie_reply);
-
- message = _dbus_generate_local_error_message (msg->cookie_reply,
- item->type == KDBUS_ITEM_REPLY_TIMEOUT ? DBUS_ERROR_NO_REPLY : DBUS_ERROR_NAME_HAS_NO_OWNER, NULL);
- if (message == NULL)
- {
- ret_size = -1;
- goto out;
- }
-
- dbus_message_set_serial (message, get_next_client_serial (kdbus_transport));
-
- if (!add_message_to_received (message, kdbus_transport->base.connection))
- ret_size = -1;
- }
+ _dbus_verbose (" +%s (%llu bytes) cookie=%llu\n",
+ enum_MSG (item->type), item->size, msg->cookie_reply);
break;
case KDBUS_ITEM_NAME_ADD:
char *data,
DBusTransportKdbus *kdbus_transport,
int *fds,
- int *n_fds,
- DBusError *error)
+ int *n_fds)
{
int ret_size = 0;
int start;
dbus_uint64_t flags = 0;
int ret;
- DBusError error;
-
- dbus_error_init (&error);
start = _dbus_string_get_length (buffer);
return -1;
}
- buf_size = kdbus_message_size (msg);
+ buf_size = kdbus_message_size (msg, n_fds);
if (buf_size == -1)
{
_dbus_verbose ("kdbus error - too short message: %d (%m)\n", errno);
}
data = _dbus_string_get_data_len (buffer, start, buf_size);
- ret_size = kdbus_decode_msg (msg, data, kdbus_transport, fds, n_fds, &error);
+ ret_size = kdbus_decode_msg (msg, data, kdbus_transport, fds, n_fds);
if (ret_size == -1) /* error */
_dbus_string_set_length (buffer, start);
return ret_size;
}
+#ifdef ENABLE_KDBUS_SYNC_CALLS
+static DBusMessage *
+kdbus_send_sync_call (DBusTransportKdbus *transport,
+ DBusMessage *message)
+{
+ DBusMessage *reply = NULL;
+ DBusError error;
+ const char *destination;
+
+ dbus_message_lock (message);
+
+ destination = dbus_message_get_destination (message);
+ if (destination)
+ {
+ int ret;
+
+ ret = capture_org_freedesktop_DBus ((DBusTransportKdbus*)transport, destination, message, &reply);
+ if (ret < 0)
+ goto error;
+ else if (ret == 0)
+ goto out;
+ }
+
+ kdbus_write_msg_internal (transport, message, destination, &reply, TRUE);
+ if (reply == NULL)
+ goto error;
+ else
+ goto out;
+
+error:
+
+ dbus_error_init (&error);
+
+ dbus_set_error (&error, DBUS_ERROR_FAILED,
+ "Something went wrong");
+
+ reply = reply_with_error ((char*)error.name,
+ NULL,
+ error.message,
+ message);
+
+ dbus_error_free (&error);
+
+out:
+
+ _dbus_assert (reply != NULL);
+ dbus_message_lock (reply);
+
+ return reply;
+}
+#endif
+
/**
* Copy-paste from socket transport. Only renames done.
*/
again:
/* See if we've exceeded max messages and need to disable reading */
- if (kdbus_transport->activator == NULL)
- check_read_watch (kdbus_transport);
+ if (kdbus_transport->activator == NULL)
+ check_read_watch (kdbus_transport);
if (total > kdbus_transport->max_bytes_read_per_iteration)
{
oom = TRUE;
goto out;
}
- _dbus_message_loader_get_buffer (transport->loader, &buffer);
+ _dbus_message_loader_get_buffer (transport->loader, &buffer, NULL, NULL);
bytes_read = kdbus_read_message (kdbus_transport, buffer, fds, &n_fds);
* When timeout is set to -1 in client application,
* error messages are inserted directly to incoming queue and
* application hangs on dbus_poll.
- */
+ *
+ * This causes a busy loop in _dbus_connection_block_pending_call()
+ * There is no case of waiting for the locally-generated error reply
+
if (_dbus_connection_get_n_incoming (transport->connection) > 0)
{
timeout_milliseconds = 0;
}
+ */
+
/* This is kind of a hack; if we have stuff to write, then try
* to avoid the poll. This is probably about a 5% speedup on an
* echo client/server.
_dbus_transport_kdbus_get_unix_user);
_dbus_transport_set_get_unix_process_id_function (&kdbus_transport->base,
_dbus_transport_kdbus_get_unix_process_id);
+#ifdef ENABLE_KDBUS_SYNC_CALLS
+ _dbus_transport_set_send_sync_call_function (&kdbus_transport->base,
+ (DBusTransportSendSyncCallFunction) kdbus_send_sync_call);
+#endif
_dbus_transport_set_assure_protocol_function (&kdbus_transport->base,
_dbus_message_assure_gvariant,
DBUS_PROTOCOL_VERSION_GVARIANT);
return NULL;
}
-static dbus_bool_t
-initialize_policies (DBusTransportKdbus *transport, DBusBusType bus_type)
-{
- dbus_bool_t result = TRUE;
-
-#ifdef LIBDBUSPOLICY
- if (DBUS_BUS_SYSTEM == bus_type || DBUS_BUS_SESSION == bus_type)
- {
- transport->policy = dbuspolicy1_init (bus_type);
- if (NULL == transport->policy)
- result = FALSE;
- }
-#endif
-
- return result;
-}
-
/**
* Connects to kdbus, creates and sets-up transport.
*
goto failed_0;
}
- kdbus = _kdbus_new ();
+ kdbus = _kdbus_new (path);
if (NULL == kdbus)
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed_0;
}
- ret = _kdbus_open (kdbus, path);
+ ret = _kdbus_open (kdbus);
if (ret < 0)
{
dbus_set_error (error,
goto failed_1;
}
- if (!initialize_policies (transport,
- _dbus_bus_get_address_type (_dbus_string_get_data (&address))))
- {
- dbus_set_error (error,
- DBUS_ERROR_FAILED,
- "Can't load dbus policy for kdbus transport");
- _kdbus_close (kdbus);
- transport_finalize ((DBusTransport*)transport);
- transport = NULL;
- }
-
_dbus_string_free (&address);
return (DBusTransport*)transport;