summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-04-25 23:50:34 +0000
committerHavoc Pennington <hp@redhat.com>2003-04-25 23:50:34 +0000
commitb3bd48edfc1aab0a9dc64bfa4c380d845d218e73 (patch)
tree0ba9466c0b457769e9aa890906da532d875aac43
parent4b87aa40dfba668f8622873f2ea420b098704e41 (diff)
downloaddbus-b3bd48edfc1aab0a9dc64bfa4c380d845d218e73.tar.gz
2003-04-25 Havoc Pennington <hp@redhat.com>
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
-rw-r--r--ChangeLog21
-rw-r--r--bus/activation.c29
-rw-r--r--bus/bus.c32
-rw-r--r--bus/bus.h64
-rw-r--r--bus/config-parser.c17
-rw-r--r--bus/connection.c115
-rw-r--r--bus/connection.h5
-rw-r--r--bus/driver.c3
-rw-r--r--bus/services.c33
-rw-r--r--dbus/dbus-mainloop.c86
-rw-r--r--dbus/dbus-timeout.c2
-rw-r--r--doc/config-file.txt8
-rw-r--r--test/data/valid-config-files/basic.conf2
13 files changed, 296 insertions, 121 deletions
diff --git a/ChangeLog b/ChangeLog
index 4448c578..8ed52f0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,26 @@
2003-04-25 Havoc Pennington <hp@redhat.com>
+ 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 <hp@redhat.com>
+
* dbus/dbus-transport.c (_dbus_transport_get_unix_user): fix bug
where we used >= 0 instead of != DBUS_UID_UNSET.
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 @@
<limit name="max_completed_connections">50</limit>
<limit name="max_incomplete_connections">80</limit>
<limit name="max_connections_per_user">64</limit>
+ <limit name="max_pending_activations">64</limit>
+ <limit name="max_services_per_connection">256</limit>
</busconfig>