From dd848a42a64a3b22a0cc60f6657b56ce9b6010ae Mon Sep 17 00:00:00 2001 From: David Zeuthen 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//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 . Thanks! Signed-off-by: David Zeuthen --- 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 -#ifndef HAVE_FREEBSD -#include -#else +#ifdef HAVE_FREEBSD #include #include #include @@ -34,6 +32,7 @@ #include #include #include +#include #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