#include "bus.h"
#include <stdio.h>
+#include <stdlib.h>
#include "activation.h"
#include "connection.h"
#include "audit.h"
#include "dir-watch.h"
#include "check.h"
+#include <dbus/dbus-auth.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-credentials.h>
BusContext *context;
BusServerData *bd;
- if (!dbus_server_allocate_data_slot (&server_data_slot))
- return NULL;
+ /* this data slot was allocated by the BusContext */
+ _dbus_assert (server_data_slot >= 0);
bd = BUS_SERVER_DATA (server);
- if (bd == NULL)
- {
- dbus_server_free_data_slot (&server_data_slot);
- return NULL;
- }
- context = bd->context;
+ /* every DBusServer in the dbus-daemon has gone through setup_server() */
+ _dbus_assert (bd != NULL);
- dbus_server_free_data_slot (&server_data_slot);
+ context = bd->context;
return context;
}
{
BusContext *context = data;
+ /* If this fails it logs a warning, so we don't need to do that */
if (!bus_connections_setup_connection (context->connections, new_connection))
{
- _dbus_verbose ("No memory to setup new connection\n");
-
/* if we don't do this, it will get unref'd without
* being disconnected... kind of strange really
* that we have to do this, people won't get it right
DBusList **auth_mechanisms_list;
int len;
dbus_bool_t retval;
+ DBusLogFlags log_flags = DBUS_LOG_FLAGS_STDERR;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
auth_mechanisms = NULL;
pidfile = NULL;
- _dbus_init_system_log (TRUE);
+ if (flags & BUS_CONTEXT_FLAG_SYSLOG_ALWAYS)
+ {
+ context->syslog = TRUE;
+ log_flags |= DBUS_LOG_FLAGS_SYSTEM_LOG;
+
+ if (flags & BUS_CONTEXT_FLAG_SYSLOG_ONLY)
+ log_flags &= ~DBUS_LOG_FLAGS_STDERR;
+ }
+ else if (flags & BUS_CONTEXT_FLAG_SYSLOG_NEVER)
+ {
+ context->syslog = FALSE;
+ }
+ else
+ {
+ context->syslog = bus_config_parser_get_syslog (parser);
+
+ if (context->syslog)
+ log_flags |= DBUS_LOG_FLAGS_SYSTEM_LOG;
+ }
+
+ _dbus_init_system_log ("dbus-daemon", log_flags);
if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION)
context->systemd_activation = TRUE;
link = _dbus_list_get_first_link (auth_mechanisms_list);
while (link != NULL)
{
+ DBusString name;
+ _dbus_string_init_const (&name, link->data);
+ if (!_dbus_auth_is_supported_mechanism (&name))
+ {
+ DBusString list;
+ if (!_dbus_string_init (&list))
+ goto oom;
+
+ if (!_dbus_auth_dump_supported_mechanisms (&list))
+ {
+ _dbus_string_free (&list);
+ goto oom;
+ }
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Unsupported auth mechanism \"%s\" in bus config file detected. Supported mechanisms are \"%s\".",
+ (char*)link->data,
+ _dbus_string_get_const_data (&list));
+ _dbus_string_free (&list);
+ goto failed;
+ }
auth_mechanisms[i] = _dbus_strdup (link->data);
if (auth_mechanisms[i] == NULL)
goto oom;
}
context->fork = bus_config_parser_get_fork (parser);
- context->syslog = bus_config_parser_get_syslog (parser);
context->keep_umask = bus_config_parser_get_keep_umask (parser);
context->allow_anonymous = bus_config_parser_get_allow_anonymous (parser);
return retval;
}
-static dbus_bool_t
-list_concat_new (DBusList **a,
- DBusList **b,
- DBusList **result)
-{
- DBusList *link;
-
- *result = NULL;
-
- for (link = _dbus_list_get_first_link (a); link; link = _dbus_list_get_next_link (a, link))
- {
- if (!_dbus_list_append (result, link->data))
- goto oom;
- }
- for (link = _dbus_list_get_first_link (b); link; link = _dbus_list_get_next_link (b, link))
- {
- if (!_dbus_list_append (result, link->data))
- goto oom;
- }
-
- return TRUE;
-oom:
- _dbus_list_clear (result);
- return FALSE;
-}
-
static void
raise_file_descriptor_limit (BusContext *context)
{
/* We used to compute a suitable rlimit based on the configured number
* of connections, but that breaks down as soon as we allow fd-passing,
* because each connection is allowed to pass 64 fds to us, and if
- * they all did, we'd hit kernel limits. We now hard-code 64k as a
- * good limit, like systemd does: that's enough to avoid DoS from
- * anything short of multiple uids conspiring against us.
+ * they all did, we'd hit kernel limits. We now hard-code a good
+ * limit that is enough to avoid DoS from anything short of multiple
+ * uids conspiring against us, much like systemd does.
*/
- if (!_dbus_rlimit_raise_fd_limit_if_privileged (65536, &error))
+ if (!_dbus_rlimit_raise_fd_limit (&error))
{
bus_context_log (context, DBUS_SYSTEM_LOG_WARNING,
"%s: %s", error.name, error.message);
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))
/* We need to monitor both the configuration directories and directories
* containing .service files.
*/
- if (!list_concat_new (bus_config_parser_get_conf_dirs (parser),
- bus_config_parser_get_service_dirs (parser),
- &watched_dirs))
+ if (!bus_config_parser_get_watched_dirs (parser, &watched_dirs))
{
BUS_SET_OOM (error);
return FALSE;
!_dbus_pipe_is_stdout_or_stderr (print_pid_pipe))
_dbus_pipe_close (print_pid_pipe, NULL);
+ /* Raise the file descriptor limits before dropping the privileges
+ * required to do so.
+ */
+ raise_file_descriptor_limit (context);
+
+ /* Here we change our credentials if required,
+ * as soon as we've set up our sockets and pidfile.
+ * This must be done before initializing LSMs, so that the netlink
+ * monitoring thread started by avc_init() will not lose CAP_AUDIT_WRITE
+ * when the main thread calls setuid().
+ * https://bugs.freedesktop.org/show_bug.cgi?id=92832
+ */
+ if (context->user != NULL)
+ {
+ if (!_dbus_change_to_daemon_user (context->user, error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ goto failed;
+ }
+ }
+
+ /* Auditing should be initialized before LSMs, so that the LSMs are able
+ * to log audit-events that happen during their initialization.
+ */
+ bus_audit_init (context);
+
if (!bus_selinux_full_init ())
{
- bus_context_log (context, DBUS_SYSTEM_LOG_FATAL, "SELinux enabled but D-Bus initialization failed; check system log\n");
+ bus_context_log (context, DBUS_SYSTEM_LOG_ERROR,
+ "SELinux enabled but D-Bus initialization failed; "
+ "check system log");
+ exit (1);
}
if (!bus_apparmor_full_init (error))
"AppArmor D-Bus mediation is enabled\n");
}
+ /* When SELinux is used, this must happen after bus_selinux_full_init()
+ * so that it has access to the access vector cache, which is required
+ * to process <associate/> elements.
+ * http://lists.freedesktop.org/archives/dbus/2008-October/010491.html
+ */
if (!process_config_postinit (context, parser, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
parser = NULL;
}
- /* Here we change our credentials if required,
- * as soon as we've set up our sockets and pidfile
- */
- if (context->user != NULL)
- {
- if (!_dbus_change_to_daemon_user (context->user, error))
- {
- _DBUS_ASSERT_ERROR_IS_SET (error);
- goto failed;
- }
- }
-
- bus_audit_init (context);
-
context->check = bus_check_new(context, error);
if (context->check == NULL)
goto failed;
return context->initial_fd_limit;
}
+dbus_bool_t
+bus_context_get_using_syslog (BusContext *context)
+{
+ return context->syslog;
+}
+
void
bus_context_log (BusContext *context, DBusSystemLogSeverity severity, const char *msg, ...)
{
va_list args;
- if (!context->syslog)
- {
- /* we're not syslogging; just output to stderr */
- va_start (args, msg);
- vfprintf (stderr, msg, args);
- fprintf (stderr, "\n");
- va_end (args);
-
- if (severity == DBUS_SYSTEM_LOG_FATAL)
- _dbus_exit (1);
-
- return;
- }
-
va_start (args, msg);
if (context->log_prefix)
if (!_dbus_string_append_printf_valist (&full_msg, msg, args))
goto oom_out;
- _dbus_system_log (severity, "%s", _dbus_string_get_const_data (&full_msg));
+ _dbus_log (severity, "%s", _dbus_string_get_const_data (&full_msg));
oom_out:
_dbus_string_free (&full_msg);
}
else
- _dbus_system_logv (severity, msg, args);
+ _dbus_logv (severity, msg, args);
out:
va_end (args);
DBusSystemLogSeverity severity,
const char *msg)
{
- if (!context->syslog)
- {
- fputs (msg, stderr);
- fputc ('\n', stderr);
-
- if (severity == DBUS_SYSTEM_LOG_FATAL)
- _dbus_exit (1);
- }
- else
- {
- _dbus_system_log (severity, "%s%s", nonnull (context->log_prefix, ""),
- msg);
- }
+ _dbus_log (severity, "%s%s", nonnull (context->log_prefix, ""), msg);
}
void
dbus_bool_t requested_reply;
const char *privilege;
char *out_rule = NULL;
+ BusResult can_send_result = BUS_RESULT_TRUE;
type = dbus_message_get_type (message);
src = dbus_message_get_sender (message);
}
else
{
- _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus\n");
+ _dbus_assert_not_reached ("a message was somehow sent to an inactive recipient from a source other than the message bus");
recipient_policy = NULL;
}
}
log = FALSE;
if (sender_policy) {
- switch (bus_client_policy_check_can_send (sender,
- sender_policy,
- context->registry,
- requested_reply,
- addressed_recipient,
- proposed_recipient,
- message, &toggles, &log, &privilege,
- deferred_message, &out_rule))
+ can_send_result = bus_client_policy_check_can_send (sender,
+ sender_policy,
+ context->registry,
+ requested_reply,
+ addressed_recipient,
+ proposed_recipient,
+ message, &toggles, &log, &privilege,
+ deferred_message, &out_rule);
+ if (can_send_result == BUS_RESULT_FALSE)
{
- case BUS_RESULT_TRUE:
- break;
- case BUS_RESULT_FALSE:
complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
"Rejected send message", toggles,
message, sender, proposed_recipient, requested_reply,
- (addressed_recipient == proposed_recipient), privilege,
+ (addressed_recipient == proposed_recipient) || (type == DBUS_MESSAGE_TYPE_SIGNAL),
+ privilege,
error, out_rule);
_dbus_verbose ("security policy disallowing message due to sender policy\n");
if (out_rule)
free (out_rule);
return BUS_RESULT_FALSE;
- break;
- case BUS_RESULT_LATER:
- return BUS_RESULT_LATER;
- break;
}
}
complain_about_message(context, DBUS_ERROR_ACCESS_DENIED,
"Rejected receive message", toggles, message, sender,
proposed_recipient, requested_reply,
- (addressed_recipient == proposed_recipient), privilege, error, out_rule);
+ (addressed_recipient == proposed_recipient) || (type == DBUS_MESSAGE_TYPE_SIGNAL),
+ privilege, error, out_rule);
_dbus_verbose(
"security policy disallowing message due to recipient policy\n");
if (out_rule)
free (out_rule);
+ if (deferred_message && *deferred_message)
+ bus_deferred_message_set_response (*deferred_message, BUS_RESULT_FALSE);
return BUS_RESULT_FALSE;
case BUS_RESULT_LATER:
return BUS_RESULT_LATER;
}
}
+ if (can_send_result == BUS_RESULT_LATER)
+ return BUS_RESULT_LATER;
+
/* See if limits on size have been exceeded */
if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message,
requested_reply, error))