summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2011-04-11 11:38:22 -0400
committerDavid Zeuthen <davidz@redhat.com>2011-04-11 11:38:22 -0400
commit83a65f1255fc3eebfb4be1f80a5ab0b5f98eef7c (patch)
tree5cab0f63712a48fc1fb21cc34a65afba5eb14cce
parent83f280620c9f4f5a3021994f35b9c3baf193231c (diff)
downloadpolkit-83a65f1255fc3eebfb4be1f80a5ab0b5f98eef7c.tar.gz
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>
-rw-r--r--src/polkit/polkitunixprocess.c58
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;
}