Accessing gnome-keyring on first login is broken with systemd, apps relying on a working keyring just hang or show errors. This is a known bug since 2023 [1] with multiple open merge requests to fix the bug [2][3][4]. Both Debian and Fedora have patched their packages to ship a workaround [5][6]. From the available patches I've decided to use the one from Debian [4], because I didn't see [2] being used in another distribution and [3] doesn't seem to be as technically correct according to [7]. I've also tried to reproduce this problem with OpenRC, but it doesn't happen there. Hence not applying the patch to Alpine. [1]: https://gitlab.gnome.org/GNOME/gnome-keyring/-/work_items/137 [2]: https://gitlab.gnome.org/GNOME/gnome-keyring/-/merge_requests/69 [3]: https://gitlab.gnome.org/GNOME/gnome-keyring/-/merge_requests/78 [4]: https://gitlab.gnome.org/GNOME/gnome-keyring/-/merge_requests/99 [5]: https://src.fedoraproject.org/rpms/gnome-keyring/blob/rawhide/f/78.patch [6]: https://salsa.debian.org/gnome-team/gnome-keyring/-/blob/debian/latest/debian/patches/gkd-login-Register-the-login-collection-on-dbus-on-creati.patch [7]: https://gitlab.gnome.org/GNOME/gnome-keyring/-/merge_requests/78#note_2567002 Fixes: #3496 Signed-off-by: Oliver Smith <ollieparanoid@postmarketos.org> Part-of: <https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/8587>
235 lines
7.5 KiB
Diff
235 lines
7.5 KiB
Diff
From c9c1bbc151d6adb61d18a6a93b3e08a7c5b641d4 Mon Sep 17 00:00:00 2001
|
|
From: Alessandro Astone <alessandro.astone@canonical.com>
|
|
Date: Fri, 3 Oct 2025 12:40:07 +0200
|
|
Subject: [PATCH] gkd-login: Register the login collection on dbus on creation
|
|
|
|
The 'login' keyring created on the first user log-in was not properly exposed
|
|
on the dbus org.freedesktop.secrets service.
|
|
|
|
It would be listed in the org.freedesktop.Secret.Service.Collections property
|
|
as /org/freedesktop/secrets/collection/login, but no object was actually
|
|
exported at that path.
|
|
|
|
Link: https://gitlab.gnome.org/GNOME/gnome-keyring/-/merge_requests/99
|
|
Closes: https://gitlab.gnome.org/GNOME/gnome-keyring/-/issues/137
|
|
Closes: https://gitlab.gnome.org/GNOME/gnome-keyring/-/issues/151
|
|
---
|
|
daemon/dbus/gkd-secret-service.c | 37 +++++++++++++++++++
|
|
daemon/login/gkd-login-context.c | 61 ++++++++++++++++++++++++++++++++
|
|
daemon/login/gkd-login-context.h | 17 +++++++++
|
|
daemon/login/gkd-login.c | 10 +++++-
|
|
daemon/login/meson.build | 1 +
|
|
5 files changed, 125 insertions(+), 1 deletion(-)
|
|
create mode 100644 daemon/login/gkd-login-context.c
|
|
create mode 100644 daemon/login/gkd-login-context.h
|
|
|
|
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
|
|
index 7a445815..0ebdf944 100644
|
|
--- a/daemon/dbus/gkd-secret-service.c
|
|
+++ b/daemon/dbus/gkd-secret-service.c
|
|
@@ -39,6 +39,8 @@
|
|
#include "gkd-internal-generated.h"
|
|
#include "gkd-secrets-generated.h"
|
|
|
|
+#include "daemon/login/gkd-login-context.h"
|
|
+
|
|
#include "egg/egg-error.h"
|
|
#include "egg/egg-unix-credentials.h"
|
|
|
|
@@ -938,6 +940,33 @@ service_name_owner_changed (GDBusConnection *connection,
|
|
g_hash_table_remove (self->clients, object_name);
|
|
}
|
|
|
|
+static void
|
|
+on_login_keyring_created (GkdLoginContext *context,
|
|
+ GckObject *keyring,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ GkdSecretService *self = GKD_SECRET_SERVICE (user_data);
|
|
+ gsize n_identifier;
|
|
+ char *identifier;
|
|
+ char *path;
|
|
+ GError *error = NULL;
|
|
+
|
|
+ g_debug ("intercepted new login keyring, registering on dbus");
|
|
+
|
|
+ identifier = gck_object_get_data (keyring, CKA_ID, NULL, &n_identifier, &error);
|
|
+ if (identifier == NULL) {
|
|
+ g_warning ("couldn't get login keyring identifier: %s", error->message);
|
|
+ g_clear_error (&error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ path = gkd_secret_util_build_path (SECRET_COLLECTION_PREFIX, identifier, n_identifier);
|
|
+ gkd_secret_service_emit_collection_created (self, path);
|
|
+
|
|
+ g_free (path);
|
|
+ g_free (identifier);
|
|
+}
|
|
+
|
|
/* -----------------------------------------------------------------------------
|
|
* OBJECT
|
|
*/
|
|
@@ -974,6 +1003,7 @@ gkd_secret_service_constructor (GType type,
|
|
GError *error = NULL;
|
|
GckSlot *slot = NULL;
|
|
guint i;
|
|
+ GkdLoginContext *login_ctx;
|
|
|
|
g_return_val_if_fail (self, NULL);
|
|
g_return_val_if_fail (self->connection, NULL);
|
|
@@ -1055,6 +1085,13 @@ gkd_secret_service_constructor (GType type,
|
|
|
|
gkd_secret_service_init_collections (self);
|
|
|
|
+ login_ctx = gkd_login_context_get_default ();
|
|
+ g_signal_connect_object (login_ctx,
|
|
+ "keyring-created",
|
|
+ G_CALLBACK (on_login_keyring_created),
|
|
+ self,
|
|
+ G_CONNECT_DEFAULT);
|
|
+
|
|
return G_OBJECT (self);
|
|
}
|
|
|
|
diff --git a/daemon/login/gkd-login-context.c b/daemon/login/gkd-login-context.c
|
|
new file mode 100644
|
|
index 00000000..926a2e26
|
|
--- /dev/null
|
|
+++ b/daemon/login/gkd-login-context.c
|
|
@@ -0,0 +1,61 @@
|
|
+#include "config.h"
|
|
+#include "gkd-login-context.h"
|
|
+
|
|
+struct _GkdLoginContext {
|
|
+ GObject parent_instance;
|
|
+};
|
|
+
|
|
+enum {
|
|
+ KEYRING_CREATED,
|
|
+ LAST_SIGNAL
|
|
+};
|
|
+
|
|
+static guint signals[LAST_SIGNAL] = { 0 };
|
|
+
|
|
+G_DEFINE_TYPE (GkdLoginContext, gkd_login_context, G_TYPE_OBJECT)
|
|
+
|
|
+static void
|
|
+gkd_login_context_class_init (GkdLoginContextClass *klass)
|
|
+{
|
|
+ /* * keyring-created signal:
|
|
+ * Emitted when the login keyring is successfully created on disk/in the store.
|
|
+ * Passes the GckObject representing the keyring so subscribers can use it.
|
|
+ */
|
|
+ signals[KEYRING_CREATED] = g_signal_new ("keyring-created",
|
|
+ GKD_TYPE_LOGIN_CONTEXT,
|
|
+ G_SIGNAL_RUN_LAST,
|
|
+ 0,
|
|
+ NULL, NULL,
|
|
+ g_cclosure_marshal_VOID__OBJECT,
|
|
+ G_TYPE_NONE,
|
|
+ 1, GCK_TYPE_OBJECT);
|
|
+}
|
|
+
|
|
+static void
|
|
+gkd_login_context_init (GkdLoginContext *self)
|
|
+{
|
|
+}
|
|
+
|
|
+GkdLoginContext *
|
|
+gkd_login_context_get_default (void)
|
|
+{
|
|
+ static GkdLoginContext *default_login_context = NULL;
|
|
+
|
|
+ if (g_once_init_enter_pointer (&default_login_context)) {
|
|
+ GkdLoginContext *context = g_object_new (GKD_TYPE_LOGIN_CONTEXT, NULL);
|
|
+
|
|
+ g_once_init_leave_pointer (&default_login_context, context);
|
|
+ }
|
|
+
|
|
+ return default_login_context;
|
|
+}
|
|
+
|
|
+void
|
|
+gkd_login_context_emit_keyring_created (GkdLoginContext *self,
|
|
+ GckObject *keyring)
|
|
+{
|
|
+ g_return_if_fail (GKD_IS_LOGIN_CONTEXT (self));
|
|
+ g_return_if_fail (GCK_IS_OBJECT (keyring));
|
|
+
|
|
+ g_signal_emit (self, signals[KEYRING_CREATED], 0, keyring);
|
|
+}
|
|
diff --git a/daemon/login/gkd-login-context.h b/daemon/login/gkd-login-context.h
|
|
new file mode 100644
|
|
index 00000000..a4bee57f
|
|
--- /dev/null
|
|
+++ b/daemon/login/gkd-login-context.h
|
|
@@ -0,0 +1,17 @@
|
|
+#ifndef GKD_LOGIN_CONTEXT_H
|
|
+#define GKD_LOGIN_CONTEXT_H
|
|
+
|
|
+#include <glib-object.h>
|
|
+#include <gck/gck.h>
|
|
+
|
|
+#define GKD_TYPE_LOGIN_CONTEXT (gkd_login_context_get_type ())
|
|
+G_DECLARE_FINAL_TYPE (GkdLoginContext, gkd_login_context, GKD, LOGIN_CONTEXT, GObject)
|
|
+
|
|
+/* Singleton accessor */
|
|
+GkdLoginContext * gkd_login_context_get_default (void);
|
|
+
|
|
+/* Trigger to be called by gkd-login.c when the keyring is ready */
|
|
+void gkd_login_context_emit_keyring_created (GkdLoginContext *self,
|
|
+ GckObject *keyring);
|
|
+
|
|
+#endif /* GKD_LOGIN_CONTEXT_H */
|
|
diff --git a/daemon/login/gkd-login.c b/daemon/login/gkd-login.c
|
|
index 855f5c3a..9225fdb9 100644
|
|
--- a/daemon/login/gkd-login.c
|
|
+++ b/daemon/login/gkd-login.c
|
|
@@ -21,6 +21,7 @@
|
|
#include "config.h"
|
|
|
|
#include "gkd-login.h"
|
|
+#include "gkd-login-context.h"
|
|
|
|
#include "daemon/gkd-pkcs11.h"
|
|
|
|
@@ -149,6 +150,8 @@ static GckObject*
|
|
create_login_keyring (GckSession *session, GckObject *cred, GError **error)
|
|
{
|
|
GckBuilder builder = GCK_BUILDER_INIT;
|
|
+ GckObject *collection;
|
|
+ GkdLoginContext *context;
|
|
|
|
g_return_val_if_fail (GCK_IS_SESSION (session), NULL);
|
|
g_return_val_if_fail (GCK_IS_OBJECT (cred), NULL);
|
|
@@ -161,7 +164,12 @@ create_login_keyring (GckSession *session, GckObject *cred, GError **error)
|
|
/* TRANSLATORS: This is the display label for the login keyring */
|
|
gck_builder_add_string (&builder, CKA_LABEL, _("Login"));
|
|
|
|
- return gck_session_create_object (session, gck_builder_end (&builder), NULL, error);
|
|
+ context = gkd_login_context_get_default ();
|
|
+ collection = gck_session_create_object (session, gck_builder_end (&builder), NULL, error);
|
|
+ if (collection)
|
|
+ gkd_login_context_emit_keyring_created (context, collection);
|
|
+
|
|
+ return collection;
|
|
}
|
|
|
|
static GckObject*
|
|
diff --git a/daemon/login/meson.build b/daemon/login/meson.build
|
|
index e56b6505..63ceb717 100644
|
|
--- a/daemon/login/meson.build
|
|
+++ b/daemon/login/meson.build
|
|
@@ -2,6 +2,7 @@ libgkd_login_sources = files(
|
|
'gkd-login.c',
|
|
'gkd-login-interaction.c',
|
|
'gkd-login-password.c',
|
|
+ 'gkd-login-context.c',
|
|
)
|
|
|
|
libgkd_login_deps = [
|
|
--
|
|
2.54.0
|
|
|