Commit message: Fix CVE-2018-1116: Trusting client-supplied UID

As part of CVE-2013-4288, the D-Bus clients were allowed (and
encouraged) to submit the UID of the subject of authorization checks
to avoid races against UID changes (notably using executables
set-UID to root).

However, that also allowed any client to submit an arbitrary UID, and
that could be used to bypass "can only ask about / affect the same UID"
checks in CheckAuthorization / RegisterAuthenticationAgent /
UnregisterAuthenticationAgent.  This allowed an attacker:

- With CheckAuthorization, to cause the registered authentication
  agent in victim's session to pop up a dialog, or to determine whether
  the victim currently has a temporary authorization to perform an
  operation.

  (In principle, the attacker can also determine whether JavaScript
  rules allow the victim process to perform an operation; however,
  usually rules base their decisions on information determined from
  the supplied UID, so the attacker usually won't learn anything new.)

- With RegisterAuthenticationAgent, to prevent the victim's
  authentication agent to work (for a specific victim process),
  or to learn about which operations requiring authorization
  the victim is attempting.

To fix this, expose internal _polkit_unix_process_get_owner() /
obsolete polkit_unix_process_get_owner() as a private
polkit_unix_process_get_racy_uid__() (being more explicit about the
dangers on relying on it), and use it in
polkit_backend_session_monitor_get_user_for_subject() to return
a boolean indicating whether the subject UID may be caller-chosen.

Then, in the permission checks that require the subject to be
equal to the caller, fail on caller-chosen UIDs (and continue
through the pre-existing code paths which allow root, or root-designated
server processes, to ask about arbitrary subjects.)

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
CVE: CVE-2018-1116
CWE: CWE-200
Vulnerability description: A flaw was found in polkit before version 0.116. The implementation of the polkit_backend_interactive_authority_check_authorization function in polkitd allows to test for authentication and trigger authentication of unrelated processes owned by other users. This may result in a local DoS and information disclosure.

Project: polkit
File: polkitunixprocess.c

get_kinfo_proc (pid_t pid, struct kinfo_proc *p)
{
  int mib[4];
  size_t len;

  len = 4;
  sysctlnametomib ("kern.proc.pid", mib, &len);

  len = sizeof (struct kinfo_proc);
  mib[3] = pid;

  if (sysctl (mib, 4, p, &len, NULL, 0) == -1)
    return FALSE;

  return TRUE;
}

Project: polkit

get_kinfo_proc (gint pid,
#ifdef HAVE_NETBSD
                struct kinfo_proc2 *p)
#else
                struct kinfo_proc *p)
#endif
{
  int name[6];
  u_int namelen;
  size_t sz;

  sz = sizeof(*p);
  namelen = 0;
  name[namelen++] = CTL_KERN;
#ifdef HAVE_NETBSD
  name[namelen++] = KERN_PROC2;
#else
  name[namelen++] = KERN_PROC;
#endif
  name[namelen++] = KERN_PROC_PID;
  name[namelen++] = pid;
  name[namelen++] = sz;
  name[namelen++] = 1;

  if (sysctl (name, namelen, p, &sz, NULL, 0) == -1)
    return FALSE;

  return TRUE;
}

Project: polkit
File: polkitunixprocess.c

get_start_time_for_pid (pid_t    pid,
                        GError **error)
{
  guint64 start_time;
#if !defined(HAVE_FREEBSD) && !defined(HAVE_NETBSD) && !defined(HAVE_OPENBSD)
  gchar *filename;
  gchar *contents;
  size_t length;
  gchar **tokens;
  guint num_tokens;
  gchar *p;
  gchar *endp;

  start_time = 0;
  contents = NULL;

  filename = g_strdup_printf ("/proc/%d/stat", pid);

  if (!g_file_get_contents (filename, &contents, &length, error))
    goto out;

  /* start time is the token at index 19 after the '(process name)' entry - since only this
   * field can contain the ')' character, search backwards for this to avoid malicious
   * processes trying to fool us
   */
  p = strrchr (contents, ')');
  if (p == NULL)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_FAILED,
                   "Error parsing file %s",
                   filename);
      goto out;
    }
  p += 2; /* skip ') ' */
  if (p - contents >= (int) length)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_FAILED,
                   "Error parsing file %s",
                   filename);
      goto out;
    }

  tokens = g_strsplit (p, " ", 0);

  num_tokens = g_strv_length (tokens);

  if (num_tokens < 20)
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_FAILED,
                   "Error parsing file %s",
                   filename);
      goto out;
    }

  start_time = strtoull (tokens[19], &endp, 10);
  if (endp == tokens[19])
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_FAILED,
                   "Error parsing file %s",
                   filename);
      goto out;
    }

  g_strfreev (tokens);

 out:
  g_free (filename);
  g_free (contents);
#else
#ifdef HAVE_NETBSD
  struct kinfo_proc2 p;
#else
  struct kinfo_proc p;
#endif

  start_time = 0;

  if (! get_kinfo_proc (pid, &p))
    {
      g_set_error (error,
                   POLKIT_ERROR,
                   POLKIT_ERROR_FAILED,
                   "Error obtaining start time for %d (%s)",
                   (gint) pid,
                   g_strerror (errno));
      goto out;
    }

#ifdef HAVE_FREEBSD
  start_time = (guint64) p.ki_start.tv_sec;
#else
  start_time = (guint64) p.p_ustart_sec;
#endif

out:
#endif

  return start_time;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

_polkit_subject_get_cmdline (PolkitSubject *subject)
{
  PolkitSubject *process;
  gchar *ret;
  gint pid;
  gchar *filename;
  gchar *contents;
  gsize contents_len;
  GError *error;
  guint n;

  g_return_val_if_fail (subject != NULL, NULL);

  error = NULL;

  ret = NULL;
  process = NULL;
  filename = NULL;
  contents = NULL;

  if (POLKIT_IS_UNIX_PROCESS (subject))
    {
      process = g_object_ref (subject);
    }
  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
    {
      process = polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject),
                                                         NULL,
                                                         &error);
      if (process == NULL)
        {
          g_printerr ("Error getting process for system bus name `%s': %s\n",
                      polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject)),
                      error->message);
          g_error_free (error);
          goto out;
        }
    }
  else
    {
      g_warning ("Unknown subject type passed to _polkit_subject_get_cmdline()");
      goto out;
    }

  pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (process));

  filename = g_strdup_printf ("/proc/%d/cmdline", pid);

  if (!g_file_get_contents (filename,
                            &contents,
                            &contents_len,
                            &error))
    {
      g_printerr ("Error opening `%s': %s\n",
                  filename,
                  error->message);
      g_error_free (error);
      goto out;
    }

  if (contents == NULL || contents_len == 0)
    {
      goto out;
    }
  else
    {
      /* The kernel uses '\0' to separate arguments - replace those with a space. */
      for (n = 0; n < contents_len - 1; n++)
        {
          if (contents[n] == '\0')
            contents[n] = ' ';
        }
      ret = g_strdup (contents);
      g_strstrip (ret);
    }

 out:
  g_free (filename);
  g_free (contents);
  if (process != NULL)
    g_object_unref (process);
  return ret;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

action_pool_changed (PolkitBackendActionPool *action_pool,
                     PolkitBackendInteractiveAuthority *authority)
{
  g_signal_emit_by_name (authority, "changed");
}

Project: polkit
File: polkitbackendinteractiveauthority.c

check_authorization_challenge_cb (AuthenticationAgent         *agent,
                                  PolkitSubject               *subject,
                                  PolkitIdentity              *user_of_subject,
                                  PolkitSubject               *caller,
                                  PolkitBackendInteractiveAuthority *authority,
                                  const gchar                 *action_id,
                                  PolkitDetails               *details,
                                  PolkitImplicitAuthorization  implicit_authorization,
                                  gboolean                     authentication_success,
                                  gboolean                     was_dismissed,
                                  PolkitIdentity              *authenticated_identity,
                                  gpointer                     user_data)
{
  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
  PolkitBackendInteractiveAuthorityPrivate *priv;
  PolkitAuthorizationResult *result;
  gchar *scope_str;
  gchar *subject_str;
  gchar *user_of_subject_str;
  gchar *authenticated_identity_str;
  gchar *subject_cmdline;
  gboolean is_temp;

  priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);

  result = NULL;

  scope_str = polkit_subject_to_string (agent->scope);
  subject_str = polkit_subject_to_string (subject);
  user_of_subject_str = polkit_identity_to_string (user_of_subject);
  authenticated_identity_str = NULL;
  if (authenticated_identity != NULL)
    authenticated_identity_str = polkit_identity_to_string (authenticated_identity);

  subject_cmdline = _polkit_subject_get_cmdline (subject);
  if (subject_cmdline == NULL)
    subject_cmdline = g_strdup ("<unknown>");

  g_debug ("In check_authorization_challenge_cb\n"
           "  subject                %s\n"
           "  action_id              %s\n"
           "  was_dismissed          %d\n"
           "  authentication_success %d\n",
           subject_str,
           action_id,
           was_dismissed,
           authentication_success);

  if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
      implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
    polkit_details_insert (details, "polkit.retains_authorization_after_challenge", "true");

  is_temp = FALSE;
  if (authentication_success)
    {
      /* store temporary authorization depending on value of implicit_authorization */
      if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
          implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
        {
          const gchar *id;

          is_temp = TRUE;

          id = temporary_authorization_store_add_authorization (priv->temporary_authorization_store,
                                                                subject,
                                                                authentication_agent_get_scope (agent),
                                                                action_id);

          polkit_details_insert (details, "polkit.temporary_authorization_id", id);

          /* we've added a temporary authorization, let the user know */
          g_signal_emit_by_name (authority, "changed");
        }
      result = polkit_authorization_result_new (TRUE, FALSE, details);
    }
  else
    {
      /* TODO: maybe return set is_challenge? */
      if (was_dismissed)
        polkit_details_insert (details, "polkit.dismissed", "true");
      result = polkit_authorization_result_new (FALSE, FALSE, details);
    }

  /* Log the event */
  if (authentication_success)
    {
      if (is_temp)
        {
          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                        "Operator of %s successfully authenticated as %s to gain "
                                        "TEMPORARY authorization for action %s for %s [%s] (owned by %s)",
                                        scope_str,
                                        authenticated_identity_str,
                                        action_id,
                                        subject_str,
                                        subject_cmdline,
                                        user_of_subject_str);
        }
      else
        {
          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                        "Operator of %s successfully authenticated as %s to gain "
                                        "ONE-SHOT authorization for action %s for %s [%s] (owned by %s)",
                                        scope_str,
                                        authenticated_identity_str,
                                        action_id,
                                        subject_str,
                                        subject_cmdline,
                                        user_of_subject_str);
        }
    }
  else
    {
      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                    "Operator of %s FAILED to authenticate to gain "
                                    "authorization for action %s for %s [%s] (owned by %s)",
                                    scope_str,
                                    action_id,
                                    subject_str,
                                    subject_cmdline,
                                    user_of_subject_str);
    }

  /* log_result (authority, action_id, subject, caller, result); */

  g_simple_async_result_set_op_res_gpointer (simple,
                                             result,
                                             g_object_unref);
  g_simple_async_result_complete (simple);
  g_object_unref (simple);

  g_free (subject_cmdline);
  g_free (authenticated_identity_str);
  g_free (user_of_subject_str);
  g_free (subject_str);
  g_free (scope_str);
}

Project: polkit
File: polkitbackendinteractiveauthority.c

identity_is_root_user (PolkitIdentity *user)
{
  if (!POLKIT_IS_UNIX_USER (user))
    return FALSE;
  return polkit_unix_user_get_uid (POLKIT_UNIX_USER (user)) == 0;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

may_identity_check_authorization (PolkitBackendInteractiveAuthority   *interactive_authority,
                                  const gchar                         *action_id,
                                  PolkitIdentity                      *identity)
{
  PolkitBackendInteractiveAuthorityPrivate *priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);
  gboolean ret = FALSE;
  PolkitActionDescription *action_desc = NULL;
  const gchar *owners = NULL;
  gchar **tokens = NULL;
  guint n;

  /* uid 0 may check anything */
  if (identity_is_root_user (identity))
    {
      ret = TRUE;
      goto out;
    }

  action_desc = polkit_backend_action_pool_get_action (priv->action_pool, action_id, NULL);
  if (action_desc == NULL)
    goto out;

  owners = polkit_action_description_get_annotation (action_desc, "org.freedesktop.policykit.owner");
  if (owners == NULL)
    goto out;

  tokens = g_strsplit (owners, " ", 0);
  for (n = 0; tokens != NULL && tokens[n] != NULL; n++)
    {
      PolkitIdentity *owner_identity;
      GError *error = NULL;
      owner_identity = polkit_identity_from_string (tokens[n], &error);
      if (owner_identity == NULL)
        {
          g_warning ("Error parsing owner identity %d of action_id %s: %s (%s, %d)",
                     n, action_id, error->message, g_quark_to_string (error->domain), error->code);
          g_error_free (error);
          continue;
        }
      if (polkit_identity_equal (identity, owner_identity))
        {
          ret = TRUE;
          g_object_unref (owner_identity);
          goto out;
        }
      g_object_unref (owner_identity);
    }

 out:
  g_clear_object (&action_desc);
  g_strfreev (tokens);

  return ret;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

on_name_owner_changed_signal (GDBusConnection *connection,
                              const gchar     *sender_name,
                              const gchar     *object_path,
                              const gchar     *interface_name,
                              const gchar     *signal_name,
                              GVariant        *parameters,
                              gpointer         user_data)
{
  PolkitBackendInteractiveAuthority *authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (user_data);
  const gchar *name;
  const gchar *old_owner;
  const gchar *new_owner;

  g_variant_get (parameters,
                 "(&s&s&s)",
                 &name,
                 &old_owner,
                 &new_owner);

  polkit_backend_interactive_authority_system_bus_name_owner_changed (authority,
                                                                      name,
                                                                      old_owner,
                                                                      new_owner);
}

Project: polkit
File: polkitbackendinteractiveauthority.c

on_session_monitor_changed (PolkitBackendSessionMonitor *monitor,
                            gpointer                     user_data)
{
  PolkitBackendInteractiveAuthority *authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (user_data);
  g_signal_emit_by_name (authority, "changed");
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_check_authorization_finish (PolkitBackendAuthority  *authority,
                                                                 GAsyncResult            *res,
                                                                 GError                 **error)
{
  GSimpleAsyncResult *simple;
  PolkitAuthorizationResult *result;

  simple = G_SIMPLE_ASYNC_RESULT (res);

  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_backend_interactive_authority_check_authorization);

  result = NULL;

  if (g_simple_async_result_propagate_error (simple, error))
    goto out;

  result = g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));

 out:
  return result;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_class_init (PolkitBackendInteractiveAuthorityClass *klass)
{
  GObjectClass *gobject_class;
  PolkitBackendAuthorityClass *authority_class;

  gobject_class = G_OBJECT_CLASS (klass);
  authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);

  gobject_class->finalize = polkit_backend_interactive_authority_finalize;

  authority_class->get_name                        = polkit_backend_interactive_authority_get_name;
  authority_class->get_version                     = polkit_backend_interactive_authority_get_version;
  authority_class->get_features                    = polkit_backend_interactive_authority_get_features;
  authority_class->enumerate_actions               = polkit_backend_interactive_authority_enumerate_actions;
  authority_class->check_authorization             = polkit_backend_interactive_authority_check_authorization;
  authority_class->check_authorization_finish      = polkit_backend_interactive_authority_check_authorization_finish;
  authority_class->register_authentication_agent   = polkit_backend_interactive_authority_register_authentication_agent;
  authority_class->unregister_authentication_agent = polkit_backend_interactive_authority_unregister_authentication_agent;
  authority_class->authentication_agent_response   = polkit_backend_interactive_authority_authentication_agent_response;
  authority_class->enumerate_temporary_authorizations = polkit_backend_interactive_authority_enumerate_temporary_authorizations;
  authority_class->revoke_temporary_authorizations = polkit_backend_interactive_authority_revoke_temporary_authorizations;
  authority_class->revoke_temporary_authorization_by_id = polkit_backend_interactive_authority_revoke_temporary_authorization_by_id;



  g_type_class_add_private (klass, sizeof (PolkitBackendInteractiveAuthorityPrivate));
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_enumerate_actions (PolkitBackendAuthority   *authority,
                                                  PolkitSubject            *caller,
                                                  const gchar              *interactivee,
                                                  GError                  **error)
{
  PolkitBackendInteractiveAuthority *interactive_authority;
  PolkitBackendInteractiveAuthorityPrivate *priv;
  GList *actions;

  interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority);
  priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);

  actions = polkit_backend_action_pool_get_all_actions (priv->action_pool, interactivee);

  return actions;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_finalize (GObject *object)
{
  PolkitBackendInteractiveAuthority *interactive_authority;
  PolkitBackendInteractiveAuthorityPrivate *priv;

  interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (object);
  priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority);

  if (priv->name_owner_changed_signal_id > 0)
    g_dbus_connection_signal_unsubscribe (priv->system_bus_connection, priv->name_owner_changed_signal_id);

  if (priv->system_bus_connection != NULL)
    g_object_unref (priv->system_bus_connection);

  if (priv->action_pool != NULL)
    g_object_unref (priv->action_pool);

  if (priv->session_monitor != NULL)
    g_object_unref (priv->session_monitor);

  temporary_authorization_store_free (priv->temporary_authorization_store);

  g_hash_table_unref (priv->hash_scope_to_authentication_agent);

  G_OBJECT_CLASS (polkit_backend_interactive_authority_parent_class)->finalize (object);
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_get_features (PolkitBackendAuthority *authority)
{
  return POLKIT_AUTHORITY_FEATURES_TEMPORARY_AUTHORIZATION;
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_get_name (PolkitBackendAuthority *authority)
{
  return "interactive";
}

Project: polkit
File: polkitbackendinteractiveauthority.c

polkit_backend_interactive_authority_get_version (PolkitBackendAuthority *authority)
{
  return PACKAGE_VERSION;
}

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

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

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

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

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor)
{
  /* TODO */
  return NULL;
}

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

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

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

polkit_backend_session_monitor_new (void)
{
  PolkitBackendSessionMonitor *monitor;

  monitor = POLKIT_BACKEND_SESSION_MONITOR (g_object_new (POLKIT_BACKEND_TYPE_SESSION_MONITOR, NULL));

  return monitor;
}

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

sd_source_check (GSource *source)
{
  SdSource *sd_source = (SdSource *)source;

  return sd_source->pollfd.revents != 0;
}

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

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

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

sd_source_finalize (GSource *source)
{
  SdSource *sd_source = (SdSource*)source;

  sd_login_monitor_unref (sd_source->monitor);
}

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

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

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

sd_source_prepare (GSource *source,
                   gint    *timeout)
{
  *timeout = -1;
  return FALSE;
}

Project: polkit
File: polkitbackendsessionmonitor-systemd.c

sessions_changed (gpointer user_data)
{
  PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);

  g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);

  return TRUE;
}

Project: polkit
File: polkitbackendsessionmonitor.c

ensure_database (PolkitBackendSessionMonitor  *monitor,
                 GError                      **error)
{
  gboolean ret = FALSE;

  if (monitor->database != NULL)
    {
      struct stat statbuf;

      if (stat (CKDB_PATH, &statbuf) != 0)
        {
          g_set_error (error,
                       G_IO_ERROR,
                       g_io_error_from_errno (errno),
                       "Error statting file " CKDB_PATH " to check timestamp: %s",
                       strerror (errno));
          goto out;
        }
      if (statbuf.st_mtime == monitor->database_mtime)
        {
          ret = TRUE;
          goto out;
        }
    }

  ret = reload_database (monitor, error);

 out:
  return ret;
}

Project: polkit
File: polkitbackendsessionmonitor.c

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->database_monitor != NULL)
    g_object_unref (monitor->database_monitor);

  if (monitor->database != NULL)
    g_key_file_free (monitor->database);

  if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL)
    G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object);
}