polkit/polkit-CVE-2011-1485-1.patch

135 lines
3.7 KiB
Diff

From dd848a42a64a3b22a0cc60f6657b56ce9b6010ae Mon Sep 17 00:00:00 2001
From: David Zeuthen <davidz@redhat.com>
Date: Thu, 31 Mar 2011 16:59:09 +0000
Subject: PolkitUnixProcess: Clarify that the real uid is returned, not the effective one
On Linux, also switch to parsing /proc/<pid>/status instead of relying
on the st_uid returned by stat(2) to be the uid we want.
This was pointed out by Neel Mehta <nmehta@google.com>. Thanks!
Signed-off-by: David Zeuthen <davidz@redhat.com>
---
diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c
index d95a1d4..876da69 100644
--- a/src/polkit/polkitunixprocess.c
+++ b/src/polkit/polkitunixprocess.c
@@ -24,9 +24,7 @@
#endif
#include <sys/types.h>
-#ifndef HAVE_FREEBSD
-#include <sys/stat.h>
-#else
+#ifdef HAVE_FREEBSD
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
@@ -34,6 +32,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <stdio.h>
#include "polkitunixprocess.h"
#include "polkitsubject.h"
@@ -208,6 +207,8 @@ polkit_unix_process_get_pid (PolkitUnixProcess *process)
*
* Gets the uid of the owner of @process.
*
+ * Note that this returns the real user-id (not the effective user-id) of @process.
+ *
* Returns: The UNIX user id of the owner for @process or 0 if @error is set.
**/
gint
@@ -215,17 +216,21 @@ polkit_unix_process_get_owner (PolkitUnixProcess *process,
GError **error)
{
gint result;
+ gchar *contents;
+ gchar **lines;
#ifdef HAVE_FREEBSD
struct kinfo_proc p;
#else
- struct stat statbuf;
- char procbuf[32];
+ gchar filename[64];
+ guint n;
#endif
g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), 0);
g_return_val_if_fail (error == NULL || *error == NULL, 0);
result = 0;
+ lines = NULL;
+ contents = NULL;
#ifdef HAVE_FREEBSD
if (get_kinfo_proc (process->pid, &p) == 0)
@@ -241,23 +246,52 @@ polkit_unix_process_get_owner (PolkitUnixProcess *process,
result = p.ki_uid;
#else
- g_snprintf (procbuf, sizeof procbuf, "/proc/%d", process->pid);
- if (stat (procbuf, &statbuf) != 0)
+
+ /* see 'man proc' for layout of the status file
+ *
+ * Uid, Gid: Real, effective, saved set, and file system UIDs (GIDs).
+ */
+ g_snprintf (filename, sizeof filename, "/proc/%d/status", process->pid);
+ if (!g_file_get_contents (filename,
+ &contents,
+ NULL,
+ error))
{
- g_set_error (error,
- POLKIT_ERROR,
- POLKIT_ERROR_FAILED,
- "stat() failed for /proc/%d: %s",
- process->pid,
- g_strerror (errno));
goto out;
}
+ lines = g_strsplit (contents, "\n", -1);
+ for (n = 0; lines != NULL && lines[n] != NULL; n++)
+ {
+ gint real_uid, effective_uid;
+ if (!g_str_has_prefix (lines[n], "Uid:"))
+ continue;
+ if (sscanf (lines[n] + 4, "%d %d", &real_uid, &effective_uid) != 2)
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Unexpected line `%s' in file %s",
+ lines[n],
+ filename);
+ goto out;
+ }
+ else
+ {
+ result = real_uid;
+ goto out;
+ }
+ }
- result = statbuf.st_uid;
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Didn't find any line starting with `Uid:' in file %s",
+ filename);
#endif
- out:
-
+out:
+ g_strfreev (lines);
+ g_free (contents);
return result;
}
--
cgit v0.8.3-6-g21f6