From 7092c102f246085922f032f0fba2a89d0b02ba89 Mon Sep 17 00:00:00 2001 From: Jan Rybar Date: Mon, 20 May 2024 16:45:48 +0200 Subject: [PATCH] PolkitPermission re-check on real session changes Resolves: RHEL-34029 --- ...-0.115-pkperm-watch-real-ssn-changes.patch | 353 ++++++++++++++++++ polkit.spec | 7 +- 2 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 polkit-0.115-pkperm-watch-real-ssn-changes.patch diff --git a/polkit-0.115-pkperm-watch-real-ssn-changes.patch b/polkit-0.115-pkperm-watch-real-ssn-changes.patch new file mode 100644 index 0000000..0e58643 --- /dev/null +++ b/polkit-0.115-pkperm-watch-real-ssn-changes.patch @@ -0,0 +1,353 @@ +diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml +index 88da3c0..eea05ae 100644 +--- a/data/org.freedesktop.PolicyKit1.Authority.xml ++++ b/data/org.freedesktop.PolicyKit1.Authority.xml +@@ -431,7 +431,7 @@ Must match the effective UID of the caller of org.freedesktop.PolicyKit1.Authori + + + +- ++ + + + +diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c +index 71d527c..93691b6 100644 +--- a/src/polkit/polkitauthority.c ++++ b/src/polkit/polkitauthority.c +@@ -84,6 +84,7 @@ static PolkitAuthority *the_authority = NULL; + enum + { + CHANGED_SIGNAL, ++ SESSIONS_CHANGED_SIGNAL, + LAST_SIGNAL, + }; + +@@ -113,9 +114,19 @@ on_proxy_signal (GDBusProxy *proxy, + gpointer user_data) + { + PolkitAuthority *authority = POLKIT_AUTHORITY (user_data); ++ guint16 msg_mask; ++ + if (g_strcmp0 (signal_name, "Changed") == 0) + { +- g_signal_emit_by_name (authority, "changed"); ++ if ((parameters != NULL) && g_variant_check_format_string(parameters, "(q)", FALSE ) ) ++ { ++ g_variant_get(parameters, "(q)", &msg_mask); ++ g_signal_emit (authority, signals[msg_mask], 0); ++ } ++ else ++ { ++ g_signal_emit_by_name (authority, "changed"); ++ } + } + } + +@@ -287,6 +298,21 @@ polkit_authority_class_init (PolkitAuthorityClass *klass) + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); ++ /** ++ * PolkitAuthority::sessions-changed: ++ * @authority: A #PolkitAuthority. ++ * ++ * Emitted when sessions change ++ */ ++ signals[SESSIONS_CHANGED_SIGNAL] = g_signal_new ("sessions-changed", ++ POLKIT_TYPE_AUTHORITY, ++ G_SIGNAL_RUN_LAST, ++ 0, /* class offset */ ++ NULL, /* accumulator */ ++ NULL, /* accumulator data */ ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, ++ 0); + } + + /* ---------------------------------------------------------------------------------------------------- */ +diff --git a/src/polkit/polkitpermission.c b/src/polkit/polkitpermission.c +index f264094..3231bf2 100644 +--- a/src/polkit/polkitpermission.c ++++ b/src/polkit/polkitpermission.c +@@ -24,6 +24,10 @@ + # include "config.h" + #endif + ++#ifdef HAVE_LIBSYSTEMD ++# include ++#endif ++ + #include + #include + +@@ -60,6 +64,8 @@ struct _PolkitPermission + + gchar *action_id; + ++ gchar *session_state; ++ + /* non-NULL exactly when authorized with a temporary authorization */ + gchar *tmp_authz_id; + }; +@@ -74,9 +80,14 @@ enum + static void process_result (PolkitPermission *permission, + PolkitAuthorizationResult *result); + ++static char *get_session_state(); ++ + static void on_authority_changed (PolkitAuthority *authority, + gpointer user_data); + ++static void on_sessions_changed (PolkitAuthority *authority, ++ gpointer user_data); ++ + static gboolean acquire (GPermission *permission, + GCancellable *cancellable, + GError **error); +@@ -126,6 +137,8 @@ polkit_permission_constructed (GObject *object) + + if (G_OBJECT_CLASS (polkit_permission_parent_class)->constructed != NULL) + G_OBJECT_CLASS (polkit_permission_parent_class)->constructed (object); ++ ++ permission->session_state = get_session_state(); + } + + static void +@@ -135,11 +148,15 @@ polkit_permission_finalize (GObject *object) + + g_free (permission->action_id); + g_free (permission->tmp_authz_id); ++ g_free (permission->session_state); + g_object_unref (permission->subject); + + g_signal_handlers_disconnect_by_func (permission->authority, + on_authority_changed, + permission); ++ g_signal_handlers_disconnect_by_func (permission->authority, ++ on_sessions_changed, ++ permission); + g_object_unref (permission->authority); + + if (G_OBJECT_CLASS (polkit_permission_parent_class)->finalize != NULL) +@@ -417,6 +434,11 @@ polkit_permission_initable_init (GInitable *initable, + G_CALLBACK (on_authority_changed), + permission); + ++ g_signal_connect (permission->authority, ++ "sessions-changed", ++ G_CALLBACK (on_sessions_changed), ++ permission); ++ + result = polkit_authority_check_authorization_sync (permission->authority, + permission->subject, + permission->action_id, +@@ -469,6 +491,37 @@ changed_check_cb (GObject *source_object, + g_object_unref (permission); + } + ++static char *get_session_state() ++{ ++#ifdef HAVE_LIBSYSTEMD ++ char *session = NULL; ++ char *state = NULL; ++ uid_t uid; ++ ++ if ( sd_pid_get_session(getpid(), &session) < 0 ) ++ { ++ if ( sd_pid_get_owner_uid(getpid(), &uid) < 0) ++ { ++ goto out; ++ } ++ if (sd_uid_get_display(uid, &session) < 0) ++ { ++ goto out; ++ } ++ } ++ ++ if (session != NULL) ++ { ++ sd_session_get_state(session, &state); ++ } ++out: ++ g_free(session); ++ return state; ++#else ++ return NULL; ++#endif ++} ++ + static void + on_authority_changed (PolkitAuthority *authority, + gpointer user_data) +@@ -485,6 +538,40 @@ on_authority_changed (PolkitAuthority *authority, + g_object_ref (permission)); + } + ++ ++static void on_sessions_changed (PolkitAuthority *authority, ++ gpointer user_data) ++{ ++#ifdef HAVE_LIBSYSTEMD ++ char *new_session_state = NULL; ++ char *last_state = NULL; ++ ++ PolkitPermission *permission = POLKIT_PERMISSION (user_data); ++ ++ new_session_state = get_session_state(); ++ ++ /* if we cannot tell the session state, we should do CheckAuthorization anyway */ ++ if ((new_session_state == NULL) || ( g_strcmp0(new_session_state, permission->session_state) != 0 )) ++ { ++ last_state = permission->session_state; ++ permission->session_state = new_session_state; ++ g_free(last_state); ++ ++ polkit_authority_check_authorization (permission->authority, ++ permission->subject, ++ permission->action_id, ++ NULL, /* PolkitDetails */ ++ POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, ++ NULL /* cancellable */, ++ changed_check_cb, ++ g_object_ref (permission)); ++ } ++#else ++ on_authority_changed(authority, user_data); /* TODO: resolve the "too many session signals" issue for non-systemd systems later */ ++#endif ++} ++ ++ + static void + process_result (PolkitPermission *permission, + PolkitAuthorizationResult *result) +diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c +index 0d1fac4..6d21af9 100644 +--- a/src/polkitbackend/polkitbackendauthority.c ++++ b/src/polkitbackend/polkitbackendauthority.c +@@ -48,6 +48,7 @@ + enum + { + CHANGED_SIGNAL, ++ SESSIONS_CHANGED_SIGNAL, + LAST_SIGNAL, + }; + +@@ -78,6 +79,15 @@ polkit_backend_authority_class_init (PolkitBackendAuthorityClass *klass) + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); ++ signals[SESSIONS_CHANGED_SIGNAL] = g_signal_new ("sessions-changed", ++ POLKIT_BACKEND_TYPE_AUTHORITY, ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (PolkitBackendAuthorityClass, changed), ++ NULL, /* accumulator */ ++ NULL, /* accumulator data */ ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, ++ 0); + } + + /** +@@ -501,6 +511,8 @@ typedef struct + + gulong authority_changed_id; + ++ gulong authority_session_monitor_signaller; ++ + gchar *object_path; + + GHashTable *cancellation_id_to_check_auth_data; +@@ -523,6 +535,9 @@ server_free (Server *server) + if (server->authority != NULL && server->authority_changed_id > 0) + g_signal_handler_disconnect (server->authority, server->authority_changed_id); + ++ if (server->authority != NULL && server->authority_session_monitor_signaller > 0) ++ g_signal_handler_disconnect (server->authority, server->authority_session_monitor_signaller); ++ + if (server->cancellation_id_to_check_auth_data != NULL) + g_hash_table_unref (server->cancellation_id_to_check_auth_data); + +@@ -531,20 +546,23 @@ server_free (Server *server) + g_free (server); + } + +-static void +-on_authority_changed (PolkitBackendAuthority *authority, +- gpointer user_data) ++static void changed_dbus_call_handler(PolkitBackendAuthority *authority, ++ gpointer user_data, ++ guint16 msg_mask) + { + Server *server = user_data; + GError *error; ++ GVariant *parameters; + + error = NULL; ++ ++ parameters = g_variant_new("(q)", msg_mask); + if (!g_dbus_connection_emit_signal (server->connection, + NULL, /* destination bus name */ + server->object_path, + "org.freedesktop.PolicyKit1.Authority", + "Changed", +- NULL, ++ parameters, + &error)) + { + g_warning ("Error emitting Changed() signal: %s", error->message); +@@ -552,6 +570,29 @@ on_authority_changed (PolkitBackendAuthority *authority, + } + } + ++ ++static void ++on_authority_changed (PolkitBackendAuthority *authority, ++ gpointer user_data) ++{ ++ guint16 msg_mask = 0; ++ ++ msg_mask = (guint16) CHANGED_SIGNAL; ++ changed_dbus_call_handler(authority, user_data, msg_mask); ++} ++ ++ ++static void ++on_sessions_changed (PolkitBackendAuthority *authority, ++ gpointer user_data) ++{ ++ guint16 msg_mask = 0; ++ ++ msg_mask = (guint16) SESSIONS_CHANGED_SIGNAL; ++ changed_dbus_call_handler(authority, user_data, msg_mask); ++} ++ ++ + static const gchar *server_introspection_data = + "" + " " +@@ -1397,6 +1438,11 @@ polkit_backend_authority_register (PolkitBackendAuthority *authority, + G_CALLBACK (on_authority_changed), + server); + ++ server->authority_session_monitor_signaller = g_signal_connect (server->authority, ++ "sessions-changed", ++ G_CALLBACK (on_sessions_changed), ++ server); ++ + return server; + + error: +diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c +index 08d439e..40376dd 100644 +--- a/src/polkitbackend/polkitbackendinteractiveauthority.c ++++ b/src/polkitbackend/polkitbackendinteractiveauthority.c +@@ -284,7 +284,7 @@ on_session_monitor_changed (PolkitBackendSessionMonitor *monitor, + gpointer user_data) + { + PolkitBackendInteractiveAuthority *authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (user_data); +- g_signal_emit_by_name (authority, "changed"); ++ g_signal_emit_by_name (authority, "sessions-changed"); + } + + static void diff --git a/polkit.spec b/polkit.spec index a164619..498e70f 100644 --- a/polkit.spec +++ b/polkit.spec @@ -6,7 +6,7 @@ Summary: An authorization framework Name: polkit Version: 0.115 -Release: 15%{?dist}.1 +Release: 15%{?dist}.2 License: LGPLv2+ URL: http://www.freedesktop.org/wiki/Software/polkit Source0: http://www.freedesktop.org/software/polkit/releases/%{name}-%{version}.tar.gz @@ -30,6 +30,7 @@ Patch13: polkit-0.115-CVE-2021-4034.patch Patch14: polkit-0.115-CVE-2021-4115.patch Patch15: polkit-0.115-tty-flags-restore-if-changed.patch Patch16: polkit-0.115-session-monitor-watch-sessions-only.patch +Patch17: polkit-0.115-pkperm-watch-real-ssn-changes.patch BuildRequires: gcc-c++ @@ -196,6 +197,10 @@ exit 0 %{_libdir}/girepository-1.0/*.typelib %changelog +* Mon May 20 2024 Jan Rybar - 0.115-15.2 +- PolkitPermission re-check on real session changes +- Resolves: RHEL-34029 + * Mon Apr 22 2024 Jan Rybar - 0.115-15.1 - reduce waking session monitor on uninteresting session changes - make polkit-pkla-compat uninstallable (for cases when no .pkla on system)