diff options
Diffstat (limited to 'dbus')
-rw-r--r-- | dbus/dbus-connection.c | 4 | ||||
-rw-r--r-- | dbus/dbus-mainloop.c | 65 | ||||
-rw-r--r-- | dbus/dbus-message.c | 2 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.c | 75 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 3 | ||||
-rw-r--r-- | dbus/dbus-transport-protected.h | 1 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 38 |
7 files changed, 129 insertions, 59 deletions
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 9595f48a..94fe075c 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2082,8 +2082,8 @@ dbus_connection_dispatch (DBusConnection *connection) } } - _dbus_verbose (" done dispatching %p (%s)\n", message, - dbus_message_get_name (message)); + _dbus_verbose (" done dispatching %p (%s) on connection %p\n", message, + dbus_message_get_name (message), connection); out: _dbus_connection_release_dispatch (connection); diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c index bf011082..3c810f22 100644 --- a/dbus/dbus-mainloop.c +++ b/dbus/dbus-mainloop.c @@ -47,6 +47,7 @@ typedef enum typedef struct { + int refcount; CallbackType type; void *data; DBusFreeFunction free_data_func; @@ -74,10 +75,10 @@ typedef struct #define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback) static WatchCallback* -watch_callback_new (DBusWatch *watch, +watch_callback_new (DBusWatch *watch, DBusWatchFunction function, - void *data, - DBusFreeFunction free_data_func) + void *data, + DBusFreeFunction free_data_func) { WatchCallback *cb; @@ -88,18 +89,19 @@ watch_callback_new (DBusWatch *watch, cb->watch = watch; cb->function = function; cb->last_iteration_oom = FALSE; + cb->callback.refcount = 1; cb->callback.type = CALLBACK_WATCH; cb->callback.data = data; cb->callback.free_data_func = free_data_func; - + return cb; } static TimeoutCallback* -timeout_callback_new (DBusTimeout *timeout, +timeout_callback_new (DBusTimeout *timeout, DBusTimeoutFunction function, - void *data, - DBusFreeFunction free_data_func) + void *data, + DBusFreeFunction free_data_func) { TimeoutCallback *cb; @@ -111,6 +113,7 @@ timeout_callback_new (DBusTimeout *timeout, cb->function = function; _dbus_get_current_time (&cb->last_tv_sec, &cb->last_tv_usec); + cb->callback.refcount = 1; cb->callback.type = CALLBACK_TIMEOUT; cb->callback.data = data; cb->callback.free_data_func = free_data_func; @@ -119,12 +122,27 @@ timeout_callback_new (DBusTimeout *timeout, } static void -callback_free (Callback *cb) +callback_ref (Callback *cb) +{ + _dbus_assert (cb->refcount > 0); + + cb->refcount += 1; +} + +static void +callback_unref (Callback *cb) { - if (cb->free_data_func) - (* cb->free_data_func) (cb->data); + _dbus_assert (cb->refcount > 0); + + cb->refcount -= 1; - dbus_free (cb); + if (cb->refcount == 0) + { + if (cb->free_data_func) + (* cb->free_data_func) (cb->data); + + dbus_free (cb); + } } static dbus_bool_t @@ -165,7 +183,7 @@ remove_callback (DBusLoop *loop, break; } - callback_free (cb); + callback_unref (cb); _dbus_list_remove_link (&loop->callbacks, link); loop->callback_list_serial += 1; } @@ -229,7 +247,7 @@ _dbus_loop_add_watch (DBusLoop *loop, if (!add_callback (loop, (Callback*) wcb)) { wcb->callback.free_data_func = NULL; /* don't want to have this side effect */ - callback_free ((Callback*) wcb); + callback_unref ((Callback*) wcb); return FALSE; } @@ -283,7 +301,7 @@ _dbus_loop_add_timeout (DBusLoop *loop, if (!add_callback (loop, (Callback*) tcb)) { tcb->callback.free_data_func = NULL; /* don't want to have this side effect */ - callback_free ((Callback*) tcb); + callback_unref ((Callback*) tcb); return FALSE; } @@ -490,6 +508,7 @@ _dbus_loop_iterate (DBusLoop *loop, fds = NULL; watches_for_fds = NULL; + n_fds = 0; oom_watch_pending = FALSE; orig_depth = loop->depth; @@ -578,6 +597,8 @@ _dbus_loop_iterate (DBusLoop *loop, else if (dbus_watch_get_enabled (wcb->watch)) { watches_for_fds[i] = wcb; + + callback_ref (cb); flags = dbus_watch_get_flags (wcb->watch); @@ -726,7 +747,7 @@ _dbus_loop_iterate (DBusLoop *loop, unsigned int condition; wcb = watches_for_fds[i]; - + condition = 0; if (fds[i].revents & _DBUS_POLLIN) condition |= DBUS_WATCH_READABLE; @@ -765,8 +786,18 @@ _dbus_loop_iterate (DBusLoop *loop, next_iteration: if (fds && fds != static_fds) dbus_free (fds); - if (watches_for_fds && watches_for_fds != static_watches_for_fds) - dbus_free (watches_for_fds); + if (watches_for_fds) + { + i = 0; + while (i < n_fds) + { + callback_unref (&watches_for_fds[i]->callback); + ++i; + } + + if (watches_for_fds != static_watches_for_fds) + dbus_free (watches_for_fds); + } if (_dbus_loop_dispatch (loop)) retval = TRUE; diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 0044913e..5e6a2c60 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -585,7 +585,7 @@ _dbus_message_set_serial (DBusMessage *message, */ dbus_bool_t dbus_message_set_reply_serial (DBusMessage *message, - dbus_int32_t reply_serial) + dbus_int32_t reply_serial) { _dbus_assert (!message->locked); diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index f706d08a..0877a293 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -1315,7 +1315,8 @@ static dbus_bool_t store_user_info (struct passwd *p, DBusCredentials *credentials, DBusString *homedir, - DBusString *username_out) + DBusString *username_out, + DBusError *error) { int old_homedir_len; @@ -1332,7 +1333,7 @@ store_user_info (struct passwd *p, if (!_dbus_string_append (homedir, p->pw_dir)) { - _dbus_verbose ("No memory to get homedir\n"); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } } @@ -1342,7 +1343,7 @@ store_user_info (struct passwd *p, { if (homedir) _dbus_string_set_length (homedir, old_homedir_len); - _dbus_verbose ("No memory to get username\n"); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } @@ -1363,6 +1364,7 @@ store_user_info (struct passwd *p, * @param credentials to fill in or #NULL * @param homedir string to append homedir to or #NULL * @param username_out string to append username to or #NULL + * @param error return location for reason for failure * * @returns #TRUE on success */ @@ -1371,7 +1373,8 @@ get_user_info (const DBusString *username, dbus_uid_t uid, DBusCredentials *credentials, DBusString *homedir, - DBusString *username_out) + DBusString *username_out, + DBusError *error) { const char *username_c_str; @@ -1417,10 +1420,13 @@ get_user_info (const DBusString *username, if (result == 0 && p == &p_str) { return store_user_info (p, credentials, homedir, - username_out); + username_out, error); } else { + dbus_set_error (error, DBUS_ERROR_FAILED, + "User \"%s\" unknown or no memory to allocate password entry\n", + username_c_str); _dbus_verbose ("User %s unknown\n", username_c_str); return FALSE; } @@ -1438,10 +1444,13 @@ get_user_info (const DBusString *username, if (p != NULL) { return store_user_info (p, credentials, homedir, - username_out); + username_out, error); } else { + dbus_set_error (error, DBUS_ERROR_FAILED, + "User \"%s\" unknown or no memory to allocate password entry\n", + username_c_str); _dbus_verbose ("User %s unknown\n", username_c_str); return FALSE; } @@ -1474,7 +1483,7 @@ dbus_bool_t _dbus_credentials_from_username (const DBusString *username, DBusCredentials *credentials) { - return get_user_info (username, -1, credentials, NULL, NULL); + return get_user_info (username, -1, credentials, NULL, NULL, NULL); } /** @@ -1512,7 +1521,7 @@ dbus_bool_t _dbus_credentials_from_user_id (unsigned long user_id, DBusCredentials *credentials) { - return get_user_info (NULL, user_id, credentials, NULL, NULL); + return get_user_info (NULL, user_id, credentials, NULL, NULL, NULL); } _DBUS_DEFINE_GLOBAL_LOCK (user_info); @@ -1570,7 +1579,7 @@ _dbus_user_info_from_current_process (const DBusString **username, _dbus_credentials_clear (&u.creds); if (!get_user_info (NULL, getuid (), - &u.creds, &u.dir, &u.name)) + &u.creds, &u.dir, &u.name, NULL)) goto fail_init; if (!_dbus_register_shutdown_func (shutdown_user_info, @@ -1611,7 +1620,7 @@ dbus_bool_t _dbus_homedir_from_username (const DBusString *username, DBusString *homedir) { - return get_user_info (username, -1, NULL, homedir, NULL); + return get_user_info (username, -1, NULL, homedir, NULL, NULL); } /** @@ -1773,21 +1782,20 @@ _dbus_get_group_id (const DBusString *group_name, /** * Gets all groups for a particular user. Returns #FALSE * if no memory, or user isn't known, but always initializes - * group_ids to a NULL array. - * - * @todo failing to distinguish "out of memory" from - * "unknown user" is kind of bogus and would probably - * result in a failure in a comprehensive test suite. + * group_ids to a NULL array. Sets error to the reason + * for returning #FALSE. * * @param uid the user ID * @param group_ids return location for array of group IDs * @param n_group_ids return location for length of returned array + * @param error return location for error * @returns #TRUE on success */ dbus_bool_t _dbus_get_groups (unsigned long uid, unsigned long **group_ids, - int *n_group_ids) + int *n_group_ids, + DBusError *error) { DBusCredentials creds; DBusString username; @@ -1800,10 +1808,13 @@ _dbus_get_groups (unsigned long uid, retval = FALSE; if (!_dbus_string_init (&username)) - return FALSE; + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return FALSE; + } if (!get_user_info (NULL, uid, &creds, - NULL, &username) || + NULL, &username, error) || creds.gid == DBUS_GID_UNSET) goto out; @@ -1818,7 +1829,10 @@ _dbus_get_groups (unsigned long uid, buf_count = 17; buf = dbus_new (gid_t, buf_count); if (buf == NULL) - goto out; + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } if (getgrouplist (username_c, creds.gid, @@ -1827,6 +1841,7 @@ _dbus_get_groups (unsigned long uid, gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0])); if (new == NULL) { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_free (buf); goto out; } @@ -1839,6 +1854,7 @@ _dbus_get_groups (unsigned long uid, *group_ids = dbus_new (unsigned long, buf_count); if (*group_ids == NULL) { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_free (buf); goto out; } @@ -1855,19 +1871,28 @@ _dbus_get_groups (unsigned long uid, /* We just get the one group ID */ *group_ids = dbus_new (unsigned long, 1); if (*group_ids == NULL) - goto out; + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } *n_group_ids = 1; (*group_ids)[0] = creds.gid; } #endif /* HAVE_GETGROUPLIST */ + + retval = TRUE; + + out: + _dbus_string_free (&username); - retval = TRUE; - - out: - _dbus_string_free (&username); - return retval; + if (retval) + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + else + _DBUS_ASSERT_ERROR_IS_SET (error); + + return retval; } /** diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 4edfe94a..27f27b58 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -148,7 +148,8 @@ dbus_bool_t _dbus_get_group_id (const DBusString *group_name, dbus_gid_t *gid); dbus_bool_t _dbus_get_groups (dbus_uid_t uid, dbus_gid_t **group_ids, - int *n_group_ids); + int *n_group_ids, + DBusError *error); unsigned long _dbus_getpid (void); diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 052c15fa..1c5b4208 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -100,6 +100,7 @@ struct DBusTransport unsigned int send_credentials_pending : 1; /**< #TRUE if we need to send credentials */ unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */ unsigned int is_server : 1; /**< #TRUE if on the server side */ + unsigned int unused_bytes_recovered : 1; /**< #TRUE if we've recovered unused bytes from auth */ }; dbus_bool_t _dbus_transport_init_base (DBusTransport *transport, diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index f9b3d8a8..e726de24 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -459,9 +459,21 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) maybe_authenticated = (!(transport->send_credentials_pending || - transport->receive_credentials_pending)) && - _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED; + transport->receive_credentials_pending)); + if (maybe_authenticated) + { + switch (_dbus_auth_do_work (transport->auth)) + { + case DBUS_AUTH_STATE_AUTHENTICATED: + case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES: + /* leave as maybe_authenticated */ + break; + default: + maybe_authenticated = FALSE; + } + } + /* If we've authenticated as some identity, check that the auth * identity is the same as our own identity. In the future, we * may have API allowing applications to specify how this is @@ -768,18 +780,18 @@ _dbus_transport_get_dispatch_status (DBusTransport *transport) if (!_dbus_transport_get_is_authenticated (transport)) { - switch (_dbus_auth_do_work (transport->auth)) - { - case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: - return DBUS_DISPATCH_NEED_MEMORY; - case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES: - if (!recover_unused_bytes (transport)) - return DBUS_DISPATCH_NEED_MEMORY; - break; - default: - break; - } + if (_dbus_auth_do_work (transport->auth) == + DBUS_AUTH_STATE_WAITING_FOR_MEMORY) + return DBUS_DISPATCH_NEED_MEMORY; + else + return DBUS_DISPATCH_COMPLETE; } + + if (!transport->unused_bytes_recovered && + !recover_unused_bytes (transport)) + return DBUS_DISPATCH_NEED_MEMORY; + + transport->unused_bytes_recovered = TRUE; if (!_dbus_message_loader_queue_messages (transport->loader)) return DBUS_DISPATCH_NEED_MEMORY; |