summaryrefslogtreecommitdiff
path: root/source/l/polkit/CVE-2011-1485/0001-PolkitUnixProcess-Clarify-that-the-real-uid-is-retur.patch
blob: 9431056bc1749051437533ef5a09f4ec70c36cb5 (plain)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
From dd848a42a64a3b22a0cc60f6657b56ce9b6010ae Mon Sep 17 00:00:00 2001
From: David Zeuthen <davidz@redhat.com>
Date: Thu, 31 Mar 2011 12:59:09 -0400
Subject: [PATCH 1/4] 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 |   66 ++++++++++++++++++++++++++++++----------
 1 files changed, 50 insertions(+), 16 deletions(-)

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;
 }
 
-- 
1.7.4.4