...
 
Commits (6)
......@@ -148,10 +148,13 @@ POLKIT_UNIX_SESSION_GET_CLASS
PolkitUnixProcess
polkit_unix_process_new
polkit_unix_process_new_full
polkit_unix_process_new_for_owner
polkit_unix_process_set_pid
polkit_unix_process_get_pid
polkit_unix_process_set_start_time
polkit_unix_process_get_start_time
polkit_unix_process_set_pid
polkit_unix_process_get_owner
polkit_unix_process_set_uid
polkit_unix_process_get_uid
<SUBSECTION Standard>
PolkitUnixProcessClass
POLKIT_UNIX_PROCESS
......
......@@ -24,6 +24,7 @@
#endif
#include <string.h>
#include <stdio.h>
#include "polkitsubject.h"
#include "polkitunixprocess.h"
......@@ -209,8 +210,6 @@ polkit_subject_from_string (const gchar *str,
GError **error)
{
PolkitSubject *subject;
guint64 val;
gchar *endptr;
g_return_val_if_fail (str != NULL, NULL);
......@@ -220,12 +219,20 @@ polkit_subject_from_string (const gchar *str,
if (g_str_has_prefix (str, "unix-process:"))
{
val = g_ascii_strtoull (str + sizeof "unix-process:" - 1,
&endptr,
10);
if (*endptr == '\0')
gint scanned_pid;
guint64 scanned_starttime;
gint scanned_uid;
if (sscanf (str, "unix-process:%d:%" G_GUINT64_FORMAT ":%d", &scanned_pid, &scanned_starttime, &scanned_uid) == 3)
{
subject = polkit_unix_process_new ((gint) val);
subject = polkit_unix_process_new_for_owner (scanned_pid, scanned_starttime, scanned_uid);
}
else if (sscanf (str, "unix-process:%d:%" G_GUINT64_FORMAT, &scanned_pid, &scanned_starttime) == 2)
{
subject = polkit_unix_process_new_full (scanned_pid, scanned_starttime);
}
else if (sscanf (str, "unix-process:%d", &scanned_pid) == 1)
{
subject = polkit_unix_process_new (scanned_pid);
if (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) == 0)
{
g_object_unref (subject);
......@@ -233,8 +240,8 @@ polkit_subject_from_string (const gchar *str,
g_set_error (error,
POLKIT_ERROR,
POLKIT_ERROR_FAILED,
"No process with pid %" G_GUINT64_FORMAT,
val);
"Unable to determine start time for process with pid %d",
scanned_pid);
}
}
}
......@@ -268,6 +275,7 @@ polkit_subject_new_for_real (_PolkitSubject *real)
EggDBusHashMap *details;
EggDBusVariant *variant;
EggDBusVariant *variant2;
EggDBusVariant *variant3;
s = NULL;
......@@ -281,10 +289,24 @@ polkit_subject_new_for_real (_PolkitSubject *real)
else if (strcmp (kind, "unix-process") == 0)
{
variant = egg_dbus_hash_map_lookup (details, "pid");
variant2 = egg_dbus_hash_map_lookup (details, "start-time");
if (variant != NULL && variant2 != NULL)
s = polkit_unix_process_new_full (egg_dbus_variant_get_uint (variant),
egg_dbus_variant_get_uint64 (variant2));
if (variant != NULL && egg_dbus_variant_is_uint (variant))
{
gint pid;
guint64 start_time;
gint uid;
variant2 = egg_dbus_hash_map_lookup (details, "start-time");
pid = egg_dbus_variant_get_uint (variant);
if (variant2 != NULL && egg_dbus_variant_is_uint64 (variant2))
start_time = egg_dbus_variant_get_uint64 (variant2);
else
start_time = 0;
variant3 = egg_dbus_hash_map_lookup (details, "uid");
if (variant3 != NULL && egg_dbus_variant_is_int (variant3))
uid = egg_dbus_variant_get_int (variant3);
else
uid = -1;
s = polkit_unix_process_new_for_owner (pid, start_time, uid);
}
}
else if (strcmp (kind, "unix-session") == 0)
{
......@@ -330,6 +352,9 @@ polkit_subject_get_real (PolkitSubject *subject)
egg_dbus_hash_map_insert (details,
"start-time",
egg_dbus_variant_new_for_uint64 (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject))));
egg_dbus_hash_map_insert (details,
"uid",
egg_dbus_variant_new_for_int (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject))));
}
else if (POLKIT_IS_UNIX_SESSION (subject))
{
......
This diff is collapsed.
......@@ -50,11 +50,21 @@ GType polkit_unix_process_get_type (void) G_GNUC_CONST;
PolkitSubject *polkit_unix_process_new (gint pid);
PolkitSubject *polkit_unix_process_new_full (gint pid,
guint64 start_time);
PolkitSubject *polkit_unix_process_new_for_owner (gint pid,
guint64 start_time,
gint uid);
gint polkit_unix_process_get_pid (PolkitUnixProcess *process);
gint polkit_unix_process_get_uid (PolkitUnixProcess *process);
guint64 polkit_unix_process_get_start_time (PolkitUnixProcess *process);
void polkit_unix_process_set_pid (PolkitUnixProcess *process,
gint pid);
void polkit_unix_process_set_uid (PolkitUnixProcess *process,
gint uid);
void polkit_unix_process_set_start_time (PolkitUnixProcess *process,
guint64 start_time);
G_GNUC_DEPRECATED
gint polkit_unix_process_get_owner (PolkitUnixProcess *process,
GError **error);
......
......@@ -386,6 +386,7 @@ polkit_backend_config_source_ensure (PolkitBackendConfigSource *source)
}
source->priv->key_files = g_list_reverse (source->priv->key_files);
source->priv->has_data = TRUE;
out:
g_list_foreach (files, (GFunc) g_object_unref, NULL);
......
......@@ -641,6 +641,8 @@ polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorization
g_free (filename);
}
store->priv->has_data = TRUE;
out:
g_list_foreach (files, (GFunc) g_object_unref, NULL);
g_list_free (files);
......
......@@ -418,14 +418,13 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor
if (POLKIT_IS_UNIX_PROCESS (subject))
{
GError *local_error;
local_error = NULL;
uid = polkit_unix_process_get_owner (POLKIT_UNIX_PROCESS (subject), &local_error);
if (local_error != NULL)
uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject));
if ((gint) uid == -1)
{
g_propagate_error (error, local_error);
g_error_free (local_error);
g_set_error (error,
POLKIT_ERROR,
POLKIT_ERROR_FAILED,
"Unix process subject does not have uid set");
goto out;
}
user = polkit_unix_user_new (uid);
......
......@@ -38,6 +38,10 @@
#include <syslog.h>
#include <stdarg.h>
#ifdef __linux__
#include <sys/prctl.h>
#endif
#include <polkit/polkit.h>
static gchar *original_user_name = NULL;
......@@ -410,8 +414,6 @@ main (int argc, char *argv[])
GPtrArray *saved_env;
gchar *opt_user;
pid_t pid_of_caller;
uid_t uid_of_caller;
struct stat statbuf;
ret = 127;
authority = NULL;
......@@ -520,9 +522,9 @@ main (int argc, char *argv[])
g_free (path);
argv[n] = path = s;
}
if (stat (path, &statbuf) != 0)
if (access (path, F_OK) != 0)
{
g_printerr ("Error getting information about %s: %s\n", path, g_strerror (errno));
g_printerr ("Error accessing %s: %s\n", path, g_strerror (errno));
goto out;
}
command_line = g_strjoinv (" ", argv + n);
......@@ -579,40 +581,49 @@ main (int argc, char *argv[])
*/
g_type_init ();
/* now check if the program that invoked us is authorized */
/* make sure we are nuked if the parent process dies */
#ifdef __linux__
if (prctl (PR_SET_PDEATHSIG, SIGTERM) != 0)
{
g_printerr ("prctl(PR_SET_PDEATHSIG, SIGTERM) failed: %s\n", g_strerror (errno));
goto out;
}
#else
#warning "Please add OS specific code to catch when the parent dies"
#endif
/* Figure out the parent process */
pid_of_caller = getppid ();
if (pid_of_caller == 1)
{
/* getppid() can return 1 if the parent died (meaning that we are reaped
* by /sbin/init); get process group leader instead - for example, this
* happens when launching via gnome-panel (alt+f2, then 'pkexec gedit').
* by /sbin/init); In that case we simpy bail.
*/
pid_of_caller = getpgrp ();
}
subject = polkit_unix_process_new (pid_of_caller);
if (subject == NULL)
{
g_printerr ("No such process for pid %d: %s\n", (gint) pid_of_caller, error->message);
g_error_free (error);
g_printerr ("Refusing to render service to dead parents.\n");
goto out;
}
/* paranoia: check that the uid of pid_of_caller matches getuid() */
error = NULL;
uid_of_caller = polkit_unix_process_get_owner (POLKIT_UNIX_PROCESS (subject),
&error);
if (error != NULL)
{
g_printerr ("Error determing pid of caller (pid %d): %s\n", (gint) pid_of_caller, error->message);
g_error_free (error);
goto out;
}
if (uid_of_caller != getuid ())
{
g_printerr ("User of caller (%d) does not match our uid (%d)\n", uid_of_caller, getuid ());
goto out;
}
/* This process we want to check an authorization for is the process
* that launched us - our parent process.
*
* At the time the parent process fork()'ed and exec()'ed us, the
* process had the same real-uid that we have now. So we use this
* real-uid instead of of looking it up to avoid TOCTTOU issues
* (consider the parent process exec()'ing a setuid helper).
*
* On the other hand, the monotonic process start-time is guaranteed
* to never change so it's safe to look that up given only the PID
* since we are guaranteed to be nuked if the parent goes away
* (cf. the prctl(2) call above).
*/
subject = polkit_unix_process_new_for_owner (pid_of_caller,
0, /* 0 means "look up start-time in /proc" */
getuid ());
/* really double-check the invariants guaranteed by the PolkitUnixProcess class */
g_assert (subject != NULL);
g_assert (polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)) == pid_of_caller);
g_assert (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0);
g_assert (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) > 0);
authority = polkit_authority_get ();
......