static void child_watch_died (GPid pid, gint status, gpointer user_data) { PidData *pid_data = user_data; g_autoptr(GVariant) signal_variant = NULL; g_debug ("Client Pid %d died", pid_data->pid); signal_variant = g_variant_ref_sink (g_variant_new ("(uu)", pid, status)); g_dbus_connection_emit_signal (session_bus, pid_data->client, "/org/freedesktop/portal/Flatpak", "org.freedesktop.portal.Flatpak", "SpawnExited", signal_variant, NULL); /* This frees the pid_data, so be careful */ g_hash_table_remove (client_pid_data_hash, GUINT_TO_POINTER (pid_data->pid)); /* This might have caused us to go to idle (zero children) */ schedule_idle_callback (); }
int main (int argc, char **argv) { gchar exe_path[PATH_MAX+1]; ssize_t exe_path_len; gboolean replace; gboolean verbose; gboolean show_version; GBusNameOwnerFlags flags; GOptionContext *context; g_autoptr(GError) error = NULL; const GOptionEntry options[] = { { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "Replace old daemon.", NULL }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Enable debug output.", NULL }, { "session", 0, 0, G_OPTION_ARG_NONE, &on_session_bus, "Run in session, not system scope (for tests).", NULL }, { "no-idle-exit", 0, 0, G_OPTION_ARG_NONE, &no_idle_exit, "Don't exit when idle.", NULL }, { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, "Show program version.", NULL}, { NULL } }; setlocale (LC_ALL, ""); g_setenv ("GIO_USE_VFS", "local", TRUE); g_set_prgname (argv[0]); g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, message_handler, NULL); context = g_option_context_new (""); g_option_context_set_summary (context, "Flatpak system helper"); g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE); replace = FALSE; verbose = FALSE; show_version = FALSE; if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("%s: %s", g_get_application_name(), error->message); g_printerr ("\n"); g_printerr ("Try \"%s --help\" for more information.", g_get_prgname ()); g_printerr ("\n"); g_option_context_free (context); return 1; } if (show_version) { g_print (PACKAGE_STRING "\n"); return 0; } if (verbose) g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL); authority = polkit_authority_get_sync (NULL, &error); if (authority == NULL) { g_printerr ("Can't get polkit authority: %s\n", error->message); return 1; } exe_path_len = readlink ("/proc/self/exe", exe_path, sizeof (exe_path) - 1); if (exe_path_len > 0) { exe_path[exe_path_len] = 0; GFileMonitor *monitor; g_autoptr(GFile) exe = NULL; g_autoptr(GError) local_error = NULL; exe = g_file_new_for_path (exe_path); monitor = g_file_monitor_file (exe, G_FILE_MONITOR_NONE, NULL, &local_error); if (monitor == NULL) g_warning ("Failed to set watch on %s: %s", exe_path, error->message); else g_signal_connect (monitor, "changed", G_CALLBACK (binary_file_changed_cb), NULL); } flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; if (replace) flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; name_owner_id = g_bus_own_name (on_session_bus ? G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM, "org.freedesktop.Flatpak.SystemHelper", flags, on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL); /* Ensure we don't idle exit */ schedule_idle_callback (); main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); return 0; }
static gboolean flatpak_authorize_method_handler (GDBusInterfaceSkeleton *interface, GDBusMethodInvocation *invocation, gpointer user_data) { const gchar *method_name = g_dbus_method_invocation_get_method_name (invocation); const gchar *sender = g_dbus_method_invocation_get_sender (invocation); GVariant *parameters = g_dbus_method_invocation_get_parameters (invocation); g_autoptr(AutoPolkitSubject) subject = polkit_system_bus_name_new (sender); g_autoptr(AutoPolkitDetails) details = polkit_details_new (); const gchar *action = NULL; gboolean authorized = FALSE; /* Ensure we don't idle exit */ schedule_idle_callback (); if (on_session_bus) { /* This is test code, make sure it never runs with privileges */ g_assert (geteuid () != 0); g_assert (getuid () != 0); g_assert (getegid () != 0); g_assert (getgid () != 0); authorized = TRUE; } else if (g_strcmp0 (method_name, "Deploy") == 0) { const char *ref, *origin; guint32 flags; gboolean is_update, is_app; g_variant_get_child (parameters, 1, "u", &flags); g_variant_get_child (parameters, 2, "&s", &ref); g_variant_get_child (parameters, 3, "&s", &origin); is_update = (flags & FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE) != 0; is_app = g_str_has_prefix (ref, "app/"); if (is_update) { if (is_app) action = "org.freedesktop.Flatpak.app-update"; else action = "org.freedesktop.Flatpak.runtime-update"; } else { if (is_app) action = "org.freedesktop.Flatpak.app-install"; else action = "org.freedesktop.Flatpak.runtime-install"; } polkit_details_insert (details, "origin", origin); polkit_details_insert (details, "ref", ref); } else if (g_strcmp0 (method_name, "DeployAppstream") == 0) { const char *arch, *origin; g_variant_get_child (parameters, 1, "&s", &origin); g_variant_get_child (parameters, 2, "&s", &arch); action = "org.freedesktop.Flatpak.appstream-update"; polkit_details_insert (details, "origin", origin); polkit_details_insert (details, "arch", arch); } else if (g_strcmp0 (method_name, "InstallBundle") == 0) { const char *path; g_variant_get_child (parameters, 0, "^&ay", &path); action = "org.freedesktop.Flatpak.install-bundle"; polkit_details_insert (details, "path", path); } else if (g_strcmp0 (method_name, "Uninstall") == 0) { const char *ref; gboolean is_app; g_variant_get_child (parameters, 1, "&s", &ref); is_app = g_str_has_prefix (ref, "app/"); if (is_app) action = "org.freedesktop.Flatpak.app-uninstall"; else action = "org.freedesktop.Flatpak.runtime-uninstall"; polkit_details_insert (details, "ref", ref); } else if (g_strcmp0 (method_name, "ConfigureRemote") == 0) { const char *remote; g_variant_get_child (parameters, 1, "&s", &remote); action = "org.freedesktop.Flatpak.configure-remote"; polkit_details_insert (details, "remote", remote); } if (action) { g_autoptr(AutoPolkitAuthorizationResult) result; g_autoptr(GError) error = NULL; result = polkit_authority_check_authorization_sync (authority, subject, action, details, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, NULL, &error); if (result == NULL) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Authorization error: %s", error->message); return FALSE; } authorized = polkit_authorization_result_get_is_authorized (result); } if (!authorized) { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, "Flatpak system operation %s not allowed for user", method_name); } return authorized; }