diff options
author | Ray Strode <rstrode@redhat.com> | 2008-05-09 14:44:01 +0000 |
---|---|---|
committer | Ray Strode <halfline@src.gnome.org> | 2008-05-09 14:44:01 +0000 |
commit | 1196f4aa6da632ceafd7bb2c9d19c0a2f9c403ae (patch) | |
tree | 90ecdaa9d121438fe6ba2e5cc372d0ecf36f4691 /gconf | |
parent | 21b7a298729ec253f196ba7cd92121af062862ff (diff) | |
download | gconf-1196f4aa6da632ceafd7bb2c9d19c0a2f9c403ae.tar.gz |
Tie gconf daemon to session bus and drop use daemon GetIOR() method
2008-05-09 Ray Strode <rstrode@redhat.com>
Tie gconf daemon to session bus and drop use daemon
GetIOR() method instead of /tmp/something/ior to
tell clients about ior (bugs 141138 and 507310)
* configure.in: depend on dbus
* gconf/gconfd.c (get_introspection_xml),
(bus_message_handler), (get_on_d_bus), (main):
Connect to message bus, take org.gnome.GConf name,
and export GetIOR() method. Quit, when session quits.
* Makefile.am:
* gconf/org.gnome.GConf.server.in: new service file to
support session bus activation
* gconf/gconf-sanity-check.c (offer_delete_locks):
Daemon doesn't have a lock anymore, so need to try to
blow it away.
* gconf/gcon-internals.c (read_current_server_and_set_warning),
(read_current_server), (gconf_get_current_lock_holder),
(gconf_daemon_blow_away_locks), (set_cloexec),
(close_fd_func): dropped functions dealing with files in /tmp
(get_ior), (gconf_get_server), (gconf_get_lock_or_current_holder),
(gconf_activate_server: call GetIOR method instead of of reading
/tmp/gconf-$USER/ior
svn path=/trunk/; revision=2589
Diffstat (limited to 'gconf')
-rw-r--r-- | gconf/Makefile.am | 8 | ||||
-rw-r--r-- | gconf/gconf-internals.c | 367 | ||||
-rw-r--r-- | gconf/gconf-sanity-check.c | 2 | ||||
-rw-r--r-- | gconf/gconfd.c | 183 | ||||
-rw-r--r-- | gconf/org.gnome.GConf.service.in | 3 |
5 files changed, 218 insertions, 345 deletions
diff --git a/gconf/Makefile.am b/gconf/Makefile.am index 0b223cae..ac023c86 100644 --- a/gconf/Makefile.am +++ b/gconf/Makefile.am @@ -121,11 +121,17 @@ libgconf_2_la_LDFLAGS = -version-info $(GCONF_CURRENT):$(GCONF_REVISION):$(GCONF libgconf_2_la_LIBADD = $(INTLLIBS) $(DEPENDENT_LIBS) -EXTRA_DIST=GConfX.idl default.path.in gconfmarshal.list regenerate-enum-header.sh regenerate-enum-footer.sh +EXTRA_DIST=GConfX.idl default.path.in org.gnome.GConf.service gconfmarshal.list regenerate-enum-header.sh regenerate-enum-footer.sh default.path: $(srcdir)/default.path.in sed -e 's,[@]sysgconfdir[@],$(sysgconfdir),g' \ <$(srcdir)/default.path.in >default.path +org.gnome.GConf.service: $(srcdir)/org.gnome.GConf.service.in + sed -e 's,[@]libexecdir[@],$(libexecdir),g' \ + <$(srcdir)/org.gnome.GConf.service.in >org.gnome.GConf.service + +servicedir = $(datadir)/dbus-1/services +service_DATA = org.gnome.GConf.service install-data-local: default.path $(mkinstalldirs) $(DESTDIR)$(sysgconfdir)/$(MAJOR_VERSION) diff --git a/gconf/gconf-internals.c b/gconf/gconf-internals.c index f078810d..d274fa89 100644 --- a/gconf/gconf-internals.c +++ b/gconf/gconf-internals.c @@ -36,6 +36,8 @@ #include <time.h> #include <math.h> +#include <dbus/dbus.h> + #ifdef G_OS_WIN32 #include <windows.h> #include <share.h> @@ -2418,107 +2420,101 @@ open_empty_locked_file (const gchar *directory, return fd; } -static ConfigServer -read_current_server_and_set_warning (const gchar *iorfile, - GString *warning) +static char * +get_ior (gboolean start_if_not_found, + GString *failure_log) { - FILE *fp; - - fp = g_fopen (iorfile, "r"); - - if (fp == NULL) - { - if (warning) - g_string_append_printf (warning, - _("IOR file '%s' not opened successfully, no gconfd located: %s"), - iorfile, g_strerror (errno)); + DBusMessage *message, *reply; + DBusConnection *connection; + DBusError bus_error; + char *ior; - return CORBA_OBJECT_NIL; - } - else /* successfully opened IOR file */ - { - char buf[2048] = { '\0' }; - const char *str = NULL; - - fgets (buf, sizeof (buf) - 2, fp); - fclose (fp); + dbus_error_init (&bus_error); + connection = dbus_bus_get (DBUS_BUS_SESSION, &bus_error); - /* The lockfile format is <pid>:<ior> for gconfd - * or <pid>:none for gconftool - */ - str = buf; - while (isdigit ((unsigned char) *str)) - ++str; + if (dbus_error_is_set (&bus_error)) { + if (failure_log) + g_string_append_printf (failure_log, + _("Failed to get connection to session: %s"), + bus_error.message); + dbus_error_free (&bus_error); + return NULL; + } - if (*str == ':') - ++str; - - if (str[0] == 'n' && - str[1] == 'o' && - str[2] == 'n' && - str[3] == 'e') - { - if (warning) - g_string_append_printf (warning, - _("gconftool or other non-gconfd process has the lock file '%s'"), - iorfile); + message = dbus_message_new_method_call ("org.gnome.GConf", + "/org/gnome/GConf", + "org.gnome.GConf", + "GetIOR"); + dbus_message_set_auto_start (message, start_if_not_found); + + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, + &bus_error); + dbus_message_unref (message); + + if (dbus_error_is_set (&bus_error)) { + if (failure_log) + g_string_append_printf (failure_log, + _("Could not send message to gconf daemon: %s"), + bus_error.message); + dbus_error_free (&bus_error); + return NULL; } - else /* file contains daemon IOR */ - { - CORBA_ORB orb; - CORBA_Environment ev; - ConfigServer server; - - CORBA_exception_init (&ev); - - orb = gconf_orb_get (); - if (orb == NULL) - { - if (warning) - g_string_append_printf (warning, - _("couldn't contact ORB to resolve existing gconfd object reference")); - return CORBA_OBJECT_NIL; - } - - server = CORBA_ORB_string_to_object (orb, (char*) str, &ev); - CORBA_exception_free (&ev); - - if (server == CORBA_OBJECT_NIL && - warning) - g_string_append_printf (warning, - _("Failed to convert IOR '%s' to an object reference"), - str); - - return server; + ior = NULL; + if (!dbus_message_get_args (reply, &bus_error, DBUS_TYPE_STRING, + &ior, DBUS_TYPE_INVALID)) { + if (failure_log) + g_string_append_printf (failure_log, + _("daemon gave errnoneous reply: %s"), + bus_error.message); + dbus_error_free (&bus_error); + return NULL; } - return CORBA_OBJECT_NIL; - } + ior = g_strdup (ior); + + dbus_message_unref (reply); + dbus_connection_unref (connection); + + return ior; } static ConfigServer -read_current_server (const gchar *iorfile, - gboolean warn_if_fail) +gconf_get_server (gboolean start_if_not_found, + GString *failure_log) { - GString *warning; ConfigServer server; - - if (warn_if_fail) - warning = g_string_new (NULL); - else - warning = NULL; + char *ior; + CORBA_ORB orb; + CORBA_Environment ev; - server = read_current_server_and_set_warning (iorfile, warning); + ior = get_ior (start_if_not_found, failure_log); - if (warning) + if (ior == NULL) { - if (warning->len > 0) - gconf_log (GCL_WARNING, "%s", warning->str); + return CORBA_OBJECT_NIL; + } - g_string_free (warning, TRUE); + CORBA_exception_init (&ev); + orb = gconf_orb_get (); + + if (orb == NULL) + { + if (failure_log) + g_string_append_printf (failure_log, + _("couldn't contact ORB to resolve existing gconfd object reference")); + return CORBA_OBJECT_NIL; } + server = CORBA_ORB_string_to_object (orb, (char*) ior, &ev); + CORBA_exception_free (&ev); + + if (server == CORBA_OBJECT_NIL && + failure_log) + g_string_append_printf (failure_log, + _("Failed to convert IOR '%s' to an object reference"), + ior); + return server; } @@ -2563,7 +2559,7 @@ gconf_get_lock_or_current_holder (const gchar *lock_directory, * it to the caller. Error is already set. */ if (current_server) - *current_server = read_current_server (lock->iorfile, TRUE); + *current_server = gconf_get_server (FALSE, NULL); gconf_lock_destroy (lock); @@ -2726,40 +2722,6 @@ gconf_release_lock (GConfLock *lock, return retval; } -/* This function doesn't try to see if the lock is valid or anything - * of the sort; it just reads it. It does do the object_to_string - */ -ConfigServer -gconf_get_current_lock_holder (const gchar *lock_directory, - GString *failure_log) -{ - char *iorfile; - ConfigServer server; - - iorfile = g_strconcat (lock_directory, "/ior", NULL); - server = read_current_server_and_set_warning (iorfile, failure_log); - g_free (iorfile); - return server; -} - -void -gconf_daemon_blow_away_locks (void) -{ - char *lock_directory; - char *iorfile; - - lock_directory = gconf_get_lock_dir (); - - iorfile = g_strconcat (lock_directory, "/ior", NULL); - - if (g_unlink (iorfile) < 0) - g_printerr (_("Failed to unlink lock file %s: %s\n"), - iorfile, g_strerror (errno)); - - g_free (iorfile); - g_free (lock_directory); -} - static CORBA_ORB gconf_orb = CORBA_OBJECT_NIL; CORBA_ORB @@ -2858,173 +2820,45 @@ gconf_get_lock_dir (void) return lock_dir; } -#if defined (F_SETFD) && defined (FD_CLOEXEC) - -#ifndef HAVE_FDWALK -static void -set_cloexec (gint fd) -{ - fcntl (fd, F_SETFD, FD_CLOEXEC); -#else -static int -set_cloexec (void *data, int fd) -{ - int *pipes = (int *)data; - - if (fd != pipes[1] && fd > 2) - fcntl (fd, F_SETFD, FD_CLOEXEC); - - return 0; -#endif -} - - -static void -close_fd_func (gpointer data) -{ - int *pipes = data; - -#ifndef HAVE_FDWALK - gint open_max; - gint i; - - open_max = sysconf (_SC_OPEN_MAX); - for (i = 3; i < open_max; i++) - { - /* don't close our write pipe */ - if (i != pipes[1]) - set_cloexec (i); - } -#else - (void) fdwalk(set_cloexec, (void *)pipes); -#endif -} - -#else - -#define close_fd_func NULL - -#endif - ConfigServer gconf_activate_server (gboolean start_if_not_found, GError **error) { ConfigServer server = CORBA_OBJECT_NIL; - int p[2] = { -1, -1 }; - char buf[1]; GError *tmp_err; - char *argv[3]; - char *gconfd_dir; - char *lock_dir; GString *failure_log; - struct stat statbuf; CORBA_Environment ev; - gboolean dir_accessible; failure_log = g_string_new (NULL); - gconfd_dir = gconf_get_daemon_dir (); - - dir_accessible = g_stat (gconfd_dir, &statbuf) >= 0; - - if (!dir_accessible && errno != ENOENT) - { - server = CORBA_OBJECT_NIL; - gconf_log (GCL_WARNING, _("Failed to stat %s: %s"), - gconfd_dir, g_strerror (errno)); - } - else if (dir_accessible) - { - g_string_append (failure_log, " 1: "); - lock_dir = gconf_get_lock_dir (); - server = gconf_get_current_lock_holder (lock_dir, failure_log); - g_free (lock_dir); - - /* Confirm server exists */ - CORBA_exception_init (&ev); - - if (!CORBA_Object_is_nil (server, &ev)) - { - ConfigServer_ping (server, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - { - server = CORBA_OBJECT_NIL; - - g_string_append_printf (failure_log, - _("Server ping error: %s"), - CORBA_exception_id (&ev)); - } - } - - CORBA_exception_free (&ev); - - if (server != CORBA_OBJECT_NIL) - { - g_string_free (failure_log, TRUE); - g_free (gconfd_dir); - return server; - } - } + g_string_append (failure_log, " 1: "); + server = gconf_get_server (start_if_not_found, failure_log); - g_free (gconfd_dir); + /* Confirm server exists */ + CORBA_exception_init (&ev); - if (start_if_not_found) + if (!CORBA_Object_is_nil (server, &ev)) { - /* Spawn server */ - if (pipe (p) < 0) - { - g_set_error (error, - GCONF_ERROR, - GCONF_ERROR_NO_SERVER, - _("Failed to create pipe for communicating with spawned gconf daemon: %s\n"), - g_strerror (errno)); - goto out; - } - - argv[0] = g_build_filename (GCONF_SERVERDIR, GCONFD, NULL); - argv[1] = g_strdup_printf ("%d", p[1]); - argv[2] = NULL; + ConfigServer_ping (server, &ev); - tmp_err = NULL; - if (!g_spawn_async (NULL, - argv, - NULL, - G_SPAWN_LEAVE_DESCRIPTORS_OPEN, - close_fd_func, - p, - NULL, - &tmp_err)) + if (ev._major != CORBA_NO_EXCEPTION) { - g_free (argv[0]); - g_free (argv[1]); - g_set_error (error, - GCONF_ERROR, - GCONF_ERROR_NO_SERVER, - _("Failed to launch configuration server: %s\n"), - tmp_err->message); - g_error_free (tmp_err); - goto out; - } - - g_free (argv[0]); - g_free (argv[1]); + server = CORBA_OBJECT_NIL; - /* If the server dies, we don't want to block indefinitely in - the read. */ - close (p[1]); - p[1] = -1; + g_string_append_printf (failure_log, + _("Server ping error: %s"), + CORBA_exception_id (&ev)); + } + } - /* Block until server starts up */ - read (p[0], buf, 1); + CORBA_exception_free (&ev); - g_string_append (failure_log, " 2: "); - lock_dir = gconf_get_lock_dir (); - server = gconf_get_current_lock_holder (lock_dir, failure_log); - g_free (lock_dir); + if (server != CORBA_OBJECT_NIL) + { + g_string_free (failure_log, TRUE); + return server; } - + out: if (server == CORBA_OBJECT_NIL && error && @@ -3037,11 +2871,6 @@ gconf_activate_server (gboolean start_if_not_found, g_string_free (failure_log, TRUE); - if (p[0] != -1) - close (p[0]); - if (p[1] != -1) - close (p[1]); - return server; } diff --git a/gconf/gconf-sanity-check.c b/gconf/gconf-sanity-check.c index 428a05ed..a88c9a04 100644 --- a/gconf/gconf-sanity-check.c +++ b/gconf/gconf-sanity-check.c @@ -395,8 +395,6 @@ offer_delete_locks (void) g_slist_free (addresses); - gconf_daemon_blow_away_locks (); - return TRUE; } diff --git a/gconf/gconfd.c b/gconf/gconfd.c index f5028879..470edc94 100644 --- a/gconf/gconfd.c +++ b/gconf/gconfd.c @@ -55,6 +55,8 @@ #endif #include <locale.h> +#include <dbus/dbus-glib-lowlevel.h> + /* This makes hash table safer when debugging */ #ifndef GCONF_ENABLE_DEBUG #define safe_g_hash_table_insert g_hash_table_insert @@ -497,57 +499,122 @@ gconf_get_poa (void) return the_poa; } -/* From ORBit2 */ -/* There is a DOS attack if another user creates - * the given directory and keeps us from creating - * it - */ -static gboolean -test_safe_tmp_dir (const char *dirname) +static const char * +get_introspection_xml (void) { -#ifndef G_OS_WIN32 - struct stat statbuf; - int fd; + return "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" + "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" + "<node>\n" + " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" + " <method name=\"Introspect\">\n" + " <arg name=\"introspection_xml\" direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " </interface>\n" + " <interface name=\"org.gnome.GConf\">\n" + " <method name=\"GetIOR\">\n" + " <arg name=\"ior\" direction=\"out\" type=\"s\"/>\n" + " </method>\n" + " </interface>\n" + "</node>\n"; +} - fd = open (dirname, O_RDONLY); - if (fd < 0) +static DBusHandlerResult +bus_message_handler (DBusConnection *connection, + DBusMessage *message, + GMainLoop *loop) +{ + DBusMessage *reply; + + reply = NULL; + + if (dbus_message_is_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")) { - gconf_log (GCL_WARNING, _("Failed to open %s: %s"), - dirname, g_strerror (errno)); - return FALSE; + gconf_main_quit (); + return DBUS_HANDLER_RESULT_HANDLED; } - - if (fstat (fd, &statbuf) != 0) + else if (dbus_message_is_method_call (message, + "org.freedesktop.DBus.Introspectable", + "Introspect")) { - gconf_log (GCL_WARNING, _("Failed to stat %s: %s"), - dirname, g_strerror (errno)); - close (fd); - return FALSE; + const char *introspection_xml; + + introspection_xml = get_introspection_xml (); + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &introspection_xml, + DBUS_TYPE_INVALID); + + } + else if (dbus_message_is_method_call (message, + "org.gnome.GConf", + "GetIOR")) + { + const char *ior; + + ior = gconf_get_daemon_ior (); + + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, &ior, DBUS_TYPE_INVALID); } - close (fd); - if (statbuf.st_uid != getuid ()) + if (reply != NULL) { - gconf_log (GCL_WARNING, _("Owner of %s is not the current user"), - dirname); - return FALSE; + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + return DBUS_HANDLER_RESULT_HANDLED; } - if ((statbuf.st_mode & (S_IRWXG|S_IRWXO)) || - !S_ISDIR (statbuf.st_mode)) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusConnection * +get_on_d_bus (void) +{ + DBusConnection *connection; + DBusError bus_error; + int result; + + dbus_error_init (&bus_error); + connection = dbus_bus_get (DBUS_BUS_SESSION, &bus_error); + + if (dbus_error_is_set (&bus_error)) { - gconf_log (GCL_WARNING, _("Bad permissions %lo on directory %s"), - (unsigned long) statbuf.st_mode & 07777, dirname); - return FALSE; + gconf_log (GCL_ERR, _("Could not connect to session bus: %s"), bus_error.message); + dbus_error_free (&bus_error); + return NULL; } -#else - /* FIXME: We can't get any useful information about the actual - * protection for the directory using stat(). We must use the Win32 - * API to check the owner and permissions (ACL). Later. - */ -#endif - - return TRUE; + + dbus_connection_setup_with_g_main (connection, NULL); + + if (!dbus_connection_add_filter (connection, (DBusHandleMessageFunction) + bus_message_handler, NULL, NULL)) + { + dbus_connection_unref (connection); + return NULL; + } + + dbus_connection_set_exit_on_disconnect (connection, FALSE); + + result = dbus_bus_request_name (connection, "org.gnome.GConf", + 0, &bus_error); + + if (dbus_error_is_set (&bus_error)) + { + gconf_log (GCL_WARNING, + _("Failed to get bus name for daemon, exiting: %s"), + bus_error.message); + dbus_error_free (&bus_error); + } + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) + { + dbus_connection_unref (connection); + return NULL; + } + + return connection; } int @@ -563,10 +630,9 @@ main(int argc, char** argv) gchar* ior; int exit_code = 0; GError *err; - char *lock_dir; - char *gconfd_dir; int dev_null_fd; int write_byte_fd; + DBusConnection *connection; _gconf_init_i18n (); setlocale (LC_ALL, ""); @@ -676,32 +742,9 @@ main(int argc, char** argv) gconf_set_daemon_ior (ior); CORBA_free (ior); - gconfd_dir = gconf_get_daemon_dir (); - lock_dir = gconf_get_lock_dir (); - - if (g_mkdir (gconfd_dir, 0700) < 0 && errno != EEXIST) - gconf_log (GCL_WARNING, _("Failed to create %s: %s"), - gconfd_dir, g_strerror (errno)); - - if (!test_safe_tmp_dir (gconfd_dir)) - { - err = g_error_new (GCONF_ERROR, - GCONF_ERROR_LOCK_FAILED, - _("Directory %s has a problem, gconfd can't use it"), - gconfd_dir); - daemon_lock = NULL; - } - else - { - err = NULL; - - daemon_lock = gconf_get_lock (lock_dir, &err); - } + connection = get_on_d_bus (); - g_free (gconfd_dir); - g_free (lock_dir); - - if (daemon_lock != NULL) + if (connection != NULL) { /* This loads backends and so on. It needs to be done before * we can handle any requests, so before we hit the @@ -725,14 +768,8 @@ main(int argc, char** argv) close (write_byte_fd); } - if (daemon_lock == NULL) + if (connection == NULL) { - g_assert (err); - - gconf_log (GCL_WARNING, _("Failed to get lock for daemon, exiting: %s"), - err->message); - g_error_free (err); - enter_shutdown (); shutdown_databases (); diff --git a/gconf/org.gnome.GConf.service.in b/gconf/org.gnome.GConf.service.in new file mode 100644 index 00000000..39f6e728 --- /dev/null +++ b/gconf/org.gnome.GConf.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.gnome.GConf +Exec=@libexecdir@/gconfd-2 |