#include <config.h>
#include "bus.h"
+
+#include <stdio.h>
+
#include "activation.h"
#include "connection.h"
#include "services.h"
#include <dbus/dbus-hash.h>
#include <dbus/dbus-credentials.h>
#include <dbus/dbus-internals.h>
+#include "kdbus-d.h"
+#include <stdlib.h>
+
#ifdef DBUS_CYGWIN
#include <signal.h>
#endif
unsigned int keep_umask : 1;
unsigned int allow_anonymous : 1;
unsigned int systemd_activation : 1;
+ unsigned int is_kdbus : 1;
+ DBusConnection *myConnection;
};
static dbus_int32_t server_data_slot = -1;
}
static dbus_bool_t
-server_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- /* FIXME this can be done in dbus-mainloop.c
- * if the code in activation.c for the babysitter
- * watch handler is fixed.
- */
-
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
add_server_watch (DBusWatch *watch,
void *data)
{
context = server_get_context (server);
- return _dbus_loop_add_watch (context->loop,
- watch, server_watch_callback, server,
- NULL);
+ return _dbus_loop_add_watch (context->loop, watch);
}
static void
context = server_get_context (server);
- _dbus_loop_remove_watch (context->loop,
- watch, server_watch_callback, server);
+ _dbus_loop_remove_watch (context->loop, watch);
}
-
static void
-server_timeout_callback (DBusTimeout *timeout,
- void *data)
+toggle_server_watch (DBusWatch *watch,
+ void *data)
{
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
+ DBusServer *server = data;
+ BusContext *context;
+
+ context = server_get_context (server);
+
+ _dbus_loop_toggle_watch (context->loop, watch);
}
static dbus_bool_t
context = server_get_context (server);
- return _dbus_loop_add_timeout (context->loop,
- timeout, server_timeout_callback, server, NULL);
+ return _dbus_loop_add_timeout (context->loop, timeout);
}
static void
context = server_get_context (server);
- _dbus_loop_remove_timeout (context->loop,
- timeout, server_timeout_callback, server);
+ _dbus_loop_remove_timeout (context->loop, timeout);
}
static void
if (!dbus_server_set_watch_functions (server,
add_server_watch,
remove_server_watch,
- NULL,
+ toggle_server_watch,
server,
NULL))
{
process_config_first_time_only (BusContext *context,
BusConfigParser *parser,
const DBusString *address,
- dbus_bool_t systemd_activation,
+ BusContextFlags flags,
DBusError *error)
{
DBusString log_prefix;
retval = FALSE;
auth_mechanisms = NULL;
+ pidfile = NULL;
- context->systemd_activation = systemd_activation;
+ _dbus_init_system_log (TRUE);
+
+ if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
+ context->systemd_activation = TRUE;
+ else
+ context->systemd_activation = FALSE;
/* Check for an existing pid file. Of course this is a race;
* we'd have to use fcntl() locks on the pid file to
* avoid that. But we want to check for the pid file
* before overwriting any existing sockets, etc.
*/
- pidfile = bus_config_parser_get_pidfile (parser);
+
+ if (flags & BUS_CONTEXT_FLAG_WRITE_PID_FILE)
+ pidfile = bus_config_parser_get_pidfile (parser);
+
if (pidfile != NULL)
{
DBusString u;
if (auth_mechanisms[i] == NULL)
goto oom;
link = _dbus_list_get_next_link (auth_mechanisms_list, link);
+ i += 1;
}
}
else
if (address)
{
- DBusServer *server;
-
- server = dbus_server_listen (_dbus_string_get_const_data(address), error);
- if (server == NULL)
- {
- _DBUS_ASSERT_ERROR_IS_SET (error);
- goto failed;
- }
- else if (!setup_server (context, server, auth_mechanisms, error))
- {
- _DBUS_ASSERT_ERROR_IS_SET (error);
- goto failed;
- }
-
- if (!_dbus_list_append (&context->servers, server))
- goto oom;
+ if(!strcmp(_dbus_string_get_const_data(address), "kdbus"))
+ {
+ DBusBusType type;
+ DBusServer* server;
+ char* bus_address;
+
+ context->is_kdbus = TRUE;
+
+ if(!strcmp (context->type, "system"))
+ type = DBUS_BUS_SYSTEM;
+ else if(!strcmp (context->type, "session"))
+ type = DBUS_BUS_SESSION;
+ else
+ type = DBUS_BUS_STARTER;
+
+ bus_address = make_kdbus_bus(type, error);
+ if(bus_address == NULL)
+ goto failed;
+
+ server = empty_server_init(bus_address);
+ if(server == NULL)
+ {
+ free(bus_address);
+ goto failed;
+ }
+
+ if (!_dbus_list_append (&context->servers, server))
+ {
+ free(bus_address);
+ goto oom;
+ }
+
+ context->myConnection = daemon_as_client(type, bus_address, error);
+ if(context->myConnection == NULL)
+ goto failed;
+ }
+ else
+ {
+ DBusServer *server;
+
+ server = dbus_server_listen (_dbus_string_get_const_data(address), error);
+ if (server == NULL)
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ goto failed;
+ }
+ else if (!setup_server (context, server, auth_mechanisms, error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ goto failed;
+ }
+
+ if (!_dbus_list_append (&context->servers, server))
+ goto oom;
+ }
}
else
{
DBusString full_address;
DBusList *link;
DBusList **dirs;
- BusActivation *new_activation;
char *addr;
const char *servicehelper;
char *s;
return FALSE;
}
+static void
+raise_file_descriptor_limit (BusContext *context)
+{
+
+ /* I just picked this out of thin air; we need some extra
+ * descriptors for things like any internal pipes we create,
+ * inotify, connections to SELinux, etc.
+ */
+ unsigned int arbitrary_extra_fds = 32;
+ unsigned int limit;
+
+ limit = context->limits.max_completed_connections +
+ context->limits.max_incomplete_connections
+ + arbitrary_extra_fds;
+
+ _dbus_request_file_descriptor_limit (limit);
+}
+
static dbus_bool_t
process_config_postinit (BusContext *context,
BusConfigParser *parser,
DBusHashTable *service_context_table;
DBusList *watched_dirs = NULL;
+ raise_file_descriptor_limit (context);
+
service_context_table = bus_config_parser_steal_service_context_table (parser);
if (!bus_registry_set_service_context_table (context->registry,
service_context_table))
BusContext*
bus_context_new (const DBusString *config_file,
- ForceForkSetting force_fork,
+ BusContextFlags flags,
DBusPipe *print_addr_pipe,
DBusPipe *print_pid_pipe,
const DBusString *address,
- dbus_bool_t systemd_activation,
DBusError *error)
{
- DBusString log_prefix;
BusContext *context;
BusConfigParser *parser;
+ _dbus_assert ((flags & BUS_CONTEXT_FLAG_FORK_NEVER) == 0 ||
+ (flags & BUS_CONTEXT_FLAG_FORK_ALWAYS) == 0);
+
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
context = NULL;
goto failed;
}
- if (!process_config_first_time_only (context, parser, address, systemd_activation, error))
+ if (!process_config_first_time_only (context, parser, address, flags, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
goto failed;
if (context->pidfile)
_dbus_string_init_const (&u, context->pidfile);
- if ((force_fork != FORK_NEVER && context->fork) || force_fork == FORK_ALWAYS)
+ if (((flags & BUS_CONTEXT_FLAG_FORK_NEVER) == 0 && context->fork) ||
+ (flags & BUS_CONTEXT_FLAG_FORK_ALWAYS))
{
_dbus_verbose ("Forking and becoming daemon\n");
dbus_server_free_data_slot (&server_data_slot);
+ if(context->myConnection)
+ {
+ DBusString unique_name;
+
+ bus_connections_setup_connection(context->connections, context->myConnection);
+ _dbus_string_init_const(&unique_name, ":1.1");
+ if(!bus_connection_complete(context->myConnection, &unique_name, error))
+ {
+ _dbus_verbose ("bus connection complete failed\n");
+ }
+ }
+
return context;
failed:
return context->loop;
}
+DBusConnection* bus_context_get_myConnection(BusContext *context)
+{
+ return context->myConnection;
+}
+
dbus_bool_t
bus_context_allow_unix_user (BusContext *context,
unsigned long uid)
va_list args;
if (!context->syslog)
- return;
+ {
+ /* we're not syslogging; just output to stderr */
+ va_start (args, msg);
+ vfprintf (stderr, msg, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+ return;
+ }
va_start (args, msg);
va_end (args);
}
+static inline const char *
+nonnull (const char *maybe_null,
+ const char *if_null)
+{
+ return (maybe_null ? maybe_null : if_null);
+}
+
+/*
+ * Log something about a message, usually that it was rejected.
+ */
+static void
+complain_about_message (BusContext *context,
+ const char *error_name,
+ const char *complaint,
+ int matched_rules,
+ DBusMessage *message,
+ DBusConnection *sender,
+ DBusConnection *proposed_recipient,
+ dbus_bool_t requested_reply,
+ dbus_bool_t log,
+ DBusError *error)
+{
+ DBusError stack_error = DBUS_ERROR_INIT;
+ const char *sender_name;
+ const char *sender_loginfo;
+ const char *proposed_recipient_loginfo;
+
+ if (error == NULL && !log)
+ return;
+
+ if (sender != NULL)
+ {
+ sender_name = bus_connection_get_name (sender);
+ sender_loginfo = bus_connection_get_loginfo (sender);
+ }
+ else
+ {
+ sender_name = "(unset)";
+ sender_loginfo = "(bus)";
+ }
+
+ if (proposed_recipient != NULL)
+ proposed_recipient_loginfo = bus_connection_get_loginfo (proposed_recipient);
+ else
+ proposed_recipient_loginfo = "bus";
+
+ dbus_set_error (&stack_error, error_name,
+ "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) "
+ "interface=\"%s\" member=\"%s\" error name=\"%s\" "
+ "requested_reply=\"%d\" destination=\"%s\" (%s)",
+ complaint,
+ matched_rules,
+ dbus_message_type_to_string (dbus_message_get_type (message)),
+ sender_name,
+ sender_loginfo,
+ nonnull (dbus_message_get_interface (message), "(unset)"),
+ nonnull (dbus_message_get_member (message), "(unset)"),
+ nonnull (dbus_message_get_error_name (message), "(unset)"),
+ requested_reply,
+ nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS),
+ proposed_recipient_loginfo);
+
+ /* If we hit OOM while setting the error, this will syslog "out of memory"
+ * which is itself an indication that something is seriously wrong */
+ if (log)
+ bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY, "%s",
+ stack_error.message);
+
+ dbus_move_error (&stack_error, error);
+}
+
/*
* addressed_recipient is the recipient specified in the message.
*
dbus_bool_t log;
int type;
dbus_bool_t requested_reply;
- const char *sender_name;
- const char *sender_loginfo;
- const char *proposed_recipient_loginfo;
type = dbus_message_get_type (message);
dest = dbus_message_get_destination (message);
addressed_recipient != NULL ||
strcmp (dest, DBUS_SERVICE_DBUS) == 0);
- /* Used in logging below */
- if (sender != NULL)
- {
- sender_name = bus_connection_get_name (sender);
- sender_loginfo = bus_connection_get_loginfo (sender);
- }
- else
- {
- sender_name = NULL;
- sender_loginfo = "(bus)";
- }
-
- if (proposed_recipient != NULL)
- proposed_recipient_loginfo = bus_connection_get_loginfo (proposed_recipient);
- else
- proposed_recipient_loginfo = "bus";
-
switch (type)
{
case DBUS_MESSAGE_TYPE_METHOD_CALL:
{
if (error != NULL && !dbus_error_is_set (error))
{
- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
- "An SELinux policy prevents this sender "
- "from sending this message to this recipient "
- "(rejected message had sender \"%s\" interface \"%s\" "
- "member \"%s\" error name \"%s\" destination \"%s\")",
- sender_name ? sender_name : "(unset)",
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- dest ? dest : DBUS_SERVICE_DBUS);
+ /* don't syslog this, just set the error: avc_has_perm should
+ * have already written to either the audit log or syslog */
+ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+ "An SELinux policy prevents this sender from sending this "
+ "message to this recipient",
+ 0, message, sender, proposed_recipient, FALSE, FALSE, error);
_dbus_verbose ("SELinux security check denying send to service\n");
}
proposed_recipient,
message, &toggles, &log))
{
- const char *msg = "Rejected send message, %d matched rules; "
- "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))";
-
- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg,
- toggles,
- dbus_message_type_to_string (dbus_message_get_type (message)),
- sender_name ? sender_name : "(unset)",
- sender_loginfo,
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- requested_reply,
- dest ? dest : DBUS_SERVICE_DBUS,
- proposed_recipient_loginfo);
- /* Needs to be duplicated to avoid calling malloc and having to handle OOM */
- if (addressed_recipient == proposed_recipient)
- bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY, msg,
- toggles,
- dbus_message_type_to_string (dbus_message_get_type (message)),
- sender_name ? sender_name : "(unset)",
- sender_loginfo,
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- requested_reply,
- dest ? dest : DBUS_SERVICE_DBUS,
- proposed_recipient_loginfo);
+ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+ "Rejected send message", toggles,
+ message, sender, proposed_recipient, requested_reply,
+ (addressed_recipient == proposed_recipient), error);
_dbus_verbose ("security policy disallowing message due to sender policy\n");
return FALSE;
}
if (log)
- bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY,
- "Would reject message, %d matched rules; "
- "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))",
- toggles,
- dbus_message_type_to_string (dbus_message_get_type (message)),
- sender_name ? sender_name : "(unset)",
- sender_loginfo,
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- requested_reply,
- dest ? dest : DBUS_SERVICE_DBUS,
- proposed_recipient_loginfo);
+ {
+ /* We want to drop this message, and are only not doing so for backwards
+ * compatibility. */
+ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+ "Would reject message", toggles,
+ message, sender, proposed_recipient, requested_reply,
+ TRUE, NULL);
+ }
if (recipient_policy &&
!bus_client_policy_check_can_receive (recipient_policy,
addressed_recipient, proposed_recipient,
message, &toggles))
{
- const char *msg = "Rejected receive message, %d matched rules; "
- "type=\"%s\" sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" reply serial=%u requested_reply=%d destination=\"%s\" (%s))";
-
- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, msg,
- toggles,
- dbus_message_type_to_string (dbus_message_get_type (message)),
- sender_name ? sender_name : "(unset)",
- sender_loginfo,
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- dbus_message_get_reply_serial (message),
- requested_reply,
- dest ? dest : DBUS_SERVICE_DBUS,
- proposed_recipient_loginfo);
- /* Needs to be duplicated to avoid calling malloc and having to handle OOM */
- if (addressed_recipient == proposed_recipient)
- bus_context_log (context, DBUS_SYSTEM_LOG_SECURITY, msg,
- toggles,
- dbus_message_type_to_string (dbus_message_get_type (message)),
- sender_name ? sender_name : "(unset)",
- sender_loginfo,
- dbus_message_get_interface (message) ?
- dbus_message_get_interface (message) : "(unset)",
- dbus_message_get_member (message) ?
- dbus_message_get_member (message) : "(unset)",
- dbus_message_get_error_name (message) ?
- dbus_message_get_error_name (message) : "(unset)",
- dbus_message_get_reply_serial (message),
- requested_reply,
- dest ? dest : DBUS_SERVICE_DBUS,
- proposed_recipient_loginfo);
+ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+ "Rejected receive message", toggles,
+ message, sender, proposed_recipient, requested_reply,
+ (addressed_recipient == proposed_recipient), NULL);
_dbus_verbose ("security policy disallowing message due to recipient policy\n");
return FALSE;
}
((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) ||
(dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds)))
{
- dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
- "The destination service \"%s\" has a full message queue",
- dest ? dest : (proposed_recipient ?
- bus_connection_get_name (proposed_recipient) :
- DBUS_SERVICE_DBUS));
+ complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
+ "Rejected: destination has a full message queue",
+ 0, message, sender, proposed_recipient, requested_reply, TRUE,
+ error);
_dbus_verbose ("security policy disallowing message due to full message queue\n");
return FALSE;
}