diff options
| -rw-r--r-- | abs/extra/polkit/CVE-2011-1485.patch | 908 | ||||
| -rw-r--r-- | abs/extra/polkit/PKGBUILD | 23 | ||||
| -rw-r--r-- | abs/extra/polkit/systemd-fallback.patch | 1571 | 
3 files changed, 1583 insertions, 919 deletions
| diff --git a/abs/extra/polkit/CVE-2011-1485.patch b/abs/extra/polkit/CVE-2011-1485.patch deleted file mode 100644 index f7054a6..0000000 --- a/abs/extra/polkit/CVE-2011-1485.patch +++ /dev/null @@ -1,908 +0,0 @@ -From dd848a42a64a3b22a0cc60f6657b56ce9b6010ae Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -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/<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> ---- -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; - } -  --- -cgit v0.8.3-6-g21f6 -From 129b6223a19e7fb2753f8cad7957ac5402394076 Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Fri, 01 Apr 2011 16:09:45 +0000 -Subject: Make PolkitUnixProcess also record the uid of the process - -This is needed to avoid possible TOCTTOU issues since a process can -change both its real uid and effective uid. - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt -index 12141e3..9f4fcf8 100644 ---- a/docs/polkit/polkit-1-sections.txt -+++ b/docs/polkit/polkit-1-sections.txt -@@ -145,10 +145,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 -diff --git a/src/polkit/polkitsubject.c b/src/polkit/polkitsubject.c -index 577afec..d2c4c20 100644 ---- a/src/polkit/polkitsubject.c -+++ b/src/polkit/polkitsubject.c -@@ -238,13 +238,18 @@ polkit_subject_from_string  (const gchar   *str, -     { -       gint scanned_pid; -       guint64 scanned_starttime; --      if (sscanf (str, "unix-process:%d:%" G_GUINT64_FORMAT, &scanned_pid, &scanned_starttime) == 2) -+      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_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_full (scanned_pid, 0); -+          subject = polkit_unix_process_new (scanned_pid); -           if (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)) == 0) -             { -               g_object_unref (subject); -@@ -297,6 +302,8 @@ polkit_subject_to_gvariant (PolkitSubject *subject) -                              g_variant_new_uint32 (polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)))); -       g_variant_builder_add (&builder, "{sv}", "start-time", -                              g_variant_new_uint64 (polkit_unix_process_get_start_time (POLKIT_UNIX_PROCESS (subject)))); -+      g_variant_builder_add (&builder, "{sv}", "uid", -+                             g_variant_new_int32 (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)))); -     } -   else if (POLKIT_IS_UNIX_SESSION (subject)) -     { -@@ -395,6 +402,7 @@ polkit_subject_new_for_gvariant (GVariant  *variant, -       GVariant *v; -       guint32 pid; -       guint64 start_time; -+      gint32 uid; -  -       v = lookup_asv (details_gvariant, "pid", G_VARIANT_TYPE_UINT32, error); -       if (v == NULL) -@@ -414,7 +422,18 @@ polkit_subject_new_for_gvariant (GVariant  *variant, -       start_time = g_variant_get_uint64 (v); -       g_variant_unref (v); -  --      ret = polkit_unix_process_new_full (pid, start_time); -+      v = lookup_asv (details_gvariant, "uid", G_VARIANT_TYPE_INT32, error); -+      if (v != NULL) -+        { -+          uid = g_variant_get_int32 (v); -+          g_variant_unref (v); -+        } -+      else -+        { -+          uid = -1; -+        } -+ -+      ret = polkit_unix_process_new_for_owner (pid, start_time, uid); -     } -   else if (g_strcmp0 (kind, "unix-session") == 0) -     { -diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c -index 876da69..913be3a 100644 ---- a/src/polkit/polkitunixprocess.c -+++ b/src/polkit/polkitunixprocess.c -@@ -62,6 +62,7 @@ struct _PolkitUnixProcess -  -   gint pid; -   guint64 start_time; -+  gint uid; - }; -  - struct _PolkitUnixProcessClass -@@ -74,6 +75,7 @@ enum -   PROP_0, -   PROP_PID, -   PROP_START_TIME, -+  PROP_UID - }; -  - static void subject_iface_init (PolkitSubjectIface *subject_iface); -@@ -81,6 +83,9 @@ static void subject_iface_init (PolkitSubjectIface *subject_iface); - static guint64 get_start_time_for_pid (gint    pid, -                                        GError **error); -  -+static gint _polkit_unix_process_get_owner (PolkitUnixProcess  *process, -+                                            GError            **error); -+ - #ifdef HAVE_FREEBSD - static gboolean get_kinfo_proc (gint pid, struct kinfo_proc *p); - #endif -@@ -92,6 +97,7 @@ G_DEFINE_TYPE_WITH_CODE (PolkitUnixProcess, polkit_unix_process, G_TYPE_OBJECT, - static void - polkit_unix_process_init (PolkitUnixProcess *unix_process) - { -+  unix_process->uid = -1; - } -  - static void -@@ -108,6 +114,10 @@ polkit_unix_process_get_property (GObject    *object, -       g_value_set_int (value, unix_process->pid); -       break; -  -+    case PROP_UID: -+      g_value_set_int (value, unix_process->uid); -+      break; -+ -     case PROP_START_TIME: -       g_value_set_uint64 (value, unix_process->start_time); -       break; -@@ -132,6 +142,14 @@ polkit_unix_process_set_property (GObject      *object, -       polkit_unix_process_set_pid (unix_process, g_value_get_int (value)); -       break; -  -+    case PROP_UID: -+      polkit_unix_process_set_uid (unix_process, g_value_get_int (value)); -+      break; -+ -+    case PROP_START_TIME: -+      polkit_unix_process_set_start_time (unix_process, g_value_get_uint64 (value)); -+      break; -+ -     default: -       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); -       break; -@@ -139,12 +157,39 @@ polkit_unix_process_set_property (GObject      *object, - } -  - static void -+polkit_unix_process_constructed (GObject *object) -+{ -+  PolkitUnixProcess *process = POLKIT_UNIX_PROCESS (object); -+ -+  /* sets start_time and uid in case they are unset */ -+ -+  if (process->start_time == 0) -+    process->start_time = get_start_time_for_pid (process->pid, NULL); -+ -+  if (process->uid == -1) -+    { -+      GError *error; -+      error = NULL; -+      process->uid = _polkit_unix_process_get_owner (process, &error); -+      if (error != NULL) -+        { -+          process->uid = -1; -+          g_error_free (error); -+        } -+    } -+ -+  if (G_OBJECT_CLASS (polkit_unix_process_parent_class)->constructed != NULL) -+    G_OBJECT_CLASS (polkit_unix_process_parent_class)->constructed (object); -+} -+ -+static void - polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - { -   GObjectClass *gobject_class = G_OBJECT_CLASS (klass); -  -   gobject_class->get_property = polkit_unix_process_get_property; -   gobject_class->set_property = polkit_unix_process_set_property; -+  gobject_class->constructed =  polkit_unix_process_constructed; -  -   /** -    * PolkitUnixProcess:pid: -@@ -156,7 +201,7 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) -                                    g_param_spec_int ("pid", -                                                      "Process ID", -                                                      "The UNIX process ID", --                                                     -1, -+                                                     0, -                                                      G_MAXINT, -                                                      0, -                                                      G_PARAM_CONSTRUCT | -@@ -166,6 +211,27 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) -                                                      G_PARAM_STATIC_NICK)); -  -   /** -+   * PolkitUnixProcess:uid: -+   * -+   * The UNIX user id of the process or -1 if unknown. -+   * -+   * Note that this is the real user-id, not the effective user-id. -+   */ -+  g_object_class_install_property (gobject_class, -+                                   PROP_UID, -+                                   g_param_spec_int ("uid", -+                                                     "User ID", -+                                                     "The UNIX user ID", -+                                                     -1, -+                                                     G_MAXINT, -+                                                     -1, -+                                                     G_PARAM_CONSTRUCT | -+                                                     G_PARAM_READWRITE | -+                                                     G_PARAM_STATIC_NAME | -+                                                     G_PARAM_STATIC_BLURB | -+                                                     G_PARAM_STATIC_NICK)); -+ -+  /** -    * PolkitUnixProcess:start-time: -    * -    * The start time of the process. -@@ -178,7 +244,8 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) -                                                         0, -                                                         G_MAXUINT64, -                                                         0, --                                                        G_PARAM_READABLE | -+                                                        G_PARAM_CONSTRUCT | -+                                                        G_PARAM_READWRITE | -                                                         G_PARAM_STATIC_NAME | -                                                         G_PARAM_STATIC_BLURB | -                                                         G_PARAM_STATIC_NICK)); -@@ -186,113 +253,50 @@ polkit_unix_process_class_init (PolkitUnixProcessClass *klass) - } -  - /** -- * polkit_unix_process_get_pid: -+ * polkit_unix_process_get_uid: -  * @process: A #PolkitUnixProcess. -  * -- * Gets the process id for @process. -+ * Gets the user id for @process. Note that this is the real user-id, -+ * not the effective user-id. -  * -- * Returns: The process id for @process. -+ * Returns: The user id for @process or -1 if unknown. -  */ - gint --polkit_unix_process_get_pid (PolkitUnixProcess *process) -+polkit_unix_process_get_uid (PolkitUnixProcess *process) - { --  g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), 0); --  return process->pid; -+  g_return_val_if_fail (POLKIT_IS_UNIX_PROCESS (process), -1); -+  return process->uid; - } -  - /** -- * polkit_unix_process_get_owner: -+ * polkit_unix_process_set_uid: -  * @process: A #PolkitUnixProcess. -- * @error: (allow-none): Return location for error or %NULL. -+ * @uid: The user id to set for @process or -1 to unset it. -  * -- * Gets the uid of the owner of @process. -+ * Sets the (real, not effective) user id for @process. -+ */ -+void -+polkit_unix_process_set_uid (PolkitUnixProcess *process, -+                             gint               uid) -+{ -+  g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); -+  g_return_if_fail (uid >= -1); -+  process->uid = uid; -+} -+ -+/** -+ * polkit_unix_process_get_pid: -+ * @process: A #PolkitUnixProcess. -  * -- * Note that this returns the real user-id (not the effective user-id) of @process. -+ * Gets the process id for @process. -  * -- * Returns: The UNIX user id of the owner for @process or 0 if @error is set. -- **/ -+ * Returns: The process id for @process. -+ */ - gint --polkit_unix_process_get_owner (PolkitUnixProcess  *process, --                               GError            **error) -+polkit_unix_process_get_pid (PolkitUnixProcess *process) - { --  gint result; --  gchar *contents; --  gchar **lines; --#ifdef HAVE_FREEBSD --  struct kinfo_proc p; --#else --  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) --    { --      g_set_error (error, --                   POLKIT_ERROR, --                   POLKIT_ERROR_FAILED, --                   "get_kinfo_proc() failed for pid %d: %s", --                   process->pid, --                   g_strerror (errno)); --      goto out; --    } -- --  result = p.ki_uid; --#else -- --  /* 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)) --    { --      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; --        } --    } -- --  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; -+  return process->pid; - } -  - /** -@@ -311,6 +315,21 @@ polkit_unix_process_get_start_time (PolkitUnixProcess *process) - } -  - /** -+ * polkit_unix_process_set_start_time: -+ * @process: A #PolkitUnixProcess. -+ * @start_time: The start time for @pid. -+ * -+ * Set the start time of @process. -+ */ -+void -+polkit_unix_process_set_start_time (PolkitUnixProcess *process, -+                                    guint64            start_time) -+{ -+  g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); -+  process->start_time = start_time; -+} -+ -+/** -  * polkit_unix_process_set_pid: -  * @process: A #PolkitUnixProcess. -  * @pid: A process id. -@@ -323,18 +342,17 @@ polkit_unix_process_set_pid (PolkitUnixProcess *process, - { -   g_return_if_fail (POLKIT_IS_UNIX_PROCESS (process)); -   process->pid = pid; --  if (pid != (gint) -1) --    process->start_time = get_start_time_for_pid (pid, NULL); - } -  - /** -  * polkit_unix_process_new: -  * @pid: The process id. -  * -- * Creates a new #PolkitUnixProcess for @pid. The start time of the -- * process will be looked up in using e.g. the -- * <filename>/proc</filename> filesystem depending on the platform in -- * use. -+ * Creates a new #PolkitUnixProcess for @pid. -+ * -+ * The uid and start time of the process will be looked up in using -+ * e.g. the <filename>/proc</filename> filesystem depending on the -+ * platform in use. -  * -  * Returns: (transfer full): A #PolkitSubject. Free with g_object_unref(). -  */ -@@ -353,22 +371,42 @@ polkit_unix_process_new (gint pid) -  * -  * Creates a new #PolkitUnixProcess object for @pid and @start_time. -  * -+ * The uid of the process will be looked up in using e.g. the -+ * <filename>/proc</filename> filesystem depending on the platform in -+ * use. -+ * -  * Returns: (transfer full): A #PolkitSubject. Free with g_object_unref(). -  */ - PolkitSubject * - polkit_unix_process_new_full (gint pid, -                               guint64 start_time) - { --  PolkitUnixProcess *process; -- --  process = POLKIT_UNIX_PROCESS (polkit_unix_process_new ((gint) -1)); --  process->pid = pid; --  if (start_time != 0) --    process->start_time = start_time; --  else --    process->start_time = get_start_time_for_pid (pid, NULL); -+  return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_PROCESS, -+                                       "pid", pid, -+                                       "start_time", start_time, -+                                       NULL)); -+} -  --  return POLKIT_SUBJECT (process); -+/** -+ * polkit_unix_process_new_for_owner: -+ * @pid: The process id. -+ * @start_time: The start time for @pid or 0 to look it up in e.g. <filename>/proc</filename>. -+ * @uid: The (real, not effective) uid of the owner of @pid or -1 to look it up in e.g. <filename>/proc</filename>. -+ * -+ * Creates a new #PolkitUnixProcess object for @pid, @start_time and @uid. -+ * -+ * Returns: (transfer full): A #PolkitSubject. Free with g_object_unref(). -+ */ -+PolkitSubject * -+polkit_unix_process_new_for_owner (gint    pid, -+                                   guint64 start_time, -+                                   gint    uid) -+{ -+  return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_PROCESS, -+                                       "pid", pid, -+                                       "start_time", start_time, -+                                       "uid", uid, -+                                       NULL)); - } -  - static guint -@@ -616,3 +654,95 @@ out: -  -   return start_time; - } -+ -+static gint -+_polkit_unix_process_get_owner (PolkitUnixProcess  *process, -+                                GError            **error) -+{ -+  gint result; -+  gchar *contents; -+  gchar **lines; -+#ifdef HAVE_FREEBSD -+  struct kinfo_proc p; -+#else -+  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) -+    { -+      g_set_error (error, -+                   POLKIT_ERROR, -+                   POLKIT_ERROR_FAILED, -+                   "get_kinfo_proc() failed for pid %d: %s", -+                   process->pid, -+                   g_strerror (errno)); -+      goto out; -+    } -+ -+  result = p.ki_uid; -+#else -+ -+  /* 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)) -+    { -+      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; -+        } -+    } -+ -+  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; -+} -+ -+/* deprecated public method */ -+gint -+polkit_unix_process_get_owner (PolkitUnixProcess  *process, -+                               GError            **error) -+{ -+  return _polkit_unix_process_get_owner (process, error); -+} -diff --git a/src/polkit/polkitunixprocess.h b/src/polkit/polkitunixprocess.h -index b88cd03..531a57d 100644 ---- a/src/polkit/polkitunixprocess.h -+++ b/src/polkit/polkitunixprocess.h -@@ -47,16 +47,24 @@ typedef struct _PolkitUnixProcess PolkitUnixProcess; - typedef struct _PolkitUnixProcessClass PolkitUnixProcessClass; -  - 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            (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); - guint64         polkit_unix_process_get_start_time (PolkitUnixProcess *process); -+gint            polkit_unix_process_get_uid        (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); -+ - gint            polkit_unix_process_get_owner      (PolkitUnixProcess  *process, --                                                    GError            **error); -+                                                    GError            **error) G_GNUC_DEPRECATED_FOR (polkit_unix_process_get_uid); -  - G_END_DECLS -  --- -cgit v0.8.3-6-g21f6 -From c23d74447c7615dc74dae259f0fc3688ec988867 Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Fri, 01 Apr 2011 16:12:27 +0000 -Subject: Use polkit_unix_process_get_uid() to get the owner of a process - -This avoids a TOCTTOU problem. - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/src/polkitbackend/polkitbackendsessionmonitor.c b/src/polkitbackend/polkitbackendsessionmonitor.c -index 495f752..9c331b6 100644 ---- a/src/polkitbackend/polkitbackendsessionmonitor.c -+++ b/src/polkitbackend/polkitbackendsessionmonitor.c -@@ -293,14 +293,15 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor -  -   if (POLKIT_IS_UNIX_PROCESS (subject)) -     { --      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_prefixed_error (error, local_error, "Error getting user for process: "); -+          g_set_error (error, -+                       POLKIT_ERROR, -+                       POLKIT_ERROR_FAILED, -+                       "Unix process subject does not have uid set"); -           goto out; -         } -- -       ret = polkit_unix_user_new (uid); -     } -   else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) --- -cgit v0.8.3-6-g21f6 -From 3b12cfac29dddd27f1f166a7574d8374cc1dccf2 Mon Sep 17 00:00:00 2001 -From: David Zeuthen <davidz@redhat.com> -Date: Fri, 01 Apr 2011 16:13:15 +0000 -Subject: pkexec: Avoid TOCTTOU problems with parent process - -In a nutshell, the parent process may change its uid (either real- or -effective uid) after launching pkexec. It can do this by exec()'ing -e.g. a setuid root program. - -To avoid this problem, just use the uid the parent process had when it -executed pkexec. This happens to be the same uid of the pkexec process -itself. - -Additionally, remove some dubious code that allowed pkexec to continue -when the parent process died as there is no reason to support -something like that. Also ensure that the pkexec process is killed if -the parent process dies. - -This problem was pointed out by Neel Mehta <nmehta@google.com>. - -Signed-off-by: David Zeuthen <davidz@redhat.com> ---- -diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c -index 9217954..3e656be 100644 ---- a/src/programs/pkexec.c -+++ b/src/programs/pkexec.c -@@ -35,6 +35,10 @@ - #include <pwd.h> - #include <errno.h> -  -+#ifdef __linux__ -+#include <sys/prctl.h> -+#endif -+ - #include <glib/gi18n.h> -  - #ifdef POLKIT_AUTHFW_PAM -@@ -423,7 +427,6 @@ main (int argc, char *argv[]) -   GPtrArray *saved_env; -   gchar *opt_user; -   pid_t pid_of_caller; --  uid_t uid_of_caller; -   gpointer local_agent_handle; -  -   ret = 127; -@@ -598,40 +601,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); -  -   error = NULL; -   authority = polkit_authority_get_sync (NULL /* GCancellable* */, &error); --- -cgit v0.8.3-6-g21f6 diff --git a/abs/extra/polkit/PKGBUILD b/abs/extra/polkit/PKGBUILD index 3a55ddc..e86dbbc 100644 --- a/abs/extra/polkit/PKGBUILD +++ b/abs/extra/polkit/PKGBUILD @@ -1,9 +1,9 @@ -# $Id$ +# $Id: PKGBUILD 158972 2012-05-13 21:06:37Z jgc $  # Maintainer: Jan de Groot <jgc@archlinux.org>  pkgname=polkit -pkgver=0.101 -pkgrel=2 +pkgver=0.105 +pkgrel=1  pkgdesc="Application development toolkit for controlling system-wide privileges"  arch=(i686 x86_64)  license=('LGPL') @@ -12,21 +12,22 @@ depends=('glib2' 'pam' 'expat')  makedepends=('intltool' 'gtk-doc' 'gobject-introspection')  replaces=('policykit')  options=('!libtool') -source=(http://hal.freedesktop.org/releases/${pkgname}-${pkgver}.tar.gz -        CVE-2011-1485.patch +source=(http://www.freedesktop.org/software/polkit/releases/$pkgname-$pkgver.tar.gz          polkit.pam) -md5sums=('f925ac93aba3c072977370c1e27feb7f' -         '4d858b8ab602614d7db2bc8574f6fd29' +md5sums=('9c29e1b6c214f0bd6f1d4ee303dfaed9'           '6564f95878297b954f0572bc1610dd15')  build() { -  cd "${srcdir}/${pkgname}-${pkgver}" -  patch -Np1 -i "${srcdir}/CVE-2011-1485.patch" +  cd $pkgname-$pkgver    ./configure --prefix=/usr --sysconfdir=/etc \        --localstatedir=/var --libexecdir=/usr/lib/polkit-1 \        --disable-static --enable-gtk-doc    make -  make DESTDIR="${pkgdir}" install +} + +package() { +  cd $pkgname-$pkgver +  make DESTDIR="$pkgdir" install -  install -m644 "${srcdir}/polkit.pam" "${pkgdir}/etc/pam.d/polkit-1" +  install -m644 "$srcdir/polkit.pam" "$pkgdir/etc/pam.d/polkit-1"  } diff --git a/abs/extra/polkit/systemd-fallback.patch b/abs/extra/polkit/systemd-fallback.patch new file mode 100644 index 0000000..f89ce10 --- /dev/null +++ b/abs/extra/polkit/systemd-fallback.patch @@ -0,0 +1,1571 @@ +diff -u -rN polkit-0.104/configure.ac polkit-0.104-systemd-fallback/configure.ac +--- polkit-0.104/configure.ac	2012-01-03 17:25:49.000000000 +0100 ++++ polkit-0.104-systemd-fallback/configure.ac	2012-03-06 15:45:55.275860194 +0100 +@@ -160,14 +160,14 @@ +               [enable_systemd=auto]) + if test "$enable_systemd" != "no"; then +   PKG_CHECK_MODULES(SYSTEMD, +-                    [libsystemd-login], ++                    [libsystemd-login libsystemd-daemon], +                     have_systemd=yes, +                     have_systemd=no) +   if test "$have_systemd" = "yes"; then +     SESSION_TRACKING=systemd +   else +     if test "$enable_systemd" = "yes"; then +-      AC_MSG_ERROR([systemd support requested but libsystemd-login1 library not found]) ++      AC_MSG_ERROR([systemd support requested but systemd libraries not found]) +     fi +   fi + fi +diff -u -rN polkit-0.104/src/polkit/Makefile.am polkit-0.104-systemd-fallback/src/polkit/Makefile.am +--- polkit-0.104/src/polkit/Makefile.am	2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkit/Makefile.am	2012-03-06 15:19:25.108853325 +0100 +@@ -79,15 +79,8 @@ + 	polkitimplicitauthorization.c		polkitimplicitauthorization.h		\ + 	polkittemporaryauthorization.c		polkittemporaryauthorization.h		\ + 	polkitpermission.c			polkitpermission.h			\ +-        $(NULL) +- +-if HAVE_SYSTEMD +-libpolkit_gobject_1_la_SOURCES += \ +-	polkitunixsession-systemd.c		polkitunixsession.h +-else +-libpolkit_gobject_1_la_SOURCES += \ + 	polkitunixsession.c			polkitunixsession.h +-endif ++        $(NULL) +  + libpolkit_gobject_1_la_CFLAGS =                                        	\ +         -D_POLKIT_COMPILATION                                  		\ +diff -u -rN polkit-0.104/src/polkit/polkitunixsession.c polkit-0.104-systemd-fallback/src/polkit/polkitunixsession.c +--- polkit-0.104/src/polkit/polkitunixsession.c	2011-10-18 19:02:27.000000000 +0200 ++++ polkit-0.104-systemd-fallback/src/polkit/polkitunixsession.c	2012-03-06 15:17:29.829788021 +0100 +@@ -23,12 +23,18 @@ + #  include "config.h" + #endif +  ++#include <stdlib.h> + #include <string.h> + #include "polkitunixsession.h" + #include "polkitsubject.h" + #include "polkiterror.h" + #include "polkitprivate.h" +  ++#ifdef HAVE_SYSTEMD ++#  include <systemd/sd-daemon.h> ++#  include <systemd/sd-login.h> ++#endif ++ + /** +  * SECTION:polkitunixsession +  * @title: PolkitUnixSession +@@ -364,34 +370,44 @@ +   PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +   GDBusConnection *connection; +   GVariant *result; +-  gboolean ret; +- +-  ret = FALSE; ++  gboolean ret = FALSE; +  +-  connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); +-  if (connection == NULL) +-    goto out; +- +-  result = g_dbus_connection_call_sync (connection, +-                                        "org.freedesktop.ConsoleKit",           /* name */ +-                                        session->session_id,                    /* object path */ +-                                        "org.freedesktop.ConsoleKit.Session",   /* interface name */ +-                                        "GetUser",                              /* method */ +-                                        NULL, /* parameters */ +-                                        G_VARIANT_TYPE ("(u)"), +-                                        G_DBUS_CALL_FLAGS_NONE, +-                                        -1, +-                                        cancellable, +-                                        error); +-  if (result == NULL) +-    goto out; ++#ifdef HAVE_SYSTEMD ++  uid_t uid; ++   ++  if (sd_booted () > 0) ++    { ++      if (sd_session_get_uid (session->session_id, &uid) == 0) ++        ret = TRUE; ++    } ++  else ++#endif ++    { ++      connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); ++      if (connection == NULL) ++        goto out; ++ ++      result = g_dbus_connection_call_sync (connection, ++                                            "org.freedesktop.ConsoleKit",           /* name */ ++                                            session->session_id,                    /* object path */ ++                                            "org.freedesktop.ConsoleKit.Session",   /* interface name */ ++                                            "GetUser",                              /* method */ ++                                            NULL, /* parameters */ ++                                            G_VARIANT_TYPE ("(u)"), ++                                            G_DBUS_CALL_FLAGS_NONE, ++                                            -1, ++                                            cancellable, ++                                            error); ++      if (result == NULL) ++        goto out; +  +-  ret = TRUE; +-  g_variant_unref (result); ++      ret = TRUE; ++      g_variant_unref (result); +  +- out: +-  if (connection != NULL) +-    g_object_unref (connection); ++     out: ++      if (connection != NULL) ++        g_object_unref (connection); ++    } +   return ret; + } +  +@@ -470,12 +486,9 @@ +                                    GError       **error) + { +   PolkitUnixSession *session = POLKIT_UNIX_SESSION (initable); +-  GDBusConnection *connection; ++  GDBusConnection *connection = NULL; +   GVariant *result; +-  gboolean ret; +- +-  connection = NULL; +-  ret = FALSE; ++  gboolean ret = FALSE; +  +   if (session->session_id != NULL) +     { +@@ -484,33 +497,56 @@ +       goto out; +     } +  +-  connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); +-  if (connection == NULL) +-    goto out; ++#ifdef HAVE_SYSTEMD ++  char *s; ++   ++  if (sd_booted () > 0) ++    { ++      if (sd_pid_get_session (session->pid, &s) == 0) ++        { ++          session->session_id = g_strdup (s); ++          free (s); ++          ret = TRUE; ++          goto out; ++        } ++       ++      g_set_error (error, ++                   POLKIT_ERROR, ++                   POLKIT_ERROR_FAILED, ++                   "No session for pid %d", ++                   (gint) session->pid); ++    } ++  else ++#endif ++    {  ++      connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); ++      if (connection == NULL) ++        goto out; ++ ++      result = g_dbus_connection_call_sync (connection, ++                                            "org.freedesktop.ConsoleKit",           /* name */ ++                                            "/org/freedesktop/ConsoleKit/Manager",  /* object path */ ++                                            "org.freedesktop.ConsoleKit.Manager",   /* interface name */ ++                                            "GetSessionForUnixProcess",             /* method */ ++                                            g_variant_new ("(u)", session->pid),    /* parameters */ ++                                            G_VARIANT_TYPE ("(o)"), ++                                            G_DBUS_CALL_FLAGS_NONE, ++                                            -1, ++                                            cancellable, ++                                            error); ++      if (result == NULL) ++        goto out; +  +-  result = g_dbus_connection_call_sync (connection, +-                                        "org.freedesktop.ConsoleKit",           /* name */ +-                                        "/org/freedesktop/ConsoleKit/Manager",  /* object path */ +-                                        "org.freedesktop.ConsoleKit.Manager",   /* interface name */ +-                                        "GetSessionForUnixProcess",             /* method */ +-                                        g_variant_new ("(u)", session->pid),    /* parameters */ +-                                        G_VARIANT_TYPE ("(o)"), +-                                        G_DBUS_CALL_FLAGS_NONE, +-                                        -1, +-                                        cancellable, +-                                        error); +-  if (result == NULL) +-    goto out; ++      g_variant_get (result, "(o)", &session->session_id); ++      g_variant_unref (result); +  +-  g_variant_get (result, "(o)", &session->session_id); +-  g_variant_unref (result); ++      ret = TRUE; ++    } +  +-  ret = TRUE; +  +  out: +   if (connection != NULL) +     g_object_unref (connection); +- +   return ret; + } +  +diff -u -rN polkit-0.104/src/polkit/polkitunixsession-systemd.c polkit-0.104-systemd-fallback/src/polkit/polkitunixsession-systemd.c +--- polkit-0.104/src/polkit/polkitunixsession-systemd.c	2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkit/polkitunixsession-systemd.c	1970-01-01 01:00:00.000000000 +0100 +@@ -1,481 +0,0 @@ +-/* +- * Copyright (C) 2011 Red Hat, Inc. +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Lesser General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +- * Lesser General Public License for more details. +- * +- * You should have received a copy of the GNU Lesser General +- * Public License along with this library; if not, write to the +- * Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- * Boston, MA 02111-1307, USA. +- * +- * Author: Matthias Clasen +- */ +- +-#ifdef HAVE_CONFIG_H +-#  include "config.h" +-#endif +- +-#include <string.h> +-#include "polkitunixsession.h" +-#include "polkitsubject.h" +-#include "polkiterror.h" +-#include "polkitprivate.h" +- +-#include <systemd/sd-login.h> +- +-/** +- * SECTION:polkitunixsession +- * @title: PolkitUnixSession +- * @short_description: Unix sessions +- * +- * An object that represents an user session. +- * +- * The session id is an opaque string obtained from ConsoleKit. +- */ +- +-/** +- * PolkitUnixSession: +- * +- * The #PolkitUnixSession struct should not be accessed directly. +- */ +-struct _PolkitUnixSession +-{ +-  GObject parent_instance; +- +-  gchar *session_id; +- +-  gint pid; +-}; +- +-struct _PolkitUnixSessionClass +-{ +-  GObjectClass parent_class; +-}; +- +-enum +-{ +-  PROP_0, +-  PROP_SESSION_ID, +-  PROP_PID, +-}; +- +-static void subject_iface_init        (PolkitSubjectIface *subject_iface); +-static void initable_iface_init       (GInitableIface *initable_iface); +-static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface); +- +-G_DEFINE_TYPE_WITH_CODE (PolkitUnixSession, polkit_unix_session, G_TYPE_OBJECT, +-                         G_IMPLEMENT_INTERFACE (POLKIT_TYPE_SUBJECT, subject_iface_init) +-                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) +-                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init) +-                         ); +- +-static void +-polkit_unix_session_init (PolkitUnixSession *session) +-{ +-} +- +-static void +-polkit_unix_session_finalize (GObject *object) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); +- +-  g_free (session->session_id); +- +-  if (G_OBJECT_CLASS (polkit_unix_session_parent_class)->finalize != NULL) +-    G_OBJECT_CLASS (polkit_unix_session_parent_class)->finalize (object); +-} +- +-static void +-polkit_unix_session_get_property (GObject    *object, +-                                  guint       prop_id, +-                                  GValue     *value, +-                                  GParamSpec *pspec) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); +- +-  switch (prop_id) +-    { +-    case PROP_SESSION_ID: +-      g_value_set_string (value, session->session_id); +-      break; +- +-    default: +-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +-      break; +-    } +-} +- +-static void +-polkit_unix_session_set_property (GObject      *object, +-                                  guint         prop_id, +-                                  const GValue *value, +-                                  GParamSpec   *pspec) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); +- +-  switch (prop_id) +-    { +-    case PROP_SESSION_ID: +-      polkit_unix_session_set_session_id (session, g_value_get_string (value)); +-      break; +- +-    case PROP_PID: +-      session->pid = g_value_get_int (value); +-      break; +- +-    default: +-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +-      break; +-    } +-} +- +-static void +-polkit_unix_session_class_init (PolkitUnixSessionClass *klass) +-{ +-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass); +- +-  gobject_class->finalize     = polkit_unix_session_finalize; +-  gobject_class->get_property = polkit_unix_session_get_property; +-  gobject_class->set_property = polkit_unix_session_set_property; +- +-  /** +-   * PolkitUnixSession:session-id: +-   * +-   * The UNIX session id. +-   */ +-  g_object_class_install_property (gobject_class, +-                                   PROP_SESSION_ID, +-                                   g_param_spec_string ("session-id", +-                                                        "Session ID", +-                                                        "The UNIX session ID", +-                                                        NULL, +-                                                        G_PARAM_CONSTRUCT | +-                                                        G_PARAM_READWRITE | +-                                                        G_PARAM_STATIC_NAME | +-                                                        G_PARAM_STATIC_BLURB | +-                                                        G_PARAM_STATIC_NICK)); +- +- +-  /** +-   * PolkitUnixSession:pid: +-   * +-   * The UNIX process id to look up the session. +-   */ +-  g_object_class_install_property (gobject_class, +-                                   PROP_PID, +-                                   g_param_spec_int ("pid", +-                                                     "Process ID", +-                                                     "Process ID to use for looking up the session", +-                                                     0, +-                                                     G_MAXINT, +-                                                     0, +-                                                     G_PARAM_CONSTRUCT_ONLY | +-                                                     G_PARAM_WRITABLE | +-                                                     G_PARAM_STATIC_NAME | +-                                                     G_PARAM_STATIC_BLURB | +-                                                     G_PARAM_STATIC_NICK)); +- +-} +- +-/** +- * polkit_unix_session_get_session_id: +- * @session: A #PolkitUnixSession. +- * +- * Gets the session id for @session. +- * +- * Returns: The session id for @session. Do not free this string, it +- * is owned by @session. +- **/ +-const gchar * +-polkit_unix_session_get_session_id (PolkitUnixSession *session) +-{ +-  g_return_val_if_fail (POLKIT_IS_UNIX_SESSION (session), NULL); +-  return session->session_id; +-} +- +-/** +- * polkit_unix_session_set_session_id: +- * @session: A #PolkitUnixSession. +- * @session_id: The session id. +- * +- * Sets the session id for @session to @session_id. +- **/ +-void +-polkit_unix_session_set_session_id (PolkitUnixSession *session, +-                                    const gchar       *session_id) +-{ +-  g_return_if_fail (POLKIT_IS_UNIX_SESSION (session)); +-  /*g_return_if_fail (session_id != NULL);*/ +-  g_free (session->session_id); +-  session->session_id = g_strdup (session_id); +-} +- +-/** +- * polkit_unix_session_new: +- * @session_id: The session id. +- * +- * Creates a new #PolkitUnixSession for @session_id. +- * +- * Returns: (transfer full): A #PolkitUnixSession. Free with g_object_unref(). +- **/ +-PolkitSubject * +-polkit_unix_session_new (const gchar *session_id) +-{ +-  return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_SESSION, +-                                       "session-id", session_id, +-                                       NULL)); +-} +- +-/** +- * polkit_unix_session_new_for_process: +- * @pid: The process id of the process to get the session for. +- * @cancellable: (allow-none): A #GCancellable or %NULL. +- * @callback: A #GAsyncReadyCallback to call when the request is satisfied +- * @user_data: The data to pass to @callback. +- * +- * Asynchronously creates a new #PolkitUnixSession object for the +- * process with process id @pid. +- * +- * When the operation is finished, @callback will be invoked in the +- * <link linkend="g-main-context-push-thread-default">thread-default +- * main loop</link> of the thread you are calling this method +- * from. You can then call +- * polkit_unix_session_new_for_process_finish() to get the result of +- * the operation. +- * +- * This method constructs the object asynchronously, for the synchronous and blocking version +- * use polkit_unix_session_new_for_process_sync(). +- **/ +-void +-polkit_unix_session_new_for_process (gint                pid, +-                                     GCancellable       *cancellable, +-                                     GAsyncReadyCallback callback, +-                                     gpointer            user_data) +-{ +-  g_async_initable_new_async (POLKIT_TYPE_UNIX_SESSION, +-                              G_PRIORITY_DEFAULT, +-                              cancellable, +-                              callback, +-                              user_data, +-                              "pid", pid, +-                              NULL); +-} +- +-/** +- * polkit_unix_session_new_for_process_finish: +- * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to polkit_unix_session_new_for_process(). +- * @error: (allow-none): Return location for error. +- * +- * Finishes constructing a #PolkitSubject for a process id. +- * +- * Returns: (transfer full) (allow-none): A #PolkitUnixSession for the @pid passed to +- *     polkit_unix_session_new_for_process() or %NULL if @error is +- *     set. Free with g_object_unref(). +- **/ +-PolkitSubject * +-polkit_unix_session_new_for_process_finish (GAsyncResult   *res, +-                                            GError        **error) +-{ +-  GObject *object; +-  GObject *source_object; +- +-  source_object = g_async_result_get_source_object (res); +-  g_assert (source_object != NULL); +- +-  object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), +-                                        res, +-                                        error); +-  g_object_unref (source_object); +- +-  if (object != NULL) +-    return POLKIT_SUBJECT (object); +-  else +-    return NULL; +-} +- +- +-/** +- * polkit_unix_session_new_for_process_sync: +- * @pid: The process id of the process to get the session for. +- * @cancellable: (allow-none): A #GCancellable or %NULL. +- * @error: (allow-none): Return location for error. +- * +- * Creates a new #PolkitUnixSession for the process with process id @pid. +- * +- * This is a synchronous call - the calling thread is blocked until a +- * reply is received. For the asynchronous version, see +- * polkit_unix_session_new_for_process(). +- * +- * Returns: (allow-none) (transfer full): A #PolkitUnixSession for +- * @pid or %NULL if @error is set. Free with g_object_unref(). +- **/ +-PolkitSubject * +-polkit_unix_session_new_for_process_sync (gint           pid, +-                                          GCancellable  *cancellable, +-                                          GError       **error) +-{ +-  return POLKIT_SUBJECT (g_initable_new (POLKIT_TYPE_UNIX_SESSION, +-                                         cancellable, +-                                         error, +-                                         "pid", pid, +-                                         NULL)); +-} +- +-static guint +-polkit_unix_session_hash (PolkitSubject *subject) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +- +-  return g_str_hash (session->session_id); +-} +- +-static gboolean +-polkit_unix_session_equal (PolkitSubject *a, +-                           PolkitSubject *b) +-{ +-  PolkitUnixSession *session_a; +-  PolkitUnixSession *session_b; +- +-  session_a = POLKIT_UNIX_SESSION (a); +-  session_b = POLKIT_UNIX_SESSION (b); +- +-  return g_strcmp0 (session_a->session_id, session_b->session_id) == 0; +-} +- +-static gchar * +-polkit_unix_session_to_string (PolkitSubject *subject) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +- +-  return g_strdup_printf ("unix-session:%s", session->session_id); +-} +- +-static gboolean +-polkit_unix_session_exists_sync (PolkitSubject   *subject, +-                                    GCancellable    *cancellable, +-                                    GError         **error) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); +-  gboolean ret; +-  uid_t uid; +- +-  ret = FALSE; +- +-  if (!sd_session_get_uid (session->session_id, &uid)) +-    ret = FALSE; +- +-  return ret; +-} +- +-static void +-exists_in_thread_func (GSimpleAsyncResult *res, +-                       GObject            *object, +-                       GCancellable       *cancellable) +-{ +-  GError *error; +-  error = NULL; +-  if (!polkit_unix_session_exists_sync (POLKIT_SUBJECT (object), +-                                        cancellable, +-                                        &error)) +-    { +-      g_simple_async_result_set_from_error (res, error); +-      g_error_free (error); +-    } +-} +- +-static void +-polkit_unix_session_exists (PolkitSubject       *subject, +-                            GCancellable        *cancellable, +-                            GAsyncReadyCallback  callback, +-                            gpointer             user_data) +-{ +-  GSimpleAsyncResult *simple; +- +-  g_return_if_fail (POLKIT_IS_UNIX_SESSION (subject)); +- +-  simple = g_simple_async_result_new (G_OBJECT (subject), +-                                      callback, +-                                      user_data, +-                                      polkit_unix_session_exists); +-  g_simple_async_result_run_in_thread (simple, +-                                       exists_in_thread_func, +-                                       G_PRIORITY_DEFAULT, +-                                       cancellable); +-  g_object_unref (simple); +-} +- +-static gboolean +-polkit_unix_session_exists_finish (PolkitSubject  *subject, +-                                      GAsyncResult   *res, +-                                      GError        **error) +-{ +-  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); +-  gboolean ret; +- +-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_unix_session_exists); +- +-  ret = FALSE; +- +-  if (g_simple_async_result_propagate_error (simple, error)) +-    goto out; +- +-  ret = g_simple_async_result_get_op_res_gboolean (simple); +- +- out: +-  return ret; +-} +- +-static void +-subject_iface_init (PolkitSubjectIface *subject_iface) +-{ +-  subject_iface->hash          = polkit_unix_session_hash; +-  subject_iface->equal         = polkit_unix_session_equal; +-  subject_iface->to_string     = polkit_unix_session_to_string; +-  subject_iface->exists        = polkit_unix_session_exists; +-  subject_iface->exists_finish = polkit_unix_session_exists_finish; +-  subject_iface->exists_sync   = polkit_unix_session_exists_sync; +-} +- +-static gboolean +-polkit_unix_session_initable_init (GInitable     *initable, +-                                   GCancellable  *cancellable, +-                                   GError       **error) +-{ +-  PolkitUnixSession *session = POLKIT_UNIX_SESSION (initable); +-  gboolean ret; +- +-  ret = FALSE; +- +-  if (session->session_id != NULL) +-    { +-      /* already set, nothing to do */ +-      ret = TRUE; +-      goto out; +-    } +- +-  if (!sd_pid_get_session (session->pid, &session->session_id)) +-    ret = TRUE; +- +-out: +-  return ret; +-} +- +-static void +-initable_iface_init (GInitableIface *initable_iface) +-{ +-  initable_iface->init = polkit_unix_session_initable_init; +-} +- +-static void +-async_initable_iface_init (GAsyncInitableIface *async_initable_iface) +-{ +-  /* use default implementation to run GInitable code in a thread */ +-} +diff -u -rN polkit-0.104/src/polkitbackend/Makefile.am polkit-0.104-systemd-fallback/src/polkitbackend/Makefile.am +--- polkit-0.104/src/polkitbackend/Makefile.am	2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkitbackend/Makefile.am	2012-03-06 15:44:15.380014886 +0100 +@@ -41,15 +41,8 @@ + 	polkitbackendconfigsource.h		polkitbackendconfigsource.c		\ + 	polkitbackendactionlookup.h		polkitbackendactionlookup.c		\ + 	polkitbackendlocalauthorizationstore.h	polkitbackendlocalauthorizationstore.c	\ +-        $(NULL) +- +-if HAVE_SYSTEMD +-libpolkit_backend_1_la_SOURCES += \ +-	polkitbackendsessionmonitor.h		polkitbackendsessionmonitor-systemd.c +-else +-libpolkit_backend_1_la_SOURCES += \ + 	polkitbackendsessionmonitor.h		polkitbackendsessionmonitor.c +-endif ++        $(NULL) +  + libpolkit_backend_1_la_CFLAGS =                                        	\ +         -D_POLKIT_COMPILATION                                  		\ +diff -u -rN polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor.c polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor.c +--- polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor.c	2011-10-18 19:02:27.000000000 +0200 ++++ polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor.c	2012-03-06 15:43:49.353562242 +0100 +@@ -26,6 +26,12 @@ + #include <string.h> + #include <glib/gstdio.h> +  ++#ifdef HAVE_SYSTEMD ++#  include <systemd/sd-daemon.h> ++#  include <systemd/sd-login.h> ++#  include <stdlib.h> ++#endif ++ + #include <polkit/polkit.h> + #include "polkitbackendsessionmonitor.h" +  +@@ -39,6 +45,88 @@ +  * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions. +  */ +  ++#ifdef HAVE_SYSTEMD ++typedef struct ++{ ++  GSource source; ++  GPollFD pollfd; ++  sd_login_monitor *monitor; ++} SdSource; ++ ++static gboolean ++sd_source_prepare (GSource *source, ++                   gint    *timeout) ++{ ++  *timeout = -1; ++  return FALSE; ++} ++ ++static gboolean ++sd_source_check (GSource *source) ++{ ++  SdSource *sd_source = (SdSource *)source; ++ ++  return sd_source->pollfd.revents != 0; ++} ++ ++static gboolean ++sd_source_dispatch (GSource     *source, ++                    GSourceFunc  callback, ++                    gpointer     user_data) ++ ++{ ++  SdSource *sd_source = (SdSource *)source; ++  gboolean ret; ++ ++  g_warn_if_fail (callback != NULL); ++ ++  ret = (*callback) (user_data); ++ ++  sd_login_monitor_flush (sd_source->monitor); ++ ++  return ret; ++} ++ ++static void ++sd_source_finalize (GSource *source) ++{ ++  SdSource *sd_source = (SdSource*)source; ++ ++  sd_login_monitor_unref (sd_source->monitor); ++} ++ ++static GSourceFuncs sd_source_funcs = { ++  sd_source_prepare, ++  sd_source_check, ++  sd_source_dispatch, ++  sd_source_finalize ++}; ++ ++static GSource * ++sd_source_new (void) ++{ ++  GSource *source; ++  SdSource *sd_source; ++  int ret; ++ ++  source = g_source_new (&sd_source_funcs, sizeof (SdSource)); ++  sd_source = (SdSource *)source; ++ ++  if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) ++    { ++      g_printerr ("Error getting login monitor: %d", ret); ++    } ++  else ++    { ++      sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor); ++      sd_source->pollfd.events = G_IO_IN; ++      g_source_add_poll (source, &sd_source->pollfd); ++    } ++ ++  return source; ++} ++#endif /* HAVE_SYSTEMD */ ++ + struct _PolkitBackendSessionMonitor + { +   GObject parent_instance; +@@ -48,6 +136,10 @@ +   GKeyFile *database; +   GFileMonitor *database_monitor; +   time_t database_mtime; ++   ++#ifdef HAVE_SYSTEMD ++  GSource *sd_source; ++#endif + }; +  + struct _PolkitBackendSessionMonitorClass +@@ -162,6 +254,18 @@ +   g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); + } +  ++#ifdef HAVE_SYSTEMD ++static gboolean ++sessions_changed (gpointer user_data) ++{ ++  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data); ++ ++  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); ++ ++  return TRUE; ++} ++#endif ++ + static void + polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) + { +@@ -176,31 +280,47 @@ +       g_error_free (error); +     } +  +-  error = NULL; +-  if (!ensure_database (monitor, &error)) +-    { +-      g_printerr ("Error loading " CKDB_PATH ": %s", error->message); +-      g_error_free (error); +-    } ++#ifdef HAVE_SYSTEMD ++  monitor->sd_source = NULL; ++   ++  if (sd_booted () > 0) ++    { ++      monitor->sd_source = sd_source_new (); ++      g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL); ++      g_source_attach (monitor->sd_source, NULL); +  +-  error = NULL; +-  file = g_file_new_for_path (CKDB_PATH); +-  monitor->database_monitor = g_file_monitor_file (file, +-                                                   G_FILE_MONITOR_NONE, +-                                                   NULL, +-                                                   &error); +-  g_object_unref (file); +-  if (monitor->database_monitor == NULL) +-    { +-      g_printerr ("Error monitoring " CKDB_PATH ": %s", error->message); +-      g_error_free (error); ++      monitor->database = NULL; ++      monitor->database_monitor = NULL; +     } +   else ++#endif +     { +-      g_signal_connect (monitor->database_monitor, +-                        "changed", +-                        G_CALLBACK (on_file_monitor_changed), +-                        monitor); ++      error = NULL; ++      if (!ensure_database (monitor, &error)) ++        { ++          g_printerr ("Error loading " CKDB_PATH ": %s", error->message); ++          g_error_free (error); ++        } ++ ++      error = NULL; ++      file = g_file_new_for_path (CKDB_PATH); ++      monitor->database_monitor = g_file_monitor_file (file, ++                                                       G_FILE_MONITOR_NONE, ++                                                       NULL, ++                                                       &error); ++      g_object_unref (file); ++      if (monitor->database_monitor == NULL) ++        { ++          g_printerr ("Error monitoring " CKDB_PATH ": %s", error->message); ++          g_error_free (error); ++        } ++      else ++        { ++          g_signal_connect (monitor->database_monitor, ++                            "changed", ++                            G_CALLBACK (on_file_monitor_changed), ++                            monitor); ++        } +     } + } +  +@@ -212,6 +332,14 @@ +   if (monitor->system_bus != NULL) +     g_object_unref (monitor->system_bus); +  ++#ifdef HAVE_SYSTEMD ++  if (monitor->sd_source != NULL) ++    { ++      g_source_destroy (monitor->sd_source); ++      g_source_unref (monitor->sd_source); ++    } ++#endif ++ +   if (monitor->database_monitor != NULL) +     g_object_unref (monitor->database_monitor); +  +@@ -328,22 +456,38 @@ +     } +   else if (POLKIT_IS_UNIX_SESSION (subject)) +     { +-      if (!ensure_database (monitor, error)) ++#ifdef HAVE_SYSTEMD ++      if (monitor->sd_source != NULL) +         { +-          g_prefix_error (error, "Error getting user for session: Error ensuring CK database at " CKDB_PATH ": "); +-          goto out; ++          if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0) ++            { ++              g_set_error (error, ++                           POLKIT_ERROR, ++                           POLKIT_ERROR_FAILED, ++                           "Error getting uid for session"); ++              goto out; ++            } +         } +- +-      group = g_strdup_printf ("Session %s", polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject))); +-      local_error = NULL; +-      uid = g_key_file_get_integer (monitor->database, group, "uid", &local_error); +-      if (local_error != NULL) ++      else ++#endif +         { +-          g_propagate_prefixed_error (error, local_error, "Error getting uid using " CKDB_PATH ": "); ++          if (!ensure_database (monitor, error)) ++            { ++              g_prefix_error (error, "Error getting user for session: Error ensuring CK database at " CKDB_PATH ": "); ++              goto out; ++            } ++ ++          group = g_strdup_printf ("Session %s", polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject))); ++          local_error = NULL; ++          uid = g_key_file_get_integer (monitor->database, group, "uid", &local_error); ++          if (local_error != NULL) ++            { ++              g_propagate_prefixed_error (error, local_error, "Error getting uid using " CKDB_PATH ": "); ++              g_free (group); ++              goto out; ++            } +           g_free (group); +-          goto out; +         } +-      g_free (group); +  +       ret = polkit_unix_user_new (uid); +     } +@@ -373,29 +517,46 @@ +  +   if (POLKIT_IS_UNIX_PROCESS (subject)) +     { +-      const gchar *session_id; +-      GVariant *result; +-      result = g_dbus_connection_call_sync (monitor->system_bus, +-                                            "org.freedesktop.ConsoleKit", +-                                            "/org/freedesktop/ConsoleKit/Manager", +-                                            "org.freedesktop.ConsoleKit.Manager", +-                                            "GetSessionForUnixProcess", +-                                            g_variant_new ("(u)", polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject))), +-                                            G_VARIANT_TYPE ("(o)"), +-                                            G_DBUS_CALL_FLAGS_NONE, +-                                            -1, /* timeout_msec */ +-                                            NULL, /* GCancellable */ +-                                            error); +-      if (result == NULL) +-        goto out; +-      g_variant_get (result, "(&o)", &session_id); +-      session = polkit_unix_session_new (session_id); +-      g_variant_unref (result); ++#ifdef HAVE_SYSTEMD ++      if (monitor->sd_source != NULL) ++        { ++          gchar *session_id; ++          pid_t pid; ++ ++          pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)); ++          if (sd_pid_get_session (pid, &session_id) < 0) ++            goto out; ++ ++          session = polkit_unix_session_new (session_id); ++          free (session_id); ++        } ++      else ++#endif ++        { ++          const gchar *session_id; ++          GVariant *result; ++          result = g_dbus_connection_call_sync (monitor->system_bus, ++                                                "org.freedesktop.ConsoleKit", ++                                                "/org/freedesktop/ConsoleKit/Manager", ++                                                "org.freedesktop.ConsoleKit.Manager", ++                                                "GetSessionForUnixProcess", ++                                                g_variant_new ("(u)", polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject))), ++                                                G_VARIANT_TYPE ("(o)"), ++                                                G_DBUS_CALL_FLAGS_NONE, ++                                                -1, /* timeout_msec */ ++                                                NULL, /* GCancellable */ ++                                                error); ++          if (result == NULL) ++            goto out; ++          g_variant_get (result, "(&o)", &session_id); ++          session = polkit_unix_session_new (session_id); ++          g_variant_unref (result); ++        } +     } +   else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) +     { +       guint32 pid; +-      const gchar *session_id; ++      gchar *session_id; +       GVariant *result; +  +       result = g_dbus_connection_call_sync (monitor->system_bus, +@@ -414,22 +575,35 @@ +       g_variant_get (result, "(u)", &pid); +       g_variant_unref (result); +  +-      result = g_dbus_connection_call_sync (monitor->system_bus, +-                                            "org.freedesktop.ConsoleKit", +-                                            "/org/freedesktop/ConsoleKit/Manager", +-                                            "org.freedesktop.ConsoleKit.Manager", +-                                            "GetSessionForUnixProcess", +-                                            g_variant_new ("(u)", pid), +-                                            G_VARIANT_TYPE ("(o)"), +-                                            G_DBUS_CALL_FLAGS_NONE, +-                                            -1, /* timeout_msec */ +-                                            NULL, /* GCancellable */ +-                                            error); +-      if (result == NULL) +-        goto out; +-      g_variant_get (result, "(&o)", &session_id); +-      session = polkit_unix_session_new (session_id); +-      g_variant_unref (result); ++#ifdef HAVE_SYSTEMD ++      if (monitor->sd_source != NULL) ++        { ++          if (sd_pid_get_session (pid, &session_id) < 0) ++            goto out; ++ ++          session = polkit_unix_session_new (session_id); ++          free (session_id); ++        } ++      else ++#endif ++        { ++          result = g_dbus_connection_call_sync (monitor->system_bus, ++                                                "org.freedesktop.ConsoleKit", ++                                                "/org/freedesktop/ConsoleKit/Manager", ++                                                "org.freedesktop.ConsoleKit.Manager", ++                                                "GetSessionForUnixProcess", ++                                                g_variant_new ("(u)", pid), ++                                                G_VARIANT_TYPE ("(o)"), ++                                                G_DBUS_CALL_FLAGS_NONE, ++                                                -1, /* timeout_msec */ ++                                                NULL, /* GCancellable */ ++                                                error); ++          if (result == NULL) ++            goto out; ++          g_variant_get (result, "(&o)", &session_id); ++          session = polkit_unix_session_new (session_id); ++          g_variant_unref (result); ++        } +     } +   else +     { +@@ -490,7 +664,22 @@ + polkit_backend_session_monitor_is_session_local  (PolkitBackendSessionMonitor *monitor, +                                                   PolkitSubject               *session) + { +-  return get_boolean (monitor, session, "is_local"); ++#ifdef HAVE_SYSTEMD ++  if (monitor->sd_source != NULL) ++    { ++      char *seat; ++ ++      if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat)) ++        { ++          free (seat); ++          return TRUE; ++        } ++ ++      return FALSE; ++    } ++  else ++#endif ++    return get_boolean (monitor, session, "is_local"); + } +  +  +@@ -498,6 +687,11 @@ + polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor, +                                                   PolkitSubject               *session) + { +-  return get_boolean (monitor, session, "is_active"); ++#ifdef HAVE_SYSTEMD ++  if (monitor->sd_source != NULL) ++    return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session))); ++  else ++#endif ++    return get_boolean (monitor, session, "is_active"); + } +  +diff -u -rN polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor-systemd.c polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor-systemd.c +--- polkit-0.104/src/polkitbackend/polkitbackendsessionmonitor-systemd.c	2012-01-03 16:03:47.000000000 +0100 ++++ polkit-0.104-systemd-fallback/src/polkitbackend/polkitbackendsessionmonitor-systemd.c	1970-01-01 01:00:00.000000000 +0100 +@@ -1,414 +0,0 @@ +-/* +- * Copyright (C) 2011 Red Hat, Inc. +- * +- * This library is free software; you can redistribute it and/or +- * modify it under the terms of the GNU Lesser General Public +- * License as published by the Free Software Foundation; either +- * version 2 of the License, or (at your option) any later version. +- * +- * This library is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +- * Lesser General Public License for more details. +- * +- * You should have received a copy of the GNU Lesser General +- * Public License along with this library; if not, write to the +- * Free Software Foundation, Inc., 59 Temple Place, Suite 330, +- * Boston, MA 02111-1307, USA. +- * +- * Author: Matthias Clasen +- */ +- +-#include "config.h" +-#include <errno.h> +-#include <pwd.h> +-#include <grp.h> +-#include <string.h> +-#include <glib/gstdio.h> +-#include <systemd/sd-login.h> +-#include <stdlib.h> +- +-#include <polkit/polkit.h> +-#include "polkitbackendsessionmonitor.h" +- +-/* <internal> +- * SECTION:polkitbackendsessionmonitor +- * @title: PolkitBackendSessionMonitor +- * @short_description: Monitor sessions +- * +- * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions. +- */ +- +-typedef struct +-{ +-  GSource source; +-  GPollFD pollfd; +-  sd_login_monitor *monitor; +-} SdSource; +- +-static gboolean +-sd_source_prepare (GSource *source, +-                   gint    *timeout) +-{ +-  *timeout = -1; +-  return FALSE; +-} +- +-static gboolean +-sd_source_check (GSource *source) +-{ +-  SdSource *sd_source = (SdSource *)source; +- +-  return sd_source->pollfd.revents != 0; +-} +- +-static gboolean +-sd_source_dispatch (GSource     *source, +-                    GSourceFunc  callback, +-                    gpointer     user_data) +- +-{ +-  SdSource *sd_source = (SdSource *)source; +-  gboolean ret; +- +-  g_warn_if_fail (callback != NULL); +- +-  ret = (*callback) (user_data); +- +-  sd_login_monitor_flush (sd_source->monitor); +- +-  return ret; +-} +- +-static void +-sd_source_finalize (GSource *source) +-{ +-  SdSource *sd_source = (SdSource*)source; +- +-  sd_login_monitor_unref (sd_source->monitor); +-} +- +-static GSourceFuncs sd_source_funcs = { +-  sd_source_prepare, +-  sd_source_check, +-  sd_source_dispatch, +-  sd_source_finalize +-}; +- +-static GSource * +-sd_source_new (void) +-{ +-  GSource *source; +-  SdSource *sd_source; +-  int ret; +- +-  source = g_source_new (&sd_source_funcs, sizeof (SdSource)); +-  sd_source = (SdSource *)source; +- +-  if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) +-    { +-      g_printerr ("Error getting login monitor: %d", ret); +-    } +-  else +-    { +-      sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor); +-      sd_source->pollfd.events = G_IO_IN; +-      g_source_add_poll (source, &sd_source->pollfd); +-    } +- +-  return source; +-} +- +-struct _PolkitBackendSessionMonitor +-{ +-  GObject parent_instance; +- +-  GDBusConnection *system_bus; +- +-  GSource *sd_source; +-}; +- +-struct _PolkitBackendSessionMonitorClass +-{ +-  GObjectClass parent_class; +- +-  void (*changed) (PolkitBackendSessionMonitor *monitor); +-}; +- +- +-enum +-{ +-  CHANGED_SIGNAL, +-  LAST_SIGNAL, +-}; +- +-static guint signals[LAST_SIGNAL] = {0}; +- +-G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT); +- +-/* ---------------------------------------------------------------------------------------------------- */ +- +-static gboolean +-sessions_changed (gpointer user_data) +-{ +-  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data); +- +-  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); +- +-  return TRUE; +-} +- +- +-static void +-polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) +-{ +-  GError *error; +- +-  error = NULL; +-  monitor->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); +-  if (monitor->system_bus == NULL) +-    { +-      g_printerr ("Error getting system bus: %s", error->message); +-      g_error_free (error); +-    } +- +-  monitor->sd_source = sd_source_new (); +-  g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL); +-  g_source_attach (monitor->sd_source, NULL); +-} +- +-static void +-polkit_backend_session_monitor_finalize (GObject *object) +-{ +-  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (object); +- +-  if (monitor->system_bus != NULL) +-    g_object_unref (monitor->system_bus); +- +-  if (monitor->sd_source != NULL) +-    { +-      g_source_destroy (monitor->sd_source); +-      g_source_unref (monitor->sd_source); +-    } +- +-  if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL) +-    G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object); +-} +- +-static void +-polkit_backend_session_monitor_class_init (PolkitBackendSessionMonitorClass *klass) +-{ +-  GObjectClass *gobject_class; +- +-  gobject_class = G_OBJECT_CLASS (klass); +- +-  gobject_class->finalize = polkit_backend_session_monitor_finalize; +- +-  /** +-   * PolkitBackendSessionMonitor::changed: +-   * @monitor: A #PolkitBackendSessionMonitor +-   * +-   * Emitted when something changes. +-   */ +-  signals[CHANGED_SIGNAL] = g_signal_new ("changed", +-                                          POLKIT_BACKEND_TYPE_SESSION_MONITOR, +-                                          G_SIGNAL_RUN_LAST, +-                                          G_STRUCT_OFFSET (PolkitBackendSessionMonitorClass, changed), +-                                          NULL,                   /* accumulator      */ +-                                          NULL,                   /* accumulator data */ +-                                          g_cclosure_marshal_VOID__VOID, +-                                          G_TYPE_NONE, +-                                          0); +-} +- +-PolkitBackendSessionMonitor * +-polkit_backend_session_monitor_new (void) +-{ +-  PolkitBackendSessionMonitor *monitor; +- +-  monitor = POLKIT_BACKEND_SESSION_MONITOR (g_object_new (POLKIT_BACKEND_TYPE_SESSION_MONITOR, NULL)); +- +-  return monitor; +-} +- +-/* ---------------------------------------------------------------------------------------------------- */ +- +-GList * +-polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor) +-{ +-  /* TODO */ +-  return NULL; +-} +- +-/* ---------------------------------------------------------------------------------------------------- */ +- +-/** +- * polkit_backend_session_monitor_get_user: +- * @monitor: A #PolkitBackendSessionMonitor. +- * @subject: A #PolkitSubject. +- * @error: Return location for error. +- * +- * Gets the user corresponding to @subject or %NULL if no user exists. +- * +- * Returns: %NULL if @error is set otherwise a #PolkitUnixUser that should be freed with g_object_unref(). +- */ +-PolkitIdentity * +-polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor  *monitor, +-                                                     PolkitSubject                *subject, +-                                                     GError                      **error) +-{ +-  PolkitIdentity *ret; +-  guint32 uid; +- +-  ret = NULL; +- +-  if (POLKIT_IS_UNIX_PROCESS (subject)) +-    { +-      uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)); +-      if ((gint) uid == -1) +-        { +-          g_set_error (error, +-                       POLKIT_ERROR, +-                       POLKIT_ERROR_FAILED, +-                       "Unix process subject does not have uid set"); +-          goto out; +-        } +-      ret = polkit_unix_user_new (uid); +-    } +-  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) +-    { +-      GVariant *result; +- +-      result = g_dbus_connection_call_sync (monitor->system_bus, +-                                            "org.freedesktop.DBus", +-                                            "/org/freedesktop/DBus", +-                                            "org.freedesktop.DBus", +-                                            "GetConnectionUnixUser", +-                                            g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))), +-                                            G_VARIANT_TYPE ("(u)"), +-                                            G_DBUS_CALL_FLAGS_NONE, +-                                            -1, /* timeout_msec */ +-                                            NULL, /* GCancellable */ +-                                            error); +-      if (result == NULL) +-        goto out; +-      g_variant_get (result, "(u)", &uid); +-      g_variant_unref (result); +- +-      ret = polkit_unix_user_new (uid); +-    } +-  else if (POLKIT_IS_UNIX_SESSION (subject)) +-    { +- +-      if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0) +-        { +-          g_set_error (error, +-                       POLKIT_ERROR, +-                       POLKIT_ERROR_FAILED, +-                       "Error getting uid for session"); +-          goto out; +-        } +- +-      ret = polkit_unix_user_new (uid); +-    } +- +- out: +-  return ret; +-} +- +-/** +- * polkit_backend_session_monitor_get_session_for_subject: +- * @monitor: A #PolkitBackendSessionMonitor. +- * @subject: A #PolkitSubject. +- * @error: Return location for error. +- * +- * Gets the session corresponding to @subject or %NULL if no session exists. +- * +- * Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref(). +- */ +-PolkitSubject * +-polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor, +-                                                        PolkitSubject               *subject, +-                                                        GError                     **error) +-{ +-  PolkitSubject *session; +- +-  session = NULL; +- +-  if (POLKIT_IS_UNIX_PROCESS (subject)) +-    { +-      gchar *session_id; +-      pid_t pid; +- +-      pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)); +-      if (sd_pid_get_session (pid, &session_id) < 0) +-        goto out; +- +-      session = polkit_unix_session_new (session_id); +-      free (session_id); +-    } +-  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) +-    { +-      guint32 pid; +-      gchar *session_id; +-      GVariant *result; +- +-      result = g_dbus_connection_call_sync (monitor->system_bus, +-                                            "org.freedesktop.DBus", +-                                            "/org/freedesktop/DBus", +-                                            "org.freedesktop.DBus", +-                                            "GetConnectionUnixProcessID", +-                                            g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))), +-                                            G_VARIANT_TYPE ("(u)"), +-                                            G_DBUS_CALL_FLAGS_NONE, +-                                            -1, /* timeout_msec */ +-                                            NULL, /* GCancellable */ +-                                            error); +-      if (result == NULL) +-        goto out; +-      g_variant_get (result, "(u)", &pid); +-      g_variant_unref (result); +- +-      if (sd_pid_get_session (pid, &session_id) < 0) +-        goto out; +- +-      session = polkit_unix_session_new (session_id); +-      free (session_id); +-    } +-  else +-    { +-      g_set_error (error, +-                   POLKIT_ERROR, +-                   POLKIT_ERROR_NOT_SUPPORTED, +-                   "Cannot get user for subject of type %s", +-                   g_type_name (G_TYPE_FROM_INSTANCE (subject))); +-    } +- +- out: +- +-  return session; +-} +- +-gboolean +-polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor, +-                                                 PolkitSubject               *session) +-{ +-  char *seat; +- +-  if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat)) +-    { +-      free (seat); +-      return TRUE; +-    } +- +-  return FALSE; +-} +- +- +-gboolean +-polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor, +-                                                  PolkitSubject               *session) +-{ +-  return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session))); +-} +- | 
