summaryrefslogtreecommitdiffstats
path: root/patches/source/polkit/CVE-2011-1485/0001-PolkitUnixProcess-Clarify-that-the-real-uid-is-retur.patch
blob: e448ce953949bb89337c30d92a62877b88f60e2e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
From 83a65f1255fc3eebfb4be1f80a5ab0b5f98eef7c Mon Sep 17 00:00:00 2001
From: David Zeuthen <davidz@redhat.com>
Date: Mon, 11 Apr 2011 11:38:22 -0400
Subject: [PATCH 1/6] 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>
---
 src/polkit/polkitunixprocess.c |   58 ++++++++++++++++++++++++++++++++-------
 1 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c
index e132387..868e3c5 100644
--- a/src/polkit/polkitunixprocess.c
+++ b/src/polkit/polkitunixprocess.c
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <stdio.h>
 
 #include "polkitunixprocess.h"
 #include "polkitsubject.h"
@@ -207,6 +208,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
@@ -214,14 +217,18 @@ 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
 
   result = 0;
+  lines = NULL;
+  contents = NULL;
 
 #ifdef HAVE_FREEBSD
   if (get_kinfo_proc (process->pid, &p) == 0)
@@ -237,22 +244,51 @@ 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:
+  g_strfreev (lines);
+  g_free (contents);
 
   return result;
 }
-- 
1.7.4.4