From 13dac52ebe3d511c9c986c47a1c1cbc35913745f Mon Sep 17 00:00:00 2001 From: Adrian Dombeck Date: Fri, 10 Jul 2026 17:13:34 +0200 Subject: [PATCH] pam/go-exec: keep PAM conversations on the caller context kscreenlocker handles PAM conversations on its Qt worker thread. Running the PAM action there lets the queued password response be processed, but the action also needs an isolated GLib context for its private D-Bus server. Restore the caller thread-default GLib context only while invoking the PAM conversation callback. This preserves the caller's callback semantics without binding unrelated application sources to authd's private D-Bus context. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- pam/go-exec/module.c | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/pam/go-exec/module.c b/pam/go-exec/module.c index 63523e4a22..e5866eb825 100644 --- a/pam/go-exec/module.c +++ b/pam/go-exec/module.c @@ -53,6 +53,7 @@ typedef struct _ActionData ModuleData *module_data; GMainLoop *loop; + GMainContext *caller_context; GDBusConnection *connection; GCancellable *cancellable; ActionType current_action; @@ -309,6 +310,7 @@ action_module_data_cleanup (ActionData *action_data) g_clear_object (&action_data->cancellable); g_clear_pointer (&action_data->loop, g_main_loop_unref); + g_clear_pointer (&action_data->caller_context, g_main_context_unref); g_clear_handle_id (&action_data->child_pid, g_spawn_close_pid); G_LOCK (logger); @@ -648,6 +650,7 @@ on_pam_method_call (GDBusConnection *connection, } else if (g_str_equal (method_name, "Prompt")) { + g_autoptr(GMainContextPusher) caller_context_pusher G_GNUC_UNUSED = NULL; g_autofree char *response = NULL; const char *prompt; int style; @@ -655,6 +658,9 @@ on_pam_method_call (GDBusConnection *connection, g_variant_get (parameters, "(i&s)", &style, &prompt); + /* PAM conversation callbacks belong to the calling application. */ + caller_context_pusher = + g_main_context_pusher_new (action_data->caller_context); ret = pam_prompt (pamh, style, &response, "%s", prompt); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(is)", ret, @@ -969,7 +975,8 @@ do_pam_action_thread (pam_handle_t *pamh, ActionType action, int flags, int argc, - const char **argv) + const char **argv, + GMainContext *caller_context) { ModuleData *module_data = NULL; g_autoptr(GMutexLocker) G_GNUC_UNUSED locker = NULL; @@ -1094,6 +1101,7 @@ do_pam_action_thread (pam_handle_t *pamh, action_data.module_data = module_data; action_data.cancellable = g_cancellable_new (); + action_data.caller_context = g_main_context_ref (caller_context); main_context = g_main_context_ref (module_data->main_context); context_pusher = g_main_context_pusher_new (main_context); @@ -1222,24 +1230,6 @@ do_pam_action_thread (pam_handle_t *pamh, return exit_status; } -typedef struct -{ - pam_handle_t *pamh; - ActionType action; - int flags; - int argc; - const char **argv; -} ActionThreadArgs; - -static inline gpointer -do_pam_action_thread_adapter (gpointer data) -{ - ActionThreadArgs * args = data; - return GINT_TO_POINTER (do_pam_action_thread (args->pamh, - args->action, args->flags, - args->argc, args->argv)); -} - static inline int do_pam_action (pam_handle_t *pamh, ActionType action, @@ -1247,7 +1237,7 @@ do_pam_action (pam_handle_t *pamh, int argc, const char **argv) { - g_autoptr(GThread) thread = NULL; + g_autoptr(GMainContext) caller_context = NULL; #ifndef AUTHD_TEST_EXEC_MODULE /* These actions aren't implemented in the go side, so let's just simplify @@ -1265,15 +1255,8 @@ do_pam_action (pam_handle_t *pamh, } #endif - thread = g_thread_new (action_type_to_string (action), - do_pam_action_thread_adapter, &(ActionThreadArgs){ - .pamh = pamh, - .action = action, - .flags = flags, - .argc = argc, - .argv = argv, - }); - return GPOINTER_TO_INT (g_thread_join (g_steal_pointer (&thread))); + caller_context = g_main_context_ref_thread_default (); + return do_pam_action_thread (pamh, action, flags, argc, argv, caller_context); } #define DEFINE_PAM_WRAPPER(name) \