From cc3cb7ac6ffe5fb8b9bb847d81a21186fda2c549 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: May 09 2018 17:59:13 +0000 Subject: fix crash on user deletion Resolves: 1573550 --- diff --git a/0001-daemon-unregister-user-after-we-re-done-with-it-not-.patch b/0001-daemon-unregister-user-after-we-re-done-with-it-not-.patch new file mode 100644 index 0000000..1efdb3a --- /dev/null +++ b/0001-daemon-unregister-user-after-we-re-done-with-it-not-.patch @@ -0,0 +1,87 @@ +From 2d9e0f43c46e1be8afd94944e7461e0086497fd3 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 4 May 2018 16:43:03 -0400 +Subject: [PATCH 1/2] daemon: unregister user after we're done with it not + before + +Now that we get the object path for a user directly from the skeleton, +we can't access that object path after the skeleton is unregistered. + +This commit fixes a problem where the user deletion handling code tries +to access the object path of a user after its skeleton is unregistered. +--- + src/daemon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/daemon.c b/src/daemon.c +index 9ec153a..d3fa971 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -483,63 +483,63 @@ reload_users (Daemon *daemon) + if (!user_get_system_account (user)) + number_of_normal_users++; + user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL); + } + g_hash_table_destroy (local); + + had_no_users = accounts_accounts_get_has_no_users (accounts); + has_no_users = number_of_normal_users == 0; + + if (had_no_users != has_no_users) + accounts_accounts_set_has_no_users (accounts, has_no_users); + + had_multiple_users = accounts_accounts_get_has_multiple_users (accounts); + has_multiple_users = number_of_normal_users > 1; + + if (had_multiple_users != has_multiple_users) + accounts_accounts_set_has_multiple_users (accounts, has_multiple_users); + + /* Swap out the users */ + old_users = daemon->priv->users; + daemon->priv->users = users; + + /* Remove all the old users */ + g_hash_table_iter_init (&iter, old_users); + while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) { + User *refreshed_user; + + refreshed_user = g_hash_table_lookup (users, name); + + if (!refreshed_user || !user_get_cached (refreshed_user)) { +- user_unregister (user); + accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon), + user_get_object_path (user)); ++ user_unregister (user); + } + } + + /* Register all the new users */ + g_hash_table_iter_init (&iter, users); + while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) { + User *stale_user; + + stale_user = g_hash_table_lookup (old_users, name); + + if (!stale_user || !user_get_cached (stale_user) && user_get_cached (user)) { + user_register (user); + accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), + user_get_object_path (user)); + } + g_object_thaw_notify (G_OBJECT (user)); + } + + g_hash_table_destroy (old_users); + } + + static gboolean + reload_users_timeout (Daemon *daemon) + { + reload_users (daemon); + daemon->priv->reload_id = 0; + + return FALSE; + } + +-- +2.17.0 + diff --git a/0002-daemon-don-t-emit-user-deleted-for-uncached-users.patch b/0002-daemon-don-t-emit-user-deleted-for-uncached-users.patch new file mode 100644 index 0000000..e696569 --- /dev/null +++ b/0002-daemon-don-t-emit-user-deleted-for-uncached-users.patch @@ -0,0 +1,89 @@ +From 815c43087926eb22f37fed6f501a3e9291edf564 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 9 May 2018 09:26:57 -0400 +Subject: [PATCH 2/2] daemon: don't emit user-deleted for uncached users + +Right now we emit spurious user-deleted signals for +all uncached users anytime a reload occurs. +Uncached users are users explicitly requested by a client, +but not part of the results returned from ListCachedUsers. + +We should only be emitting user-deleted it they were initially +cached and transitioned to uncached, not if they're still +hanging around in an uncached state. + +This commit fixes the code to do that. +--- + src/daemon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/daemon.c b/src/daemon.c +index d3fa971..a12b71b 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -482,61 +482,61 @@ reload_users (Daemon *daemon) + while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) { + if (!user_get_system_account (user)) + number_of_normal_users++; + user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL); + } + g_hash_table_destroy (local); + + had_no_users = accounts_accounts_get_has_no_users (accounts); + has_no_users = number_of_normal_users == 0; + + if (had_no_users != has_no_users) + accounts_accounts_set_has_no_users (accounts, has_no_users); + + had_multiple_users = accounts_accounts_get_has_multiple_users (accounts); + has_multiple_users = number_of_normal_users > 1; + + if (had_multiple_users != has_multiple_users) + accounts_accounts_set_has_multiple_users (accounts, has_multiple_users); + + /* Swap out the users */ + old_users = daemon->priv->users; + daemon->priv->users = users; + + /* Remove all the old users */ + g_hash_table_iter_init (&iter, old_users); + while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) { + User *refreshed_user; + + refreshed_user = g_hash_table_lookup (users, name); + +- if (!refreshed_user || !user_get_cached (refreshed_user)) { ++ if (!refreshed_user || user_get_cached (user) && !user_get_cached (refreshed_user)) { + accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon), + user_get_object_path (user)); + user_unregister (user); + } + } + + /* Register all the new users */ + g_hash_table_iter_init (&iter, users); + while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) { + User *stale_user; + + stale_user = g_hash_table_lookup (old_users, name); + + if (!stale_user || !user_get_cached (stale_user) && user_get_cached (user)) { + user_register (user); + accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), + user_get_object_path (user)); + } + g_object_thaw_notify (G_OBJECT (user)); + } + + g_hash_table_destroy (old_users); + } + + static gboolean + reload_users_timeout (Daemon *daemon) + { + reload_users (daemon); + daemon->priv->reload_id = 0; + +-- +2.17.0 + diff --git a/accountsservice.spec b/accountsservice.spec index 569af4c..75b25b4 100644 --- a/accountsservice.spec +++ b/accountsservice.spec @@ -2,7 +2,7 @@ Name: accountsservice Version: 0.6.47 -Release: 1%{?dist} +Release: 2%{?dist} Summary: D-Bus interfaces for querying and manipulating user account information License: GPLv3+ URL: https://www.freedesktop.org/wiki/Software/AccountsService/ @@ -23,6 +23,9 @@ Requires: polkit Requires: shadow-utils %{?systemd_requires} +Patch1: 0001-daemon-unregister-user-after-we-re-done-with-it-not-.patch +Patch2: 0002-daemon-don-t-emit-user-deleted-for-uncached-users.patch + %description The accountsservice project provides a set of D-Bus interfaces for querying and manipulating user account information and an implementation @@ -98,6 +101,10 @@ rm $RPM_BUILD_ROOT%{_libdir}/*.a %{_datadir}/gtk-doc/html/libaccountsservice/* %changelog +* Fri May 04 2018 Ray Strode - 0.6.47-2 +- fix crash on user deletion + Resolves: #1573550 + * Tue Apr 24 2018 Ray Strode - 0.6.47-1 - Update to 0.6.47