From b3bd48edfc1aab0a9dc64bfa4c380d845d218e73 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 25 Apr 2003 23:50:34 +0000 Subject: 2003-04-25 Havoc Pennington test suite is slightly hosed at the moment, will fix soon * bus/connection.c (bus_connections_expire_incomplete): fix to properly disable the timeout when required (bus_connection_set_name): check whether we can remove incomplete connections timeout after we complete each connection. * dbus/dbus-mainloop.c (check_timeout): fix this up a bit, probably still broken. * bus/services.c (bus_registry_acquire_service): implement max number of services owned, and honor allow/deny rules on which services a connection can own. * bus/connection.c (bus_connection_get_policy): report errors here * bus/activation.c: implement limit on number of pending activations --- ChangeLog | 21 ++++++ bus/activation.c | 29 +++++++- bus/bus.c | 32 +++++++-- bus/bus.h | 64 +++++++++--------- bus/config-parser.c | 17 ++++- bus/connection.c | 115 +++++++++++++++++++++----------- bus/connection.h | 5 +- bus/driver.c | 3 +- bus/services.c | 33 +++++++++ dbus/dbus-mainloop.c | 86 +++++++++++++----------- dbus/dbus-timeout.c | 2 + doc/config-file.txt | 8 ++- test/data/valid-config-files/basic.conf | 2 + 13 files changed, 296 insertions(+), 121 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4448c578..8ed52f0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2003-04-25 Havoc Pennington + + test suite is slightly hosed at the moment, will fix soon + + * bus/connection.c (bus_connections_expire_incomplete): fix to + properly disable the timeout when required + (bus_connection_set_name): check whether we can remove incomplete + connections timeout after we complete each connection. + + * dbus/dbus-mainloop.c (check_timeout): fix this up a bit, + probably still broken. + + * bus/services.c (bus_registry_acquire_service): implement max + number of services owned, and honor allow/deny rules on which + services a connection can own. + + * bus/connection.c (bus_connection_get_policy): report errors here + + * bus/activation.c: implement limit on number of pending + activations + 2003-04-25 Havoc Pennington * dbus/dbus-transport.c (_dbus_transport_get_unix_user): fix bug diff --git a/bus/activation.c b/bus/activation.c index a569e1a1..c50f1f28 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -45,6 +45,10 @@ struct BusActivation DBusHashTable *pending_activations; char *server_address; BusContext *context; + int n_pending_activations; /**< This is in fact the number of BusPendingActivationEntry, + * i.e. number of pending activation requests, not pending + * activations per se + */ }; typedef struct @@ -67,6 +71,7 @@ typedef struct BusActivation *activation; char *service_name; DBusList *entries; + int n_entries; DBusBabysitter *babysitter; DBusTimeout *timeout; unsigned int timeout_added : 1; @@ -150,6 +155,11 @@ bus_pending_activation_unref (BusPendingActivation *pending_activation) link = _dbus_list_get_next_link (&pending_activation->entries, link); } _dbus_list_clear (&pending_activation->entries); + + pending_activation->activation->n_pending_activations -= + pending_activation->n_entries; + + _dbus_assert (pending_activation->activation->n_pending_activations >= 0); dbus_free (pending_activation); } @@ -394,6 +404,7 @@ bus_activation_new (BusContext *context, activation->refcount = 1; activation->context = context; + activation->n_pending_activations = 0; if (!_dbus_string_copy_data (address, &activation->server_address)) { @@ -838,6 +849,15 @@ bus_activation_activate_service (BusActivation *activation, dbus_bool_t retval; _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + if (activation->n_pending_activations >= + bus_context_get_max_pending_activations (activation->context)) + { + dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, + "The maximum number of pending activations has been reached, activation of %s failed", + service_name); + return FALSE; + } entry = _dbus_hash_table_lookup_string (activation->entries, service_name); @@ -902,9 +922,6 @@ bus_activation_activate_service (BusActivation *activation, pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name); if (pending_activation) { - /* FIXME security - a client could keep sending activations over and - * over, growing this queue. - */ if (!_dbus_list_append (&pending_activation->entries, pending_activation_entry)) { _dbus_verbose ("Failed to append a new entry to pending activation\n"); @@ -913,6 +930,9 @@ bus_activation_activate_service (BusActivation *activation, bus_pending_activation_entry_free (pending_activation_entry); return FALSE; } + + pending_activation->n_entries += 1; + pending_activation->activation->n_pending_activations += 1; } else { @@ -980,6 +1000,9 @@ bus_activation_activate_service (BusActivation *activation, bus_pending_activation_entry_free (pending_activation_entry); return FALSE; } + + pending_activation->n_entries += 1; + pending_activation->activation->n_pending_activations += 1; if (!_dbus_hash_table_insert_string (activation->pending_activations, pending_activation->service_name, diff --git a/bus/bus.c b/bus/bus.c index 7bb4bf99..dc0cb560 100644 --- a/bus/bus.c +++ b/bus/bus.c @@ -825,6 +825,18 @@ bus_context_get_max_connections_per_user (BusContext *context) return context->limits.max_connections_per_user; } +int +bus_context_get_max_pending_activations (BusContext *context) +{ + return context->limits.max_pending_activations; +} + +int +bus_context_get_max_services_per_connection (BusContext *context) +{ + return context->limits.max_services_per_connection; +} + dbus_bool_t bus_context_check_security_policy (BusContext *context, DBusConnection *sender, @@ -840,7 +852,13 @@ bus_context_check_security_policy (BusContext *context, if (sender != NULL) { _dbus_assert (dbus_connection_get_is_authenticated (sender)); - sender_policy = bus_connection_get_policy (sender); + sender_policy = bus_connection_get_policy (sender, error); + if (sender_policy == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return FALSE; + } + return FALSE; } else sender_policy = NULL; @@ -848,12 +866,18 @@ bus_context_check_security_policy (BusContext *context, if (recipient != NULL) { _dbus_assert (dbus_connection_get_is_authenticated (recipient)); - recipient_policy = bus_connection_get_policy (recipient); + recipient_policy = bus_connection_get_policy (recipient, error); + if (recipient_policy == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + return FALSE; + } + return FALSE; } else recipient_policy = NULL; - if (sender_policy && + if (sender && !bus_client_policy_check_can_send (sender_policy, context->registry, recipient, message)) @@ -869,7 +893,7 @@ bus_context_check_security_policy (BusContext *context, return FALSE; } - if (recipient_policy && + if (recipient && !bus_client_policy_check_can_receive (recipient_policy, context->registry, sender, message)) diff --git a/bus/bus.h b/bus/bus.h index 7cffb33a..8431ca23 100644 --- a/bus/bus.h +++ b/bus/bus.h @@ -44,44 +44,46 @@ typedef struct BusTransaction BusTransaction; typedef struct { - long max_incoming_bytes; /**< How many incoming messages for a connection */ - long max_outgoing_bytes; /**< How many outgoing bytes can be queued for a connection */ + long max_incoming_bytes; /**< How many incoming messages for a single connection */ + long max_outgoing_bytes; /**< How many outgoing bytes can be queued for a single connection */ long max_message_size; /**< Max size of a single message in bytes */ int activation_timeout; /**< How long to wait for an activation to time out */ int auth_timeout; /**< How long to wait for an authentication to time out */ int max_completed_connections; /**< Max number of authorized connections */ int max_incomplete_connections; /**< Max number of incomplete connections */ int max_connections_per_user; /**< Max number of connections auth'd as same user */ + int max_pending_activations; /**< Max number of pending activations for the entire bus */ + int max_services_per_connection; /**< Max number of owned services for a single connection */ } BusLimits; -BusContext* bus_context_new (const DBusString *config_file, - int print_addr_fd, - DBusError *error); -void bus_context_shutdown (BusContext *context); -void bus_context_ref (BusContext *context); -void bus_context_unref (BusContext *context); -const char* bus_context_get_type (BusContext *context); -const char* bus_context_get_address (BusContext *context); -BusRegistry* bus_context_get_registry (BusContext *context); -BusConnections* bus_context_get_connections (BusContext *context); -BusActivation* bus_context_get_activation (BusContext *context); -DBusLoop* bus_context_get_loop (BusContext *context); -DBusUserDatabase* bus_context_get_user_database (BusContext *context); -dbus_bool_t bus_context_allow_user (BusContext *context, - unsigned long uid); -BusClientPolicy* bus_context_create_client_policy (BusContext *context, - DBusConnection *connection); -int bus_context_get_activation_timeout (BusContext *context); -int bus_context_get_auth_timeout (BusContext *context); -int bus_context_get_max_completed_connections (BusContext *context); -int bus_context_get_max_incomplete_connections (BusContext *context); -int bus_context_get_max_connections_per_user (BusContext *context); -dbus_bool_t bus_context_check_security_policy (BusContext *context, - DBusConnection *sender, - DBusConnection *recipient, - DBusMessage *message, - DBusError *error); - - +BusContext* bus_context_new (const DBusString *config_file, + int print_addr_fd, + DBusError *error); +void bus_context_shutdown (BusContext *context); +void bus_context_ref (BusContext *context); +void bus_context_unref (BusContext *context); +const char* bus_context_get_type (BusContext *context); +const char* bus_context_get_address (BusContext *context); +BusRegistry* bus_context_get_registry (BusContext *context); +BusConnections* bus_context_get_connections (BusContext *context); +BusActivation* bus_context_get_activation (BusContext *context); +DBusLoop* bus_context_get_loop (BusContext *context); +DBusUserDatabase* bus_context_get_user_database (BusContext *context); +dbus_bool_t bus_context_allow_user (BusContext *context, + unsigned long uid); +BusClientPolicy* bus_context_create_client_policy (BusContext *context, + DBusConnection *connection); +int bus_context_get_activation_timeout (BusContext *context); +int bus_context_get_auth_timeout (BusContext *context); +int bus_context_get_max_completed_connections (BusContext *context); +int bus_context_get_max_incomplete_connections (BusContext *context); +int bus_context_get_max_connections_per_user (BusContext *context); +int bus_context_get_max_pending_activations (BusContext *context); +int bus_context_get_max_services_per_connection (BusContext *context); +dbus_bool_t bus_context_check_security_policy (BusContext *context, + DBusConnection *sender, + DBusConnection *recipient, + DBusMessage *message, + DBusError *error); #endif /* BUS_BUS_H */ diff --git a/bus/config-parser.c b/bus/config-parser.c index bd1c47b8..5e279639 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -306,7 +306,7 @@ bus_config_parser_new (const DBusString *basedir) * and legitimate auth will fail. If interactive auth (ask user for * password) is allowed, then potentially it has to be quite long. */ - parser->limits.auth_timeout = 3000; /* 3 seconds */ + parser->limits.auth_timeout = 30000; /* 30 seconds */ parser->limits.max_incomplete_connections = 32; parser->limits.max_connections_per_user = 128; @@ -316,6 +316,9 @@ bus_config_parser_new (const DBusString *basedir) * DOS all the other users. */ parser->limits.max_completed_connections = 1024; + + parser->limits.max_pending_activations = 256; + parser->limits.max_services_per_connection = 256; parser->refcount = 1; @@ -1215,6 +1218,18 @@ set_limit (BusConfigParser *parser, must_be_int = TRUE; parser->limits.max_connections_per_user = value; } + else if (strcmp (name, "max_pending_activations") == 0) + { + must_be_positive = TRUE; + must_be_int = TRUE; + parser->limits.max_pending_activations = value; + } + else if (strcmp (name, "max_services_per_connection") == 0) + { + must_be_positive = TRUE; + must_be_int = TRUE; + parser->limits.max_services_per_connection = value; + } else { dbus_set_error (error, DBUS_ERROR_FAILED, diff --git a/bus/connection.c b/bus/connection.c index 68429b2d..8907227c 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -52,6 +52,7 @@ typedef struct DBusList *link_in_connection_list; DBusConnection *connection; DBusList *services_owned; + int n_services_owned; char *name; DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */ DBusMessage *oom_message; @@ -387,6 +388,7 @@ free_connection_data (void *data) /* services_owned should be NULL since we should be disconnected */ _dbus_assert (d->services_owned == NULL); + _dbus_assert (d->n_services_owned == 0); /* similarly */ _dbus_assert (d->transaction_messages == NULL); @@ -662,52 +664,54 @@ void bus_connections_expire_incomplete (BusConnections *connections) { int next_interval; - long tv_sec, tv_usec; - DBusList *link; - int auth_timeout; - - if (connections->incomplete == NULL) - return; - _dbus_get_current_time (&tv_sec, &tv_usec); - auth_timeout = bus_context_get_auth_timeout (connections->context); next_interval = -1; - link = _dbus_list_get_first_link (&connections->incomplete); - while (link != NULL) + if (connections->incomplete != NULL) { - DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link); - DBusConnection *connection; - BusConnectionData *d; - double elapsed; + long tv_sec, tv_usec; + DBusList *link; + int auth_timeout; - connection = link->data; + _dbus_get_current_time (&tv_sec, &tv_usec); + auth_timeout = bus_context_get_auth_timeout (connections->context); + + link = _dbus_list_get_first_link (&connections->incomplete); + while (link != NULL) + { + DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link); + DBusConnection *connection; + BusConnectionData *d; + double elapsed; - d = BUS_CONNECTION_DATA (connection); + connection = link->data; - _dbus_assert (d != NULL); + d = BUS_CONNECTION_DATA (connection); - elapsed = ((double) tv_sec - (double) d->connection_tv_sec) * 1000.0 + - ((double) tv_usec - (double) d->connection_tv_usec) / 1000.0; + _dbus_assert (d != NULL); + + elapsed = ((double) tv_sec - (double) d->connection_tv_sec) * 1000.0 + + ((double) tv_usec - (double) d->connection_tv_usec) / 1000.0; - if (elapsed > (double) auth_timeout) - { - _dbus_verbose ("Timing out authentication for connection %p\n", connection); - dbus_connection_disconnect (connection); - } - else - { - /* We can end the loop, since the connections are in oldest-first order */ - next_interval = auth_timeout - (int) elapsed; - _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n", - connection, next_interval); + if (elapsed >= (double) auth_timeout) + { + _dbus_verbose ("Timing out authentication for connection %p\n", connection); + dbus_connection_disconnect (connection); + } + else + { + /* We can end the loop, since the connections are in oldest-first order */ + next_interval = ((double)auth_timeout) - elapsed; + _dbus_verbose ("Connection %p authentication expires in %d milliseconds\n", + connection, next_interval); - break; - } + break; + } - link = next; + link = next; + } } - + if (next_interval >= 0) { _dbus_timeout_set_interval (connections->expire_timeout, @@ -717,13 +721,15 @@ bus_connections_expire_incomplete (BusConnections *connections) _dbus_verbose ("Enabled incomplete connections timeout with interval %d, %d incomplete connections\n", next_interval, connections->n_incomplete); } - else + else if (dbus_timeout_get_enabled (connections->expire_timeout)) { _dbus_timeout_set_enabled (connections->expire_timeout, FALSE); _dbus_verbose ("Disabled incomplete connections timeout, %d incomplete connections\n", connections->n_incomplete); } + else + _dbus_verbose ("No need to disable incomplete connections timeout\n"); } static dbus_bool_t @@ -731,6 +737,8 @@ expire_incomplete_timeout (void *data) { BusConnections *connections = data; + _dbus_verbose ("Running %s\n", _DBUS_FUNCTION_NAME); + /* note that this may remove the timeout */ bus_connections_expire_incomplete (connections); @@ -803,7 +811,8 @@ bus_connection_is_in_group (DBusConnection *connection, } BusClientPolicy* -bus_connection_get_policy (DBusConnection *connection) +bus_connection_get_policy (DBusConnection *connection, + DBusError *error) { BusConnectionData *d; @@ -814,6 +823,9 @@ bus_connection_get_policy (DBusConnection *connection) if (!dbus_connection_get_is_authenticated (connection)) { _dbus_verbose ("Tried to get policy for unauthenticated connection!\n"); + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Connection is not yet authenticated; the pre-authentication " + "implicit security policy is to deny everything"); return NULL; } @@ -828,11 +840,19 @@ bus_connection_get_policy (DBusConnection *connection) /* we may have a NULL policy on OOM or error getting list of * groups for a user. In the latter case we don't handle it so - * well currently, just keep pretending we're out of memory, - * which is kind of bizarre. + * well currently, as it will just keep failing over and over. */ } + if (d->policy == NULL) + { + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "There was an error creating the security policy for connection \"%s\"; " + "all operations will fail for now.", + d->name ? d->name : "(inactive)"); + return NULL; + } + return d->policy; } @@ -1075,6 +1095,8 @@ bus_connection_add_owned_service_link (DBusConnection *connection, _dbus_assert (d != NULL); _dbus_list_append_link (&d->services_owned, link); + + d->n_services_owned += 1; } dbus_bool_t @@ -1103,6 +1125,20 @@ bus_connection_remove_owned_service (DBusConnection *connection, _dbus_assert (d != NULL); _dbus_list_remove_last (&d->services_owned, service); + + d->n_services_owned -= 1; + _dbus_assert (d->n_services_owned >= 0); +} + +int +bus_connection_get_n_services_owned (DBusConnection *connection) +{ + BusConnectionData *d; + + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); + + return d->n_services_owned; } dbus_bool_t @@ -1144,6 +1180,9 @@ bus_connection_set_name (DBusConnection *connection, _dbus_assert (d->connections->n_incomplete >= 0); _dbus_assert (d->connections->n_completed > 0); + + /* See if we can remove the timeout */ + bus_connections_expire_incomplete (d->connections); return TRUE; } diff --git a/bus/connection.h b/bus/connection.h index fe5a3769..ebfe2ad2 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -68,7 +68,7 @@ void bus_connection_remove_owned_service (DBusConnection *connection, BusService *service); void bus_connection_add_owned_service_link (DBusConnection *connection, DBusList *link); - +int bus_connection_get_n_services_owned (DBusConnection *connection); /* called by driver.c */ dbus_bool_t bus_connection_set_name (DBusConnection *connection, @@ -83,7 +83,8 @@ dbus_bool_t bus_connection_is_in_group (DBusConnection *connection, dbus_bool_t bus_connection_get_groups (DBusConnection *connection, unsigned long **groups, int *n_groups); -BusClientPolicy* bus_connection_get_policy (DBusConnection *connection); +BusClientPolicy* bus_connection_get_policy (DBusConnection *connection, + DBusError *error); /* transaction API so we can send or not send a block of messages as a whole */ diff --git a/bus/driver.c b/bus/driver.c index 299968f4..9839ff03 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -204,10 +204,11 @@ create_unique_client_name (BusRegistry *registry, * for INT_MAX * INT_MAX combinations, should be pretty safe against * wraparound. */ + /* FIXME these should be in BusRegistry rather than static vars */ static int next_major_number = 0; static int next_minor_number = 0; int len; - + len = _dbus_string_get_length (str); while (TRUE) diff --git a/bus/services.c b/bus/services.c index dfc3ed08..fc749d0d 100644 --- a/bus/services.c +++ b/bus/services.c @@ -30,6 +30,7 @@ #include "connection.h" #include "utils.h" #include "activation.h" +#include "policy.h" struct BusService { @@ -257,6 +258,7 @@ bus_registry_acquire_service (BusRegistry *registry, dbus_bool_t retval; DBusConnection *old_owner; DBusConnection *current_owner; + BusClientPolicy *policy; BusService *service; retval = FALSE; @@ -283,6 +285,37 @@ bus_registry_acquire_service (BusRegistry *registry, goto out; } + + policy = bus_connection_get_policy (connection, error); + if (policy == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto out; + } + + if (!bus_client_policy_check_can_own (policy, connection, + service_name)) + { + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Connection \"%s\" is not allowed to own the service \"%s\" due " + "to security policies in the configuration file", + bus_connection_is_active (connection) ? + bus_connection_get_name (connection) : + "(inactive)"); + goto out; + } + + if (bus_connection_get_n_services_owned (connection) >= + bus_context_get_max_services_per_connection (registry->context)) + { + dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, + "Connection \"%s\" is not allowed to own more services " + "(increase limits in configuration file if required)", + bus_connection_is_active (connection) ? + bus_connection_get_name (connection) : + "(inactive)"); + goto out; + } service = bus_registry_lookup (registry, service_name); diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c index 1d1af78c..60191882 100644 --- a/dbus/dbus-mainloop.c +++ b/dbus/dbus-mainloop.c @@ -356,10 +356,12 @@ check_timeout (unsigned long tv_sec, long interval_milliseconds; int interval; + /* I'm pretty sure this function could suck (a lot) less */ + interval = dbus_timeout_get_interval (tcb->timeout); - interval_seconds = interval / 1000; - interval_milliseconds = interval - interval_seconds * 1000; + interval_seconds = interval / 1000L; + interval_milliseconds = interval % 1000L; expiration_tv_sec = tcb->last_tv_sec + interval_seconds; expiration_tv_usec = tcb->last_tv_usec + interval_milliseconds * 1000; @@ -368,44 +370,35 @@ check_timeout (unsigned long tv_sec, expiration_tv_usec -= 1000000; expiration_tv_sec += 1; } - - if (expiration_tv_sec < tv_sec || - (expiration_tv_sec == tv_sec && expiration_tv_usec < tv_usec)) - { - _dbus_verbose ("System clock went backward interval_seconds %ld interval_msecs %ld last_tv_sec %lu last_tv_usec %lu tv_sec %lu tv_usec %lu\n", - interval_seconds, interval_milliseconds, - tcb->last_tv_sec, tcb->last_tv_usec, tv_sec, tv_usec); - - /* The system time has been set backwards, reset the timeout to "interval" in the future */ - - tcb->last_tv_sec = tv_sec; - tcb->last_tv_usec = tv_usec; - - *timeout = interval; - - return FALSE; - } sec_remaining = expiration_tv_sec - tv_sec; - msec_remaining = (expiration_tv_usec - tv_usec) / 1000; - -#if 0 - printf ("Interval is %ld seconds %ld msecs\n", - interval_seconds, - interval_milliseconds); - printf ("Now is %lu seconds %lu usecs\n", - tv_sec, tv_usec); - printf ("Exp is %lu seconds %lu usecs\n", - expiration_tv_sec, expiration_tv_usec); - printf ("Pre-correction, remaining sec_remaining %ld msec_remaining %ld\n", sec_remaining, msec_remaining); + /* need to force this to be signed, as it is intended to sometimes + * produce a negative result + */ + msec_remaining = ((long) expiration_tv_usec - (long) tv_usec) / 1000L; + +#if MAINLOOP_SPEW + _dbus_verbose ("Interval is %ld seconds %ld msecs\n", + interval_seconds, + interval_milliseconds); + _dbus_verbose ("Now is %lu seconds %lu usecs\n", + tv_sec, tv_usec); + _dbus_verbose ("Last is %lu seconds %lu usecs\n", + tcb->last_tv_sec, tcb->last_tv_usec); + _dbus_verbose ("Exp is %lu seconds %lu usecs\n", + expiration_tv_sec, expiration_tv_usec); + _dbus_verbose ("Pre-correction, sec_remaining %ld msec_remaining %ld\n", + sec_remaining, msec_remaining); #endif /* We do the following in a rather convoluted fashion to deal with * the fact that we don't have an integral type big enough to hold - * the difference of two timevals in millseconds. + * the difference of two timevals in milliseconds. */ if (sec_remaining < 0 || (sec_remaining == 0 && msec_remaining < 0)) - msec_remaining = 0; + { + *timeout = 0; + } else { if (msec_remaining < 0) @@ -414,20 +407,29 @@ check_timeout (unsigned long tv_sec, sec_remaining -= 1; } - if (msec_remaining > _DBUS_INT_MAX) - { - /* Not going to fit in a 32-bit integer */ - msec_remaining = _DBUS_INT_MAX; - } + if (sec_remaining > (_DBUS_INT_MAX / 1000) || + msec_remaining > _DBUS_INT_MAX) + *timeout = _DBUS_INT_MAX; + else + *timeout = sec_remaining * 1000 + msec_remaining; } - *timeout = msec_remaining; + if (*timeout > interval) + { + /* This indicates that the system clock probably moved backward */ + _dbus_verbose ("System clock set backward! Resetting timeout.\n"); + + tcb->last_tv_sec = tv_sec; + tcb->last_tv_usec = tv_usec; + *timeout = interval; + } + #if MAINLOOP_SPEW _dbus_verbose (" timeout expires in %d milliseconds\n", *timeout); #endif - return msec_remaining == 0; + return *timeout == 0; } dbus_bool_t @@ -708,6 +710,12 @@ _dbus_loop_iterate (DBusLoop *loop, retval = TRUE; } + else + { +#if MAINLOOP_SPEW + _dbus_verbose (" timeout has not expired\n"); +#endif + } } link = next; diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c index 74210f9a..1a2d2965 100644 --- a/dbus/dbus-timeout.c +++ b/dbus/dbus-timeout.c @@ -124,6 +124,8 @@ void _dbus_timeout_set_interval (DBusTimeout *timeout, int interval) { + _dbus_assert (interval >= 0); + timeout->interval = interval; } diff --git a/doc/config-file.txt b/doc/config-file.txt index ed3cdfab..e6e24e0f 100644 --- a/doc/config-file.txt +++ b/doc/config-file.txt @@ -135,9 +135,9 @@ Elements: Available limits are: "max_incoming_bytes" : total size in bytes of messages - incoming from a connection + incoming from a single connection "max_outgoing_bytes" : total size in bytes of messages - queued up for a connection + queued up for a single connection "max_message_size" : max size of a single message in bytes "activation_timeout" : milliseconds (thousandths) until @@ -150,6 +150,10 @@ Elements: connections "max_connections_per_user" : max number of completed connections from the same user + "max_pending_activations" : max number of activations in + progress at the same time + "max_services_per_connection": max number of services a single + connection can own Some notes: diff --git a/test/data/valid-config-files/basic.conf b/test/data/valid-config-files/basic.conf index 5addd692..4500ad70 100644 --- a/test/data/valid-config-files/basic.conf +++ b/test/data/valid-config-files/basic.conf @@ -19,5 +19,7 @@ 50 80 64 + 64 + 256 -- cgit