summaryrefslogtreecommitdiffstats
path: root/source/l/polkit/CVE-2011-1485/0004-pkexec-Avoid-TOCTTOU-problems-with-parent-process.patch
diff options
context:
space:
mode:
Diffstat (limited to 'source/l/polkit/CVE-2011-1485/0004-pkexec-Avoid-TOCTTOU-problems-with-parent-process.patch')
-rw-r--r--source/l/polkit/CVE-2011-1485/0004-pkexec-Avoid-TOCTTOU-problems-with-parent-process.patch127
1 files changed, 127 insertions, 0 deletions
diff --git a/source/l/polkit/CVE-2011-1485/0004-pkexec-Avoid-TOCTTOU-problems-with-parent-process.patch b/source/l/polkit/CVE-2011-1485/0004-pkexec-Avoid-TOCTTOU-problems-with-parent-process.patch
new file mode 100644
index 000000000..8572f732d
--- /dev/null
+++ b/source/l/polkit/CVE-2011-1485/0004-pkexec-Avoid-TOCTTOU-problems-with-parent-process.patch
@@ -0,0 +1,127 @@
+From 3b12cfac29dddd27f1f166a7574d8374cc1dccf2 Mon Sep 17 00:00:00 2001
+From: David Zeuthen <davidz@redhat.com>
+Date: Fri, 1 Apr 2011 12:13:15 -0400
+Subject: [PATCH 4/4] pkexec: Avoid TOCTTOU problems with parent process
+
+In a nutshell, the parent process may change its uid (either real- or
+effective uid) after launching pkexec. It can do this by exec()'ing
+e.g. a setuid root program.
+
+To avoid this problem, just use the uid the parent process had when it
+executed pkexec. This happens to be the same uid of the pkexec process
+itself.
+
+Additionally, remove some dubious code that allowed pkexec to continue
+when the parent process died as there is no reason to support
+something like that. Also ensure that the pkexec process is killed if
+the parent process dies.
+
+This problem was pointed out by Neel Mehta <nmehta@google.com>.
+
+Signed-off-by: David Zeuthen <davidz@redhat.com>
+---
+ src/programs/pkexec.c | 66 +++++++++++++++++++++++++++++--------------------
+ 1 files changed, 39 insertions(+), 27 deletions(-)
+
+diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c
+index 9217954..3e656be 100644
+--- a/src/programs/pkexec.c
++++ b/src/programs/pkexec.c
+@@ -35,6 +35,10 @@
+ #include <pwd.h>
+ #include <errno.h>
+
++#ifdef __linux__
++#include <sys/prctl.h>
++#endif
++
+ #include <glib/gi18n.h>
+
+ #ifdef POLKIT_AUTHFW_PAM
+@@ -423,7 +427,6 @@ main (int argc, char *argv[])
+ GPtrArray *saved_env;
+ gchar *opt_user;
+ pid_t pid_of_caller;
+- uid_t uid_of_caller;
+ gpointer local_agent_handle;
+
+ ret = 127;
+@@ -598,40 +601,49 @@ main (int argc, char *argv[])
+ */
+ g_type_init ();
+
+- /* now check if the program that invoked us is authorized */
++ /* make sure we are nuked if the parent process dies */
++#ifdef __linux__
++ if (prctl (PR_SET_PDEATHSIG, SIGTERM) != 0)
++ {
++ g_printerr ("prctl(PR_SET_PDEATHSIG, SIGTERM) failed: %s\n", g_strerror (errno));
++ goto out;
++ }
++#else
++#warning "Please add OS specific code to catch when the parent dies"
++#endif
++
++ /* Figure out the parent process */
+ pid_of_caller = getppid ();
+ if (pid_of_caller == 1)
+ {
+ /* getppid() can return 1 if the parent died (meaning that we are reaped
+- * by /sbin/init); get process group leader instead - for example, this
+- * happens when launching via gnome-panel (alt+f2, then 'pkexec gedit').
++ * by /sbin/init); In that case we simpy bail.
+ */
+- pid_of_caller = getpgrp ();
+- }
+-
+- subject = polkit_unix_process_new (pid_of_caller);
+- if (subject == NULL)
+- {
+- g_printerr ("No such process for pid %d: %s\n", (gint) pid_of_caller, error->message);
+- g_error_free (error);
++ g_printerr ("Refusing to render service to dead parents.\n");
+ goto out;
+ }
+
+- /* paranoia: check that the uid of pid_of_caller matches getuid() */
+- error = NULL;
+- uid_of_caller = polkit_unix_process_get_owner (POLKIT_UNIX_PROCESS (subject),
+- &error);
+- if (error != NULL)
+- {
+- g_printerr ("Error determing pid of caller (pid %d): %s\n", (gint) pid_of_caller, error->message);
+- g_error_free (error);
+- goto out;
+- }
+- if (uid_of_caller != getuid ())
+- {
+- g_printerr ("User of caller (%d) does not match our uid (%d)\n", uid_of_caller, getuid ());
+- goto out;
+- }
++ /* This process we want to check an authorization for is the process
++ * that launched us - our parent process.
++ *
++ * At the time the parent process fork()'ed and exec()'ed us, the
++ * process had the same real-uid that we have now. So we use this
++ * real-uid instead of of looking it up to avoid TOCTTOU issues
++ * (consider the parent process exec()'ing a setuid helper).
++ *
++ * On the other hand, the monotonic process start-time is guaranteed
++ * to never change so it's safe to look that up given only the PID
++ * since we are guaranteed to be nuked if the parent goes away
++ * (cf. the prctl(2) call above).
++ */
++ subject = polkit_unix_process_new_for_owner (pid_of_caller,
++ 0, /* 0 means "look up start-time in /proc" */
++ getuid ());
++ /* really double-check the invariants guaranteed by the PolkitUnixProcess class */
++ g_assert (subject != NULL);
++ g_assert (polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)) == pid_of_caller);
++ g_assert (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0);
++ g_assert (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0);
+
+ error = NULL;
+ authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error);
+--
+1.7.4.4
+