[packages/polkit] Rel 2; fix CVE-2026-4897 and CVE-2026-85498, agent session use-after-free
arekm
arekm at pld-linux.org
Wed Sep 16 08:46:39 CEST 2026
commit 7cef6aab61b36937890edb29f6ce046916ad7beb
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Wed Sep 16 08:11:49 2026 +0200
Rel 2; fix CVE-2026-4897 and CVE-2026-85498, agent session use-after-free
CVE-2026-4897.patch | 88 +++++++++++++++++++++++++++++++
CVE-2026-85498.patch | 34 ++++++++++++
polkit-agent-session-use-after-free.patch | 80 ++++++++++++++++++++++++++++
polkit.spec | 42 ++++++++++++---
4 files changed, 238 insertions(+), 6 deletions(-)
---
diff --git a/polkit.spec b/polkit.spec
index af22efe..63f270d 100644
--- a/polkit.spec
+++ b/polkit.spec
@@ -3,6 +3,7 @@
%bcond_without apidocs # build without apidocs
%bcond_without consolekit # ConsoleKit fallback
%bcond_without systemd # use systemd-login for session tracking (fallback to ConsoleKit on runtime)
+%bcond_without tests # test suite
%bcond_with elogind # use elogind instead of systemd-login
%if %{with elogind}
@@ -12,12 +13,15 @@ Summary: A framework for defining policy for system-wide components
Summary(pl.UTF-8): Szkielet do definiowania polityki dla komponentów systemowych
Name: polkit
Version: 127
-Release: 1
+Release: 2
License: LGPL v2+
Group: Libraries
Source0: https://github.com/polkit-org/polkit/archive/%{version}/%{name}-%{version}.tar.gz
# Source0-md5: 2cc95f1b02fc1de6c9e52db986642ec4
Patch0: systemd-fallback.patch
+Patch1: CVE-2026-4897.patch
+Patch2: CVE-2026-85498.patch
+Patch3: polkit-agent-session-use-after-free.patch
URL: https://github.com/polkit-org/polkit
BuildRequires: dbus-devel
BuildRequires: docbook-dtd412-xml
@@ -31,17 +35,28 @@ BuildRequires: glib2-devel >= 1:2.44.0
BuildRequires: glibc-localedb-all
%endif
BuildRequires: gobject-introspection-devel >= 0.6.2
-BuildRequires: gtk-doc >= 1.3
-BuildRequires: gtk-doc-automake >= 1.3
-BuildRequires: libstdc++-devel >= 6:7
+%{?with_apidocs:BuildRequires: gtk-doc >= 1.3}
BuildRequires: libxslt-progs
BuildRequires: meson >= 1.4.0
BuildRequires: ninja
BuildRequires: pam-devel >= 0.80
BuildRequires: pkgconfig
+%if %{with tests}
+BuildRequires: /bin/mount
+BuildRequires: python3-dbus
+BuildRequires: python3-dbusmock
+%endif
BuildRequires: rpm-build >= 4.6
BuildRequires: rpmbuild(macros) >= 2.042
%{?with_systemd:BuildRequires: systemd-devel}
+Requires(postun): /usr/sbin/groupdel
+Requires(postun): /usr/sbin/userdel
+Requires(pre): /bin/id
+Requires(pre): /usr/bin/getgid
+Requires(pre): /usr/lib/rpm/user_group.sh
+Requires(pre): /usr/sbin/groupadd
+Requires(pre): /usr/sbin/useradd
+Requires(pre): /usr/sbin/usermod
Requires: %{name}-libs = %{version}-%{release}
%if %{without systemd} && %{without elogind}
Requires: ConsoleKit >= 0.4.1
@@ -115,21 +130,29 @@ Pliki nagłówkowe PolicyKit.
%if %{with consolekit} && (%{with systemd} || %{with elogind})
%patch -P0 -p1
%endif
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
%build
%meson \
-Dgtk_doc=%{__true_false apidocs} \
- -Dtests=false \
+ -Dtests=%{__true_false tests} \
-Dsession_tracking=%{?with_systemd:logind}%{?with_elogind:elogind} \
-Dpam_include=system-auth \
-Dpam_module_dir=/%{_lib}/security \
-Dpolkitd_user=polkitd \
-Dpolkitd_uid=283 \
-Dexamples=true \
- -Dman=true
+ -Dman=true \
+ -Dgettext=true
%meson_build
+%if %{with tests}
+%meson_test
+%endif
+
%install
rm -rf $RPM_BUILD_ROOT
@@ -145,6 +168,13 @@ rm -rf $RPM_BUILD_ROOT
%useradd -u 283 -s /bin/false -c "polkitd pseudo user" -g polkitd polkitd
%addusertogroup polkitd proc
+%preun
+# The socket-activated helper needs SO_PEERPIDFD (kernel >= 6.5) and PolkitAgentSession
+# falls back to the setuid helper only when the connect fails, so on older kernels an
+# enabled socket breaks authentication outright; the socket is therefore never enabled
+# on install, only deregistered here. https://github.com/polkit-org/polkit/issues/639
+%{?with_systemd:%systemd_preun polkit-agent-helper.socket}
+
%postun
if [ "$1" = "0" ]; then
%userremove polkitd
diff --git a/CVE-2026-4897.patch b/CVE-2026-4897.patch
new file mode 100644
index 0000000..6cab4ea
--- /dev/null
+++ b/CVE-2026-4897.patch
@@ -0,0 +1,88 @@
+From 7e122c8a5120c2aae2d9d44a26796dc18f5b677c Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar at redhat.com>
+Date: Fri, 27 Mar 2026 15:57:01 +0100
+Subject: [PATCH] CVE-2026-4897 - getline() string overflow
+
+Report and fix by Aisle.com
+Pavel Kohout, Aisle Research
+
+Signed-off-by: Jan Rybar jrybar at redhat.com
+---
+ src/polkitagent/polkitagenthelperprivate.c | 23 +++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/src/polkitagent/polkitagenthelperprivate.c b/src/polkitagent/polkitagenthelperprivate.c
+index 35bca85a..7e4f94eb 100644
+--- a/src/polkitagent/polkitagenthelperprivate.c
++++ b/src/polkitagent/polkitagenthelperprivate.c
+@@ -24,6 +24,7 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <stdlib.h>
++#include <errno.h>
+ #include <unistd.h>
+
+ #ifndef HAVE_CLEARENV
+@@ -59,21 +60,25 @@ read_cookie (int argc, char **argv)
+ return strdup (argv[2]);
+ else
+ {
+- char *ret = NULL;
+- size_t n = 0;
+- ssize_t r = getline (&ret, &n, stdin);
+- if (r == -1)
++ #define POLKIT_AGENT_MAX_COOKIE 4096
++ char buf[POLKIT_AGENT_MAX_COOKIE + 2]; /* +1 for newline, +1 for NUL */
++ if (fgets (buf, sizeof(buf), stdin) == NULL)
+ {
+ if (!feof (stdin))
+- perror ("getline");
+- free (ret);
++ perror ("fgets");
+ return NULL;
+ }
+- else
++ if (buf[strlen (buf) - 1] != '\n')
+ {
+- g_strchomp (ret);
+- return ret;
++ /* Cookie too long - drain remaining input and reject */
++ int c;
++ while ((c = getchar ()) != '\n' && c != EOF)
++ ;
++ errno = EOVERFLOW;
++ return NULL;
+ }
++ g_strchomp (buf);
++ return strdup (buf);
+ }
+ }
+
+From 39601309eb3e5e88a1c1fbda9a272ba8691f1bf3 Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar at redhat.com>
+Date: Wed, 13 May 2026 14:58:32 +0200
+Subject: [PATCH] Draining loop can keep polkit busy
+
+The draining loop is not really appropriate for pipe input, especially
+in a daemon.
+
+Co-authored-by: Frantisek Sumsal <fsumsal at redhat.com>
+---
+ src/polkitagent/polkitagenthelperprivate.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/polkitagent/polkitagenthelperprivate.c b/src/polkitagent/polkitagenthelperprivate.c
+index 7e4f94eb..c0a98251 100644
+--- a/src/polkitagent/polkitagenthelperprivate.c
++++ b/src/polkitagent/polkitagenthelperprivate.c
+@@ -70,10 +70,6 @@ read_cookie (int argc, char **argv)
+ }
+ if (buf[strlen (buf) - 1] != '\n')
+ {
+- /* Cookie too long - drain remaining input and reject */
+- int c;
+- while ((c = getchar ()) != '\n' && c != EOF)
+- ;
+ errno = EOVERFLOW;
+ return NULL;
+ }
diff --git a/CVE-2026-85498.patch b/CVE-2026-85498.patch
new file mode 100644
index 0000000..e65006d
--- /dev/null
+++ b/CVE-2026-85498.patch
@@ -0,0 +1,34 @@
+From eea172967848bb4c5a407329f40c0e45de0d187e Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar at redhat.com>
+Date: Thu, 27 Aug 2026 15:02:45 +0200
+Subject: [PATCH] CVE-2026-85498: Unsanitized underflow in cookie input
+
+Credits for the report:
+Sunwoo Lee, Korea Institute of Energy Technology (KENTECH)
+Daeyoung Kang, Korea Institute of Energy Technology (KENTECH)
+Haeryong Park, Korea Internet & Security Agency (KISA)
+Hyuk Lim, Korea Institute of Energy Technology (KENTECH)
+Seunghyun Yoon, Korea Institute of Energy Technology (KENTECH)
+Juthawong Naisanguansee
+
+Co-authored-by: Jan Rybar <jrybar at redhat.com>
+---
+ src/polkitagent/polkitagenthelperprivate.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/polkitagent/polkitagenthelperprivate.c b/src/polkitagent/polkitagenthelperprivate.c
+index c0a98251..e2d2c9be 100644
+--- a/src/polkitagent/polkitagenthelperprivate.c
++++ b/src/polkitagent/polkitagenthelperprivate.c
+@@ -68,6 +68,11 @@ read_cookie (int argc, char **argv)
+ perror ("fgets");
+ return NULL;
+ }
++ if (buf[0] == '\0')
++ {
++ errno = EINVAL;
++ return NULL;
++ }
+ if (buf[strlen (buf) - 1] != '\n')
+ {
+ errno = EOVERFLOW;
diff --git a/polkit-agent-session-use-after-free.patch b/polkit-agent-session-use-after-free.patch
new file mode 100644
index 0000000..43e23a6
--- /dev/null
+++ b/polkit-agent-session-use-after-free.patch
@@ -0,0 +1,80 @@
+From 6f3cec7f1cfd2b0a686ce53e97e5351c80fe4f32 Mon Sep 17 00:00:00 2001
+From: Jan Rybar <jrybar at redhat.com>
+Date: Wed, 12 Aug 2026 13:27:31 +0200
+Subject: [PATCH] polkitagent: Fix use-after-free in io_watch_have_data()
+
+complete_session() emits the "completed" signal, and handlers of that
+signal are explicitly documented (and, in the case of
+PolkitAgentTextListener, actually implemented) to be allowed to drop
+the last reference to the PolkitAgentSession.
+
+io_watch_have_data() can call complete_session() once from one of its
+error/success branches and then unconditionally call it a second time
+from its epilogue whenever the dispatch also carries G_IO_ERR or
+G_IO_HUP. If the first call already caused the session to be freed via
+its "completed" handler, that second call operates on freed memory.
+
+Fix this by NULLing out the local session pointer right after each
+complete_session() call, and skipping the epilogue's call when it is
+already NULL, so we never dereference a session that may have already
+been freed.
+
+Co-authored-by: Cursor <cursoragent at cursor.com>
+---
+ src/polkitagent/polkitagentsession.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
+index bcf9e993..32b2a09b 100644
+--- a/src/polkitagent/polkitagentsession.c
++++ b/src/polkitagent/polkitagentsession.c
+@@ -444,6 +444,13 @@ io_watch_have_data (GIOChannel *channel,
+ g_warning ("in io_watch_have_data() but helper is not supposed to be running");
+
+ complete_session (session, FALSE);
++ /* complete_session() emits ::completed, and handlers of that signal
++ * are documented to be allowed to drop the last reference to
++ * @session (see e.g. PolkitAgentTextListener's handler). NULL out
++ * our local pointer so we can never call complete_session() again
++ * on a possibly-freed @session below.
++ */
++ session = NULL;
+ goto out;
+ }
+
+@@ -461,6 +468,7 @@ io_watch_have_data (GIOChannel *channel,
+ g_clear_error (&error);
+
+ complete_session (session, FALSE);
++ session = NULL;
+ goto out;
+ }
+
+@@ -504,15 +512,18 @@ io_watch_have_data (GIOChannel *channel,
+ else if (g_str_has_prefix (unescaped, "SUCCESS"))
+ {
+ complete_session (session, TRUE);
++ session = NULL;
+ }
+ else if (g_str_has_prefix (unescaped, "FAILURE"))
+ {
+ complete_session (session, FALSE);
++ session = NULL;
+ }
+ else
+ {
+ g_warning ("Unknown line '%s' from helper", line);
+ complete_session (session, FALSE);
++ session = NULL;
+ goto out;
+ }
+
+@@ -520,7 +531,7 @@ io_watch_have_data (GIOChannel *channel,
+ g_free (line);
+ g_free (unescaped);
+
+- if (condition & (G_IO_ERR | G_IO_HUP))
++ if (session != NULL && (condition & (G_IO_ERR | G_IO_HUP)))
+ complete_session (session, FALSE);
+
+ /* keep the IOChannel around */
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/polkit.git/commitdiff/d4979ac65926c0ffecf087b3c7ddb9bc37a260cc
More information about the pld-cvs-commit
mailing list