diff options
| -rw-r--r-- | ChangeLog | 14 | ||||
| -rw-r--r-- | bus/bus.c | 56 | ||||
| -rw-r--r-- | bus/bus.h | 51 | ||||
| -rw-r--r-- | bus/connection.c | 317 | ||||
| -rw-r--r-- | bus/connection.h | 10 | ||||
| -rw-r--r-- | bus/dispatch.c | 5 | ||||
| -rw-r--r-- | bus/driver.c | 15 | ||||
| -rw-r--r-- | dbus/dbus-connection.h | 8 | ||||
| -rw-r--r-- | dbus/dbus-list.c | 13 | ||||
| -rw-r--r-- | dbus/dbus-list.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.c | 4 | ||||
| -rw-r--r-- | doc/TODO | 12 | 
12 files changed, 428 insertions, 79 deletions
@@ -1,3 +1,17 @@ +2003-04-19  Havoc Pennington  <hp@pobox.com> + +	* bus/driver.c (bus_driver_handle_hello): check limits and  +	return an error if they are exceeded. + +	* bus/connection.c: maintain separate lists of active and inactive +	connections, and a count of each. Maintain count of completed +	connections per user. Implement code to check connection limits. + +	* dbus/dbus-list.c (_dbus_list_unlink): export + +	* bus/bus.c (bus_context_check_security_policy): enforce a maximum +	number of bytes in the message queue for a connection +  2003-04-18  Havoc Pennington  <hp@pobox.com>  	* dbus/dbus-auth.c (record_mechanisms): memleak fixes @@ -45,8 +45,11 @@ struct BusContext    BusRegistry *registry;    BusPolicy *policy;    DBusUserDatabase *user_database; -  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 */ +  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_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 */ @@ -210,6 +213,12 @@ new_connection_callback (DBusServer     *server,         */        dbus_connection_disconnect (new_connection);      } + +  dbus_connection_set_max_received_size (new_connection, +                                         context->max_incoming_bytes); + +  dbus_connection_set_max_message_size (new_connection, +                                        context->max_message_size);    /* on OOM, we won't have ref'd the connection so it will die. */  } @@ -353,6 +362,11 @@ bus_context_new (const DBusString *config_file,     */    if (!server_data_slot_ref ())      _dbus_assert_not_reached ("second ref of server data slot failed"); + +  /* Make up some numbers! woot! */ +  context->max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;   +  context->max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63; +  context->max_message_size = _DBUS_ONE_MEGABYTE * 32;  #ifdef DBUS_BUILD_TESTS    context->activation_timeout = 6000;  /* 6 seconds */ @@ -375,7 +389,7 @@ bus_context_new (const DBusString *config_file,     * DOS all the other users.     */    context->max_completed_connections = 1024; - +      context->user_database = _dbus_user_database_new ();    if (context->user_database == NULL)      { @@ -818,6 +832,30 @@ bus_context_get_activation_timeout (BusContext *context)    return context->activation_timeout;  } +int +bus_context_get_auth_timeout (BusContext *context) +{ +  return context->auth_timeout; +} + +int +bus_context_get_max_completed_connections (BusContext *context) +{ +  return context->max_completed_connections; +} + +int +bus_context_get_max_incomplete_connections (BusContext *context) +{ +  return context->max_incomplete_connections; +} + +int +bus_context_get_max_connections_per_user (BusContext *context) +{ +  return context->max_connections_per_user; +} +  dbus_bool_t  bus_context_check_security_policy (BusContext     *context,                                     DBusConnection *sender, @@ -878,5 +916,17 @@ bus_context_check_security_policy (BusContext     *context,        return FALSE;      } +  /* See if limits on size have been exceeded */ +  if (recipient && +      dbus_connection_get_outgoing_size (recipient) > +      context->max_outgoing_bytes) +    { +      const char *dest = dbus_message_get_service (message); +      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, +                      "The destination service \"%s\" has a full message queue", +                      dest ? dest : DBUS_SERVICE_DBUS); +      return FALSE; +    } +      return TRUE;  } @@ -41,29 +41,34 @@ typedef struct BusRegistry      BusRegistry;  typedef struct BusService       BusService;  typedef struct BusTransaction   BusTransaction; -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); -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); +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/connection.c b/bus/connection.c index 71ab0108..14081e2e 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -26,14 +26,19 @@  #include "services.h"  #include "utils.h"  #include <dbus/dbus-list.h> +#include <dbus/dbus-hash.h>  static void bus_connection_remove_transactions (DBusConnection *connection);  struct BusConnections  {    int refcount; -  DBusList *list; /**< List of all the connections */ +  DBusList *completed;  /**< List of all completed connections */ +  int n_completed;      /**< Length of completed list */ +  DBusList *incomplete; /**< List of all not-yet-active connections */ +  int n_incomplete;     /**< Length of incomplete list */    BusContext *context; +  DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */  };  static int connection_data_slot = -1; @@ -42,6 +47,7 @@ static int connection_data_slot_refcount = 0;  typedef struct  {    BusConnections *connections; +  DBusList *link_in_connection_list;    DBusConnection *connection;    DBusList *services_owned;    char *name; @@ -96,6 +102,65 @@ connection_get_loop (DBusConnection *connection)    return bus_context_get_loop (d->connections->context);  } + +static int +get_connections_for_uid (BusConnections *connections, +                         dbus_uid_t      uid) +{ +  void *val; +  int current_count; + +  /* val is NULL is 0 when it isn't in the hash yet */ +   +  val = _dbus_hash_table_lookup_ulong (connections->completed_by_user, +                                       uid); + +  current_count = _DBUS_POINTER_TO_INT (val); + +  return current_count; +} + +static dbus_bool_t +adjust_connections_for_uid (BusConnections *connections, +                            dbus_uid_t      uid, +                            int             adjustment) +{ +  int current_count; + +  current_count = get_connections_for_uid (connections, uid); + +  _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT +                 ": was %d adjustment %d making %d\n", +                 uid, current_count, adjustment, current_count + adjustment); +   +  _dbus_assert (current_count >= 0); +   +  current_count += adjustment; + +  _dbus_assert (current_count >= 0); + +  if (current_count == 0) +    { +      _dbus_hash_table_remove_ulong (connections->completed_by_user, uid); +      return TRUE; +    } +  else +    { +      dbus_bool_t retval; +       +      retval = _dbus_hash_table_insert_ulong (connections->completed_by_user, +                                              uid, _DBUS_INT_TO_POINTER (current_count)); + +      /* only positive adjustment can fail as otherwise +       * a hash entry should already exist +       */ +      _dbus_assert (adjustment > 0 || +                    (adjustment <= 0 && retval)); + +      return retval; +    } +} +  void  bus_connection_disconnected (DBusConnection *connection)  { @@ -180,8 +245,34 @@ bus_connection_disconnected (DBusConnection *connection)    bus_connection_remove_transactions (connection); -  _dbus_list_remove (&d->connections->list, connection); +  if (d->link_in_connection_list != NULL) +    { +      if (d->name != NULL) +        { +          unsigned long uid; +           +          _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list); +          d->link_in_connection_list = NULL; +          d->connections->n_completed -= 1; +          if (dbus_connection_get_unix_user (connection, &uid)) +            { +              if (!adjust_connections_for_uid (d->connections, +                                               uid, -1)) +                _dbus_assert_not_reached ("adjusting downward should never fail"); +            } +        } +      else +        { +          _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list); +          d->link_in_connection_list = NULL; +          d->connections->n_incomplete -= 1; +        } +       +      _dbus_assert (d->connections->n_incomplete >= 0); +      _dbus_assert (d->connections->n_completed >= 0); +    } +      /* frees "d" as side effect */    dbus_connection_set_data (connection,                              connection_data_slot, @@ -323,6 +414,15 @@ bus_connections_new (BusContext *context)        connection_data_slot_unref ();        return NULL;      } + +  connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG, +                                                         NULL, NULL); +  if (connections->completed_by_user == NULL) +    { +      dbus_free (connections); +      connection_data_slot_unref (); +      return NULL; +    }    connections->refcount = 1;    connections->context = context; @@ -344,19 +444,37 @@ bus_connections_unref (BusConnections *connections)    connections->refcount -= 1;    if (connections->refcount == 0)      { -      while (connections->list != NULL) +      /* drop all incomplete */ +      while (connections->incomplete != NULL)          {            DBusConnection *connection; -          connection = connections->list->data; +          connection = connections->incomplete->data;            dbus_connection_ref (connection);            dbus_connection_disconnect (connection);            bus_connection_disconnected (connection);            dbus_connection_unref (connection);          } + +      _dbus_assert (connections->n_incomplete == 0); -      _dbus_list_clear (&connections->list); +      /* drop all real connections */ +      while (connections->completed != NULL) +        { +          DBusConnection *connection; + +          connection = connections->completed->data; + +          dbus_connection_ref (connection); +          dbus_connection_disconnect (connection); +          bus_connection_disconnected (connection); +          dbus_connection_unref (connection);           +        } + +      _dbus_assert (connections->n_completed == 0); + +      _dbus_hash_table_unref (connections->completed_by_user);        dbus_free (connections); @@ -405,8 +523,7 @@ bus_connections_setup_connection (BusConnections *connections,                                                NULL,                                                connection, NULL))      goto out; - - +      dbus_connection_set_unix_user_function (connection,                                            allow_user_function,                                            NULL, NULL); @@ -415,16 +532,14 @@ bus_connections_setup_connection (BusConnections *connections,                                                  dispatch_status_function,                                                  bus_context_get_loop (connections->context),                                                  NULL); + +  d->link_in_connection_list = _dbus_list_alloc_link (connection); +  if (d->link_in_connection_list == NULL) +    goto out;    /* Setup the connection with the dispatcher */    if (!bus_dispatch_add_connection (connection))      goto out; -   -  if (!_dbus_list_append (&connections->list, connection)) -    { -      bus_dispatch_remove_connection (connection); -      goto out; -    }    if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)      { @@ -434,13 +549,36 @@ bus_connections_setup_connection (BusConnections *connections,            goto out;          }      } + +  _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list); +  connections->n_incomplete += 1;    dbus_connection_ref (connection); + +  /* Note that we might disconnect ourselves here, but it only takes +   * effect on return to the main loop. +   */ +  if (connections->n_incomplete > +      bus_context_get_max_incomplete_connections (connections->context)) +    { +      _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n"); +       +      _dbus_assert (connections->incomplete != NULL); +      /* Disconnect the oldest unauthenticated connection.  FIXME +       * would it be more secure to drop a *random* connection?  This +       * algorithm seems to mean that if someone can create new +       * connections quickly enough, they can keep anyone else from +       * completing authentication. But random may or may not really +       * help with that, a more elaborate solution might be required. +       */ +      dbus_connection_disconnect (connections->incomplete->data); +    } +      retval = TRUE;   out:    if (!retval) -    {         +    {              if (!dbus_connection_set_watch_functions (connection,                                                  NULL, NULL, NULL,                                                  connection, @@ -463,6 +601,13 @@ bus_connections_setup_connection (BusConnections *connections,                                       connection_data_slot,                                       NULL, NULL))          _dbus_assert_not_reached ("failed to set connection data to null"); + +      if (d->link_in_connection_list != NULL) +        { +          _dbus_assert (d->link_in_connection_list->next == NULL); +          _dbus_assert (d->link_in_connection_list->prev == NULL); +          _dbus_list_free_link (d->link_in_connection_list); +        }      }    return retval; @@ -567,6 +712,67 @@ bus_connection_get_policy (DBusConnection *connection)    return d->policy;  } +static dbus_bool_t +foreach_active (BusConnections               *connections, +                BusConnectionForeachFunction  function, +                void                         *data) +{ +  DBusList *link; +   +  link = _dbus_list_get_first_link (&connections->completed); +  while (link != NULL) +    { +      DBusConnection *connection = link->data; +      DBusList *next = _dbus_list_get_next_link (&connections->completed, link); + +      if (!(* function) (connection, data)) +        return FALSE; +       +      link = next; +    } + +  return TRUE; +} + +static dbus_bool_t +foreach_inactive (BusConnections               *connections, +                  BusConnectionForeachFunction  function, +                  void                         *data) +{ +  DBusList *link; +   +  link = _dbus_list_get_first_link (&connections->incomplete); +  while (link != NULL) +    { +      DBusConnection *connection = link->data; +      DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link); + +      if (!(* function) (connection, data)) +        return FALSE; +       +      link = next; +    } + +  return TRUE; +} + +/** + * Calls function on each active connection; if the function returns + * #FALSE, stops iterating. Active connections are authenticated + * and have sent a Hello message. + * + * @param connections the connections object + * @param function the function + * @param data data to pass to it as a second arg + */ +void +bus_connections_foreach_active (BusConnections               *connections, +                                BusConnectionForeachFunction  function, +                                void                         *data) +{ +  foreach_active (connections, function, data); +} +  /**   * Calls function on each connection; if the function returns   * #FALSE, stops iterating. @@ -578,21 +784,12 @@ bus_connection_get_policy (DBusConnection *connection)  void  bus_connections_foreach (BusConnections               *connections,                           BusConnectionForeachFunction  function, -			void                          *data) +                         void                         *data)  { -  DBusList *link; -   -  link = _dbus_list_get_first_link (&connections->list); -  while (link != NULL) -    { -      DBusConnection *connection = link->data; -      DBusList *next = _dbus_list_get_next_link (&connections->list, link); +  if (!foreach_active (connections, function, data)) +    return; -      if (!(* function) (connection, data)) -        break; -       -      link = next; -    } +  foreach_inactive (connections, function, data);  }  BusContext* @@ -789,17 +986,40 @@ bus_connection_set_name (DBusConnection   *connection,  			 const DBusString *name)  {    BusConnectionData *d; +  unsigned long uid;    d = BUS_CONNECTION_DATA (connection);    _dbus_assert (d != NULL);    _dbus_assert (d->name == NULL); - +      if (!_dbus_string_copy_data (name, &d->name))      return FALSE;    _dbus_assert (d->name != NULL);    _dbus_verbose ("Name %s assigned to %p\n", d->name, connection); + +  if (dbus_connection_get_unix_user (connection, &uid)) +    { +      if (!adjust_connections_for_uid (d->connections, +                                       uid, 1)) +        { +          dbus_free (d->name); +          d->name = NULL; +          return FALSE; +        } +    } +   +  /* Now the connection is active, move it between lists */ +  _dbus_list_unlink (&d->connections->incomplete, +                     d->link_in_connection_list); +  d->connections->n_incomplete -= 1; +  _dbus_list_append_link (&d->connections->completed, +                          d->link_in_connection_list); +  d->connections->n_completed += 1; + +  _dbus_assert (d->connections->n_incomplete >= 0); +  _dbus_assert (d->connections->n_completed > 0);    return TRUE;  } @@ -815,6 +1035,47 @@ bus_connection_get_name (DBusConnection *connection)    return d->name;  } +/** + * Check whether completing the passed-in connection would + * exceed limits, and if so set error and return #FALSE + */ +dbus_bool_t +bus_connections_check_limits (BusConnections  *connections, +                              DBusConnection  *requesting_completion, +                              DBusError       *error) +{ +  BusConnectionData *d; +  unsigned long uid; +   +  d = BUS_CONNECTION_DATA (requesting_completion); +  _dbus_assert (d != NULL); + +  _dbus_assert (d->name == NULL); + +  if (connections->n_completed >= +      bus_context_get_max_completed_connections (connections->context)) +    { +      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, +                      "The maximum number of active connections has been reached"); +      return FALSE; +    } +   +  if (dbus_connection_get_unix_user (requesting_completion, &uid)) +    { +      if (get_connections_for_uid (connections, uid) >= +          bus_context_get_max_connections_per_user (connections->context)) +        { +          dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, +                          "The maximum number of active connections for UID %lu has been reached", +                          uid); +          return FALSE; +        } +    } +   +  return TRUE; +} + +  /*   * Transactions   * diff --git a/bus/connection.h b/bus/connection.h index c429007b..0d4d3a10 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -40,12 +40,18 @@ dbus_bool_t     bus_connections_setup_connection (BusConnections               *  void            bus_connections_foreach          (BusConnections               *connections,                                                    BusConnectionForeachFunction  function,                                                    void                         *data); +void            bus_connections_foreach_active   (BusConnections               *connections, +                                                  BusConnectionForeachFunction  function, +                                                  void                         *data);  BusContext*     bus_connections_get_context      (BusConnections               *connections); - -BusContext*     bus_connection_get_context       (DBusConnection               *connection);  +BusContext*     bus_connection_get_context       (DBusConnection               *connection);  BusConnections* bus_connection_get_connections   (DBusConnection               *connection);  BusRegistry*    bus_connection_get_registry      (DBusConnection               *connection);  BusActivation*  bus_connection_get_activation    (DBusConnection               *connection); +dbus_bool_t     bus_connections_check_limits     (BusConnections               *connections, +                                                  DBusConnection               *requesting_completion, +                                                  DBusError                    *error); +  dbus_bool_t bus_connection_is_active (DBusConnection *connection); diff --git a/bus/dispatch.c b/bus/dispatch.c index d1c19fd3..c1e67d6a 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -48,9 +48,6 @@ static dbus_bool_t  send_one_message (DBusConnection *connection, void *data)  {    SendMessageData *d = data; -   -  if (!bus_connection_is_active (connection)) -    return TRUE;    if (!bus_context_check_security_policy (d->context,                                            d->sender, @@ -93,7 +90,7 @@ bus_dispatch_broadcast_message (BusTransaction *transaction,    d.transaction = transaction;    d.error = &tmp_error; -  bus_connections_foreach (connections, send_one_message, &d); +  bus_connections_foreach_active (connections, send_one_message, &d);    if (dbus_error_is_set (&tmp_error))      { diff --git a/bus/driver.c b/bus/driver.c index c52020b5..bc58f556 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -262,8 +262,23 @@ bus_driver_handle_hello (DBusConnection *connection,    BusService *service;    dbus_bool_t retval;    BusRegistry *registry; +  BusConnections *connections;    _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +  /* Note that when these limits are exceeded we don't disconnect the +   * connection; we just sort of leave it hanging there until it times +   * out or disconnects itself or is dropped due to the max number of +   * incomplete connections. It's even OK if the connection wants to +   * retry the hello message, we support that. +   */ +  connections = bus_connection_get_connections (connection); +  if (!bus_connections_check_limits (connections, connection, +                                     error)) +    { +      _DBUS_ASSERT_ERROR_IS_SET (error); +      return FALSE; +    }    if (!_dbus_string_init (&unique_name))      { diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 6e8a9f15..c2206cd3 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -183,11 +183,11 @@ void*       dbus_connection_get_data           (DBusConnection   *connection,  void        dbus_connection_set_change_sigpipe (dbus_bool_t       will_modify_sigpipe);  -void dbus_connection_set_max_message_size       (DBusConnection *connection, -                                                 long            size); -long dbus_connection_get_max_message_size       (DBusConnection *connection); +void dbus_connection_set_max_message_size  (DBusConnection *connection, +                                            long            size); +long dbus_connection_get_max_message_size  (DBusConnection *connection);  void dbus_connection_set_max_received_size (DBusConnection *connection, -                                                 long            size); +                                            long            size);  long dbus_connection_get_max_received_size (DBusConnection *connection);  long dbus_connection_get_outgoing_size     (DBusConnection *connection); diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c index 5f4c67ca..235ed275 100644 --- a/dbus/dbus-list.c +++ b/dbus/dbus-list.c @@ -470,7 +470,15 @@ _dbus_list_remove_last (DBusList **list,    return FALSE;  } -static void +/** + * Removes the given link from the list, but doesn't + * free it. _dbus_list_remove_link() both removes the + * link and also frees it. + * + * @param list the list + * @param link the link in the list + */ +void  _dbus_list_unlink (DBusList **list,                     DBusList  *link)  { @@ -487,6 +495,9 @@ _dbus_list_unlink (DBusList **list,        if (*list == link)          *list = link->next;      } + +  link->next = NULL; +  link->prev = NULL;  }  /** diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h index ad74dfd0..f3b37ef8 100644 --- a/dbus/dbus-list.h +++ b/dbus/dbus-list.h @@ -74,6 +74,8 @@ dbus_bool_t _dbus_list_copy               (DBusList **list,  int         _dbus_list_get_length         (DBusList **list);  DBusList*   _dbus_list_alloc_link         (void      *data);  void        _dbus_list_free_link          (DBusList  *link); +void        _dbus_list_unlink             (DBusList **list, +                                           DBusList  *link);  void        _dbus_list_append_link        (DBusList **list,                                             DBusList  *link);  void        _dbus_list_prepend_link       (DBusList **list, diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 62aa0b4b..7673085f 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -470,8 +470,8 @@ _dbus_listen_unix_socket (const char     *path,     * But there doesn't seem to be a good way to do this.     *     * Just to be extra careful, I threw in the stat() - clearly -   * the stat() can't *fix* any security issue, but it probably -   * makes it harder to exploit. +   * the stat() can't *fix* any security issue, but it at least +   * avoids inadvertent/accidental data loss.     */    {      struct stat sb; @@ -21,10 +21,6 @@   - Activation needs some careful additional thinking-through. - - Recursive/composite/etc. types and associated API, see mailing list. - - - Configuration file (working on that now) -   - Property list feature on message bus (list of properties associated      with a connection). May also include message matching rules      that involve the properties of the source or destination @@ -46,9 +42,6 @@   - We might consider returning a "no such operation" error in dbus-connection.c      for unhandled messages. - - Abstract the user database, so you can use something other than the system password  -   database. -   - The convenience functions in dbus-bus.h should perhaps have     the signatures that they would have if they were autogenerated     stubs. e.g. the acquire service function. We should also evaluate  @@ -60,9 +53,6 @@     some basic spec'ing out of the GLib/Qt level stubs/skels stuff will be      needed to understand the right approach. - - sync up DBusWatch and DBusTimeout so that handle_watch() is a method on DBusWatch  -   similar to the way timeouts work -   - there are various bits of code to manage ref/unref of data slots, that should      be merged into a generic facility @@ -85,7 +75,5 @@   - We have a limit on the number of messages a connection can send, but      not on how many can be buffered for a given connection. - - make client serial and reply serial unsigned and add dbus_message_get_is_reply() -   - other apps can send you a fake DBUS_MESSAGE_LOCAL_DISCONNECT; need to      check for that and disallow it.  | 
