From c509d0bc4781dac109998ee30ab9907a40eaf2cc Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Jan 13 2010 00:52:45 +0000 Subject: Copy a ton of F12 patches --- diff --git a/dbus-1.2.16-capability.patch b/dbus-1.2.16-capability.patch new file mode 100644 index 0000000..fe933f8 --- /dev/null +++ b/dbus-1.2.16-capability.patch @@ -0,0 +1,230 @@ +diff -urp dbus-1.2.16.orig/bus/selinux.c dbus-1.2.16/bus/selinux.c +--- dbus-1.2.16.orig/bus/selinux.c 2009-10-03 08:46:51.000000000 -0400 ++++ dbus-1.2.16/bus/selinux.c 2009-10-03 08:47:26.000000000 -0400 +@@ -45,6 +45,7 @@ + #include + #include + #ifdef HAVE_LIBAUDIT ++#include + #include + #endif /* HAVE_LIBAUDIT */ + #endif /* HAVE_SELINUX */ +@@ -143,13 +144,17 @@ log_callback (const char *fmt, ...) + #ifdef HAVE_LIBAUDIT + if (audit_fd >= 0) + { +- char buf[PATH_MAX*2]; ++ capng_get_caps_process(); ++ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_AUDIT_WRITE)) ++ { ++ char buf[PATH_MAX*2]; + +- /* FIXME: need to change this to show real user */ +- vsnprintf(buf, sizeof(buf), fmt, ap); +- audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, ++ /* FIXME: need to change this to show real user */ ++ vsnprintf(buf, sizeof(buf), fmt, ap); ++ audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, + NULL, getuid()); +- return; ++ return; ++ } + } + #endif /* HAVE_LIBAUDIT */ + +diff -urp dbus-1.2.16.orig/configure.in dbus-1.2.16/configure.in +--- dbus-1.2.16.orig/configure.in 2009-10-03 08:46:51.000000000 -0400 ++++ dbus-1.2.16/configure.in 2009-10-03 08:47:26.000000000 -0400 +@@ -844,7 +844,7 @@ else + AC_CHECK_LIB(audit, audit_log_user_avc_message, + have_libaudit=yes, have_libaudit=no) + if test x$have_libaudit = xyes ; then +- AC_CHECK_LIB(cap, cap_set_proc, ++ AC_CHECK_LIB(cap-ng, capng_clear, + have_libaudit=yes, have_libaudit=no) + fi + fi +@@ -853,7 +853,7 @@ AM_CONDITIONAL(HAVE_LIBAUDIT, test x$hav + + if test x$have_libaudit = xyes ; then + SELINUX_LIBS="$SELINUX_LIBS -laudit" +- LIBS="-lcap $LIBS" ++ LIBS="-lcap-ng $LIBS" + AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support]) + fi + +diff -urp dbus-1.2.16.orig/dbus/dbus-sysdeps-util-unix.c dbus-1.2.16/dbus/dbus-sysdeps-util-unix.c +--- dbus-1.2.16.orig/dbus/dbus-sysdeps-util-unix.c 2009-10-03 08:46:51.000000000 -0400 ++++ dbus-1.2.16/dbus/dbus-sysdeps-util-unix.c 2009-10-03 08:52:14.000000000 -0400 +@@ -46,8 +46,7 @@ + #include + #include + #ifdef HAVE_LIBAUDIT +-#include +-#include ++#include + #include + #endif /* HAVE_LIBAUDIT */ + +@@ -323,10 +322,6 @@ _dbus_change_to_daemon_user (const char + dbus_uid_t uid; + dbus_gid_t gid; + DBusString u; +-#ifdef HAVE_LIBAUDIT +- dbus_bool_t we_were_root; +- cap_t new_caps; +-#endif + + _dbus_string_init_const (&u, user); + +@@ -339,123 +334,49 @@ _dbus_change_to_daemon_user (const char + } + + #ifdef HAVE_LIBAUDIT +- we_were_root = _dbus_geteuid () == 0; +- new_caps = NULL; +- /* have a tmp set of caps that we use to transition to the usr/grp dbus should +- * run as ... doesn't really help. But keeps people happy. +- */ +- +- if (we_were_root) ++ /* If we were root */ ++ if (_dbus_geteuid () == 0) + { +- cap_value_t new_cap_list[] = { CAP_AUDIT_WRITE }; +- cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID, CAP_SETGID }; +- cap_t tmp_caps = cap_init(); +- +- if (!tmp_caps || !(new_caps = cap_init ())) +- { +- dbus_set_error (error, DBUS_ERROR_FAILED, +- "Failed to initialize drop of capabilities: %s\n", +- _dbus_strerror (errno)); +- +- if (tmp_caps) +- cap_free (tmp_caps); ++ int rc; + +- return FALSE; +- } +- +- /* assume these work... */ +- cap_set_flag (new_caps, CAP_PERMITTED, 1, new_cap_list, CAP_SET); +- cap_set_flag (new_caps, CAP_EFFECTIVE, 1, new_cap_list, CAP_SET); +- cap_set_flag (tmp_caps, CAP_PERMITTED, 3, tmp_cap_list, CAP_SET); +- cap_set_flag (tmp_caps, CAP_EFFECTIVE, 3, tmp_cap_list, CAP_SET); +- +- if (prctl (PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) ++ capng_clear(CAPNG_SELECT_BOTH); ++ capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, ++ CAP_AUDIT_WRITE); ++ rc = capng_change_id(uid, gid, 0); ++ if (rc) + { +- dbus_set_error (error, _dbus_error_from_errno (errno), +- "Failed to set keep-capabilities: %s\n", +- _dbus_strerror (errno)); +- cap_free (tmp_caps); +- goto fail; +- } +- +- if (cap_set_proc (tmp_caps) == -1) +- { +- dbus_set_error (error, DBUS_ERROR_FAILED, ++ switch (rc) { ++ default: ++ dbus_set_error (error, DBUS_ERROR_FAILED, + "Failed to drop capabilities: %s\n", + _dbus_strerror (errno)); +- cap_free (tmp_caps); +- goto fail; +- } +- cap_free (tmp_caps); +- } +-#endif /* HAVE_LIBAUDIT */ +- +- /* setgroups() only works if we are a privileged process, +- * so we don't return error on failure; the only possible +- * failure is that we don't have perms to do it. +- * +- * not sure this is right, maybe if setuid() +- * is going to work then setgroups() should also work. +- */ +- if (setgroups (0, NULL) < 0) +- _dbus_warn ("Failed to drop supplementary groups: %s\n", +- _dbus_strerror (errno)); +- +- /* Set GID first, or the setuid may remove our permission +- * to change the GID +- */ +- if (setgid (gid) < 0) +- { +- dbus_set_error (error, _dbus_error_from_errno (errno), ++ break; ++ case -4: ++ dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to set GID to %lu: %s", gid, + _dbus_strerror (errno)); +- goto fail; +- } +- +- if (setuid (uid) < 0) +- { +- dbus_set_error (error, _dbus_error_from_errno (errno), ++ break; ++ case -5: ++ _dbus_warn ("Failed to drop supplementary groups: %s\n", ++ _dbus_strerror (errno)); ++ break; ++ case -6: ++ dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to set UID to %lu: %s", uid, + _dbus_strerror (errno)); +- goto fail; +- } +- +-#ifdef HAVE_LIBAUDIT +- if (we_were_root) +- { +- if (cap_set_proc (new_caps)) +- { +- dbus_set_error (error, DBUS_ERROR_FAILED, +- "Failed to drop capabilities: %s\n", +- _dbus_strerror (errno)); +- goto fail; +- } +- cap_free (new_caps); +- +- /* should always work, if it did above */ +- if (prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0) == -1) +- { +- dbus_set_error (error, _dbus_error_from_errno (errno), ++ break; ++ case -7: ++ dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to unset keep-capabilities: %s\n", + _dbus_strerror (errno)); ++ break; ++ } + return FALSE; + } + } +-#endif ++#endif /* HAVE_LIBAUDIT */ + + return TRUE; +- +- fail: +-#ifdef HAVE_LIBAUDIT +- if (!we_were_root) +- { +- /* should always work, if it did above */ +- prctl (PR_SET_KEEPCAPS, 0, 0, 0, 0); +- cap_free (new_caps); +- } +-#endif +- +- return FALSE; + } + + void diff --git a/dbus-libcap.patch b/dbus-libcap.patch new file mode 100644 index 0000000..0ea9f41 --- /dev/null +++ b/dbus-libcap.patch @@ -0,0 +1,378 @@ + + + + Access Denied + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ You are not authorized to access bug #554785. + To see this bug, you must + first log + in to an account with the appropriate permissions. + +
+ + + + +

+ Please press Back and try again. +

+ + + +
+ + + + + + + \ No newline at end of file diff --git a/dbus.spec b/dbus.spec index e3a7de0..cdc88e6 100644 --- a/dbus.spec +++ b/dbus.spec @@ -4,26 +4,29 @@ %define libselinux_version 1.15.2 %define dbus_user_uid 81 +%define _default_patch_fuzz 999 Summary: D-BUS message bus Name: dbus Epoch: 1 Version: 1.2.16 -Release: 5%{?dist} +Release: 10%{?dist} URL: http://www.freedesktop.org/software/dbus/ Source0: http://dbus.freedesktop.org/releases/dbus/%{name}-%{version}.tar.gz Source1: doxygen_to_devhelp.xsl Source2: 00-start-message-bus.sh +Source3: diagram.png +Source4: diagram.svg License: GPLv2+ or AFL Group: System Environment/Libraries -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libtool BuildRequires: expat-devel >= %{expat_version} BuildRequires: libselinux-devel >= %{libselinux_version} BuildRequires: audit-libs-devel >= 0.9 BuildRequires: libX11-devel -BuildRequires: libcap-devel +BuildRequires: libcap-ng-devel BuildRequires: gettext BuildRequires: doxygen BuildRequires: xmlto @@ -41,6 +44,28 @@ Conflicts: cups < 1:1.1.20-4 Patch0: start-early.patch Patch1: dbus-1.0.1-generate-xml-docs.patch +# from upstream +Patch2: fix-timeout-accounting.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=518541 +Patch3: dbus-1.2.16-capability.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=545267 +# http://bugs.freedesktop.org/25642 +Patch4: fix-reload-leak.patch + +# http://bugs.freedesktop.org/25697 +Patch5: fix-daemon-activation.patch + +# http://bugs.freedesktop.org/24350 +Patch6: keep-pending-activations.patch + +# http://bugs.freedesktop.org/21597 +Patch7: fix-reload-race.patch + +# http://bugs.freedesktop.org/show_bug.cgi?id=26018 +Patch8: dbus-libcap.patch + %description D-BUS is a system for sending messages between applications. It is used both for the system-wide message bus service, and as a @@ -94,6 +119,13 @@ in this separate package so server systems need not install X. %patch0 -p1 -b .start-early %patch1 -p1 -b .generate-xml-docs +%patch2 -p1 -b .fix-timeout-accounting +%patch3 -p1 -b .capability +%patch4 -p1 -b .fix-reload-leak +%patch5 -p1 -b .fix-daemon-activation +%patch6 -p1 -b .keep-pending-activations +%patch7 -p1 -b .fix-reload-race +%patch8 -p1 -b .dbus-libcap autoreconf -f -i @@ -138,6 +170,10 @@ cp doc/dbus-faq.html %{buildroot}%{_datadir}/devhelp/books/dbus cp doc/dbus-tutorial.html %{buildroot}%{_datadir}/devhelp/books/dbus cp doc/api/html/* %{buildroot}%{_datadir}/devhelp/books/dbus/api +# missing diagrams +cp %{SOURCE3} %{buildroot}%{_datadir}/devhelp/books/dbus +cp %{SOURCE4} %{buildroot}%{_datadir}/devhelp/books/dbus + install -D -m755 %{SOURCE2} %{buildroot}%{_sysconfdir}/X11/xinit/xinitrc.d/00-start-message-bus.sh mkdir -p %{buildroot}%{_datadir}/dbus-1/interfaces @@ -226,6 +262,24 @@ fi %{_includedir}/* %changelog +* Tue Jan 12 2010 Matthias Clasen - 1:1.2.16-10 +- Don't link libdub against libcap-ng + +* Fri Dec 18 2009 Ray Strode - 1:1.2.16-9 +- Fix activation of daemons (#545267) +- Fix reload memleak (fdo #24697) +- Don't forget about pending activations on reload (fdo #24350) +- Fix reload race (fdo #21597) + +* Wed Oct 7 2009 Matthias Clasen - 1:1.2.16-8 +- Drop capabilities (#518541) + +* Wed Oct 7 2009 Matthias Clasen - 1:1.2.16-7 +- Add missing diagrams to the docs (#527650) + +* Thu Oct 1 2009 Matthias Clasen - 1:1.2.16-6 +- Fix timeout accounting + * Fri Aug 21 2009 Tomas Mraz - 1:1.2.16-5 - rebuilt with new audit diff --git a/fix-daemon-activation.patch b/fix-daemon-activation.patch new file mode 100644 index 0000000..6972ba7 --- /dev/null +++ b/fix-daemon-activation.patch @@ -0,0 +1,310 @@ +From 949a64b127a32a3e5a4ce4278773f18e290c44c2 Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Mon, 14 Dec 2009 23:12:24 +0000 +Subject: Ignore exit code zero from activated services + +A variety of system components have migrated from legacy init into DBus +service activation. Many of these system components "daemonize", which +involves forking. The DBus activation system treated an exit as an +activation failure, assuming that the child process which grabbed the +DBus name didn't run first. + +While we're in here, also differentiate in this code path between the +servicehelper (system) versus direct activation (session) paths. In +the session activation path our error message mentioned a helper +process which was confusing, since none was involved. + +Based on a patch and debugging research from Ray Strode +--- +diff --git a/bus/activation.c b/bus/activation.c +index 782ffed..00caac2 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -1212,8 +1212,8 @@ pending_activation_failed (BusPendingActivation *pending_activation, + * Depending on the exit code of the helper, set the error accordingly + */ + static void +-handle_activation_exit_error (int exit_code, +- DBusError *error) ++handle_servicehelper_exit_error (int exit_code, ++ DBusError *error) + { + switch (exit_code) + { +@@ -1268,13 +1268,24 @@ babysitter_watch_callback (DBusWatch *watch, + BusPendingActivation *pending_activation = data; + dbus_bool_t retval; + DBusBabysitter *babysitter; ++ dbus_bool_t uses_servicehelper; + + babysitter = pending_activation->babysitter; +- ++ + _dbus_babysitter_ref (babysitter); +- ++ + retval = dbus_watch_handle (watch, condition); + ++ /* There are two major cases here; are we the system bus or the session? Here this ++ * is distinguished by whether or not we use a setuid helper launcher. With the launch helper, ++ * some process exit codes are meaningful, processed by handle_servicehelper_exit_error. ++ * ++ * In both cases though, just ignore when a process exits with status 0; it's possible for ++ * a program to (misguidedly) "daemonize", and that appears to us as an exit. This closes a race ++ * condition between this code and the child process claiming the bus name. ++ */ ++ uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL; ++ + /* FIXME this is broken in the same way that + * connection watches used to be; there should be + * a separate callback for status change, instead +@@ -1284,43 +1295,59 @@ babysitter_watch_callback (DBusWatch *watch, + * Fixing this lets us move dbus_watch_handle + * calls into dbus-mainloop.c + */ +- + if (_dbus_babysitter_get_child_exited (babysitter)) + { + DBusError error; + DBusHashIter iter; +- ++ dbus_bool_t activation_failed; ++ int exit_code = 0; ++ + dbus_error_init (&error); ++ + _dbus_babysitter_set_child_exit_error (babysitter, &error); + +- /* refine the error code if we got an exit code */ +- if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)) +- { +- int exit_code = 0; +- if (_dbus_babysitter_get_child_exit_status (babysitter, &exit_code)) ++ /* Explicitly check for SPAWN_CHILD_EXITED to avoid overwriting an ++ * exec error */ ++ if (dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED) ++ && _dbus_babysitter_get_child_exit_status (babysitter, &exit_code)) ++ { ++ activation_failed = exit_code != 0; ++ ++ dbus_error_free(&error); ++ ++ if (activation_failed) + { +- dbus_error_free (&error); +- handle_activation_exit_error (exit_code, &error); ++ if (uses_servicehelper) ++ handle_servicehelper_exit_error (exit_code, &error); ++ else ++ _dbus_babysitter_set_child_exit_error (babysitter, &error); + } +- } +- +- /* Destroy all pending activations with the same exec */ +- _dbus_hash_iter_init (pending_activation->activation->pending_activations, +- &iter); +- while (_dbus_hash_iter_next (&iter)) ++ } ++ else + { +- BusPendingActivation *p = _dbus_hash_iter_get_value (&iter); +- +- if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0) +- pending_activation_failed (p, &error); ++ activation_failed = TRUE; + } +- +- /* Destroys the pending activation */ +- pending_activation_failed (pending_activation, &error); + +- dbus_error_free (&error); ++ if (activation_failed) ++ { ++ /* Destroy all pending activations with the same exec */ ++ _dbus_hash_iter_init (pending_activation->activation->pending_activations, ++ &iter); ++ while (_dbus_hash_iter_next (&iter)) ++ { ++ BusPendingActivation *p = _dbus_hash_iter_get_value (&iter); ++ ++ if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0) ++ pending_activation_failed (p, &error); ++ } ++ ++ /* Destroys the pending activation */ ++ pending_activation_failed (pending_activation, &error); ++ ++ dbus_error_free (&error); ++ } + } +- ++ + _dbus_babysitter_unref (babysitter); + + return retval; +diff --git a/configure.in b/configure.in +index 7ef6632..1f2c896 100644 +--- a/configure.in ++++ b/configure.in +@@ -1499,6 +1499,7 @@ test/data/valid-config-files-system/debug-allow-all-pass.conf + test/data/valid-config-files-system/debug-allow-all-fail.conf + test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service + test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service ++test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service + test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service + test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service + test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceFail.service +diff --git a/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in b/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in +new file mode 100644 +index 0000000..49fcac3 +--- a/dev/null ++++ b/test/data/valid-service-files/org.freedesktop.DBus.TestSuiteForkingEchoService.service.in +@@ -0,0 +1,3 @@ ++[D-BUS Service] ++Name=org.freedesktop.DBus.TestSuiteForkingEchoService ++Exec=@TEST_SERVICE_BINARY@ org.freedesktop.DBus.TestSuiteForkingEchoService fork +diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am +index 1c73b87..d8e72d1 100644 +--- a/test/name-test/Makefile.am ++++ b/test/name-test/Makefile.am +@@ -10,7 +10,7 @@ else + TESTS= + endif + +-EXTRA_DIST=run-test.sh run-test-systemserver.sh test-wait-for-echo.py ++EXTRA_DIST=run-test.sh run-test-systemserver.sh test-wait-for-echo.py test-activation-forking.py + + if DBUS_BUILD_TESTS + +diff --git a/test/name-test/run-test.sh b/test/name-test/run-test.sh +index fba4558..4eb2425 100755 +--- a/test/name-test/run-test.sh ++++ b/test/name-test/run-test.sh +@@ -50,3 +50,9 @@ ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name- + + echo "running test-shutdown" + ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-shutdown || die "test-shutdown failed" ++ ++echo "running test activation forking" ++if ! python $DBUS_TOP_SRCDIR/test/name-test/test-activation-forking.py; then ++ echo "Failed test-activation-forking" ++ exit 1 ++fi +diff --git a/test/name-test/test-activation-forking.py b/test/name-test/test-activation-forking.py +new file mode 100644 +index 0000000..0d82075 +--- a/dev/null ++++ b/test/name-test/test-activation-forking.py +@@ -0,0 +1,60 @@ ++#!/usr/bin/env python ++ ++import os,sys ++ ++try: ++ import gobject ++ import dbus ++ import dbus.mainloop.glib ++except: ++ print "Failed import, aborting test" ++ sys.exit(0) ++ ++dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) ++loop = gobject.MainLoop() ++ ++exitcode = 0 ++ ++bus = dbus.SessionBus() ++bus_iface = dbus.Interface(bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'), 'org.freedesktop.DBus') ++ ++o = bus.get_object('org.freedesktop.DBus.TestSuiteForkingEchoService', '/org/freedesktop/TestSuite') ++i = dbus.Interface(o, 'org.freedesktop.TestSuite') ++ ++# Start it up ++reply = i.Echo("hello world") ++print "TestSuiteForkingEchoService initial reply OK" ++ ++def ignore(*args, **kwargs): ++ pass ++ ++# Now monitor for exits, when that happens, start it up again. ++# The goal here is to try to hit any race conditions in activation. ++counter = 0 ++def on_forking_echo_owner_changed(name, old, new): ++ global counter ++ global o ++ global i ++ if counter > 10: ++ print "Activated 10 times OK, TestSuiteForkingEchoService pass" ++ loop.quit() ++ return ++ counter += 1 ++ if new == '': ++ o = bus.get_object('org.freedesktop.DBus.TestSuiteForkingEchoService', '/org/freedesktop/TestSuite') ++ i = dbus.Interface(o, 'org.freedesktop.TestSuite') ++ i.Echo("counter %r" % counter) ++ i.Exit(reply_handler=ignore, error_handler=ignore) ++ ++bus_iface.connect_to_signal('NameOwnerChanged', on_forking_echo_owner_changed, arg0='org.freedesktop.DBus.TestSuiteForkingEchoService') ++ ++i.Exit(reply_handler=ignore, error_handler=ignore) ++ ++def check_counter(): ++ if counter == 0: ++ print "Failed to get NameOwnerChanged for TestSuiteForkingEchoService" ++ sys.exit(1) ++gobject.timeout_add(15000, check_counter) ++ ++loop.run() ++sys.exit(0) +diff --git a/test/test-service.c b/test/test-service.c +index c9f5839..a57bf9c 100644 +--- a/test/test-service.c ++++ b/test/test-service.c +@@ -398,7 +398,33 @@ main (int argc, + DBusError error; + int result; + DBusConnection *connection; +- ++ const char *name; ++ dbus_bool_t do_fork; ++ ++ if (argc != 3) ++ { ++ name = "org.freedesktop.DBus.TestSuiteEchoService"; ++ do_fork = FALSE; ++ } ++ else ++ { ++ name = argv[1]; ++ do_fork = strcmp (argv[2], "fork") == 0; ++ } ++ ++ /* The bare minimum for simulating a program "daemonizing"; the intent ++ * is to test services which move from being legacy init scripts to ++ * activated services. ++ * https://bugzilla.redhat.com/show_bug.cgi?id=545267 ++ */ ++ if (do_fork) ++ { ++ pid_t pid = fork (); ++ if (pid != 0) ++ exit (0); ++ sleep (1); ++ } ++ + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_STARTER, &error); + if (connection == NULL) +@@ -433,8 +459,8 @@ main (int argc, + if (d != (void*) 0xdeadbeef) + die ("dbus_connection_get_object_path_data() doesn't seem to work right\n"); + } +- +- result = dbus_bus_request_name (connection, "org.freedesktop.DBus.TestSuiteEchoService", ++ ++ result = dbus_bus_request_name (connection, name, + 0, &error); + if (dbus_error_is_set (&error)) + { +-- +cgit v0.8.3-6-g21f6 diff --git a/fix-reload-leak.patch b/fix-reload-leak.patch new file mode 100644 index 0000000..776678e --- /dev/null +++ b/fix-reload-leak.patch @@ -0,0 +1,12 @@ +diff -up dbus-1.2.16/bus/bus.c.policy-leak dbus-1.2.16/bus/bus.c +--- dbus-1.2.16/bus/bus.c.policy-leak 2009-12-17 19:18:50.966795963 -0500 ++++ dbus-1.2.16/bus/bus.c 2009-12-17 19:17:36.023796405 -0500 +@@ -438,6 +438,8 @@ process_config_every_time (BusContext + /* get our limits and timeout lengths */ + bus_config_parser_get_limits (parser, &context->limits); + ++ if (context->policy) ++ bus_policy_unref (context->policy); + context->policy = bus_config_parser_steal_policy (parser); + _dbus_assert (context->policy != NULL); + diff --git a/fix-reload-race.patch b/fix-reload-race.patch new file mode 100644 index 0000000..2805479 --- /dev/null +++ b/fix-reload-race.patch @@ -0,0 +1,215 @@ +--- dbus-1.2.16/bus/dir-watch-inotify.c 2009-07-14 13:06:31.000000000 -0400 ++++ hacked/bus/dir-watch-inotify.c 2009-12-18 00:46:05.524818800 -0500 +@@ -34,6 +34,7 @@ + #include + + #include ++#include + #include + #include "dir-watch.h" + +@@ -43,6 +44,7 @@ + + /* use a static array to avoid handling OOM */ + static int wds[MAX_DIRS_TO_WATCH]; ++static char *dirs[MAX_DIRS_TO_WATCH]; + static int num_wds = 0; + static int inotify_fd = -1; + static DBusWatch *watch = NULL; +@@ -90,12 +92,10 @@ + return TRUE; + } + +-void +-bus_watch_directory (const char *dir, BusContext *context) ++static int ++_init_inotify (BusContext *context) + { +- int wd; +- +- _dbus_assert (dir != NULL); ++ int ret = 0; + + if (inotify_fd == -1) { + #ifdef HAVE_INOTIFY_INIT1 +@@ -112,22 +112,38 @@ + watch = _dbus_watch_new (inotify_fd, DBUS_WATCH_READABLE, TRUE, + _handle_inotify_watch, NULL, NULL); + +- if (watch == NULL) +- { +- _dbus_warn ("Unable to create inotify watch\n"); +- goto out; +- } +- +- if (!_dbus_loop_add_watch (loop, watch, _inotify_watch_callback, +- NULL, NULL)) +- { +- _dbus_warn ("Unable to add reload watch to main loop"); +- _dbus_watch_unref (watch); +- watch = NULL; +- goto out; +- } ++ if (watch == NULL) ++ { ++ _dbus_warn ("Unable to create inotify watch\n"); ++ goto out; ++ } ++ ++ if (!_dbus_loop_add_watch (loop, watch, _inotify_watch_callback, ++ NULL, NULL)) ++ { ++ _dbus_warn ("Unable to add reload watch to main loop"); ++ _dbus_watch_unref (watch); ++ watch = NULL; ++ goto out; ++ } + } + ++ ret = 1; ++ ++out: ++ return ret; ++} ++ ++void ++bus_watch_directory (const char *dir, BusContext *context) ++{ ++ int wd; ++ ++ _dbus_assert (dir != NULL); ++ ++ if (!_init_inotify (context)) ++ goto out; ++ + if (num_wds >= MAX_DIRS_TO_WATCH ) + { + _dbus_warn ("Cannot watch config directory '%s'. Already watching %d directories\n", dir, MAX_DIRS_TO_WATCH); +@@ -141,6 +157,7 @@ + goto out; + } + ++ dirs[num_wds] = strdup (dir); + wds[num_wds++] = wd; + _dbus_verbose ("Added watch on config directory '%s'\n", dir); + +@@ -148,7 +165,84 @@ + ; + } + +-void ++void ++bus_set_watched_dirs (BusContext *context, DBusList **directories) ++{ ++ static int new_wds[MAX_DIRS_TO_WATCH]; ++ static char *new_dirs[MAX_DIRS_TO_WATCH]; ++ DBusList *link; ++ int i, j, wd; ++ ++ if (!_init_inotify (context)) ++ goto out; ++ ++ for (i = 0; i < MAX_DIRS_TO_WATCH; i++) ++ { ++ new_wds[i] = -1; ++ new_dirs[i] = NULL; ++ } ++ ++ i = 0; ++ link = _dbus_list_get_first_link (directories); ++ while (link != NULL) ++ { ++ new_dirs[i++] = (char *)link->data; ++ link = _dbus_list_get_next_link (directories, link); ++ } ++ ++ for (i = 0; new_dirs[i]; i++) ++ { ++ for (j = 0; j < num_wds; j++) ++ { ++ if (dirs[j] && strcmp (new_dirs[i], dirs[j]) == 0) ++ { ++ new_wds[i] = wds[j]; ++ new_dirs[i] = dirs[j]; ++ wds[j] = -1; ++ dirs[j] = NULL; ++ break; ++ } ++ } ++ } ++ ++ for (j = 0; j < num_wds; j++) ++ { ++ if (wds[j] != -1) ++ { ++ inotify_rm_watch (inotify_fd, wds[j]); ++ dbus_free (dirs[j]); ++ wds[j] = -1; ++ dirs[j] = NULL; ++ } ++ } ++ ++ for (i = 0; new_dirs[i]; i++) ++ { ++ if (new_wds[i] == -1) ++ { ++ wd = inotify_add_watch (inotify_fd, new_dirs[i], IN_CLOSE_WRITE | IN_DELETE | IN_MOVED_TO | IN_MOVED_FROM); ++ if (wd < 0) ++ { ++ _dbus_warn ("Cannot setup inotify for '%s'; error '%s'\n", new_dirs[i], _dbus_strerror (errno)); ++ goto out; ++ } ++ new_wds[i] = wd; ++ new_dirs[i] = strdup (new_dirs[i]); ++ } ++ } ++ ++ num_wds = i; ++ ++ for (i = 0; i < MAX_DIRS_TO_WATCH; i++) ++ { ++ wds[i] = new_wds[i]; ++ dirs[i] = new_dirs[i]; ++ } ++ ++ out:; ++} ++ ++void + bus_drop_all_directory_watches (void) + { + int ret; +--- dbus-1.2.16/bus/dir-watch.h 2009-07-14 13:06:31.000000000 -0400 ++++ hacked/bus/dir-watch.h 2009-12-18 00:45:47.437818936 -0500 +@@ -32,4 +32,6 @@ + /* drop all the watches previously set up by bus_config_watch_directory (OS dependent, may be a NOP) */ + void bus_drop_all_directory_watches (void); + ++void bus_set_watched_dirs (BusContext *context, DBusList **dirs); ++ + #endif /* DIR_WATCH_H */ +--- dbus-1.2.16/bus/bus.c 2009-07-14 13:06:31.000000000 -0400 ++++ hacked/bus/bus.c 2009-12-18 00:51:30.348481884 -0500 +@@ -516,11 +516,6 @@ + + context->activation = new_activation; + +- /* Drop existing conf-dir watches (if applicable) */ +- +- if (is_reload) +- bus_drop_all_directory_watches (); +- + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + retval = TRUE; + +@@ -551,9 +546,7 @@ + _dbus_hash_table_unref (service_context_table); + + /* Watch all conf directories */ +- _dbus_list_foreach (bus_config_parser_get_conf_dirs (parser), +- (DBusForeachFunction) bus_watch_directory, +- context); ++ bus_set_watched_dirs (context, bus_config_parser_get_conf_dirs (parser)); + + return TRUE; + } diff --git a/fix-timeout-accounting.patch b/fix-timeout-accounting.patch new file mode 100644 index 0000000..7b48a26 --- /dev/null +++ b/fix-timeout-accounting.patch @@ -0,0 +1,59 @@ +Index: dbus-1.2.16/dbus/dbus-connection.c +=================================================================== +--- dbus-1.2.16.orig/dbus/dbus-connection.c 2009-10-01 14:10:21.000000000 +0100 ++++ dbus-1.2.16/dbus/dbus-connection.c 2009-10-01 14:13:16.000000000 +0100 +@@ -2386,7 +2386,7 @@ + */ + _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); + +- _dbus_memory_pause_based_on_timeout (timeout_milliseconds); ++ _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); + } + else + { +@@ -2394,7 +2394,7 @@ + _dbus_connection_do_iteration_unlocked (connection, + DBUS_ITERATION_DO_READING | + DBUS_ITERATION_BLOCK, +- timeout_milliseconds); ++ timeout_milliseconds - elapsed_milliseconds); + } + + goto recheck_status; +@@ -2403,9 +2403,7 @@ + _dbus_verbose ("dbus_connection_send_with_reply_and_block(): clock set backward\n"); + else if (elapsed_milliseconds < timeout_milliseconds) + { +- timeout_milliseconds -= elapsed_milliseconds; +- _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds); +- _dbus_assert (timeout_milliseconds >= 0); ++ _dbus_verbose ("dbus_connection_send_with_reply_and_block(): %d milliseconds remain\n", timeout_milliseconds - elapsed_milliseconds); + + if (status == DBUS_DISPATCH_NEED_MEMORY) + { +@@ -2415,7 +2413,7 @@ + */ + _dbus_verbose ("dbus_connection_send_with_reply_and_block() waiting for more memory\n"); + +- _dbus_memory_pause_based_on_timeout (timeout_milliseconds); ++ _dbus_memory_pause_based_on_timeout (timeout_milliseconds - elapsed_milliseconds); + } + else + { +@@ -2423,14 +2421,14 @@ + _dbus_connection_do_iteration_unlocked (connection, + DBUS_ITERATION_DO_READING | + DBUS_ITERATION_BLOCK, +- timeout_milliseconds); ++ timeout_milliseconds - elapsed_milliseconds); + } + + goto recheck_status; + } + + _dbus_verbose ("dbus_connection_send_with_reply_and_block(): Waited %ld milliseconds and got no reply\n", +- (tv_sec - start_tv_sec) * 1000 + (tv_usec - start_tv_usec) / 1000); ++ elapsed_milliseconds); + + _dbus_assert (!_dbus_pending_call_get_completed_unlocked (pending)); + diff --git a/keep-pending-activations.patch b/keep-pending-activations.patch new file mode 100644 index 0000000..40a6903 --- /dev/null +++ b/keep-pending-activations.patch @@ -0,0 +1,147 @@ +diff -u -r dbus-1.2.16/bus/activation.c hacked/bus/activation.c +--- dbus-1.2.16/bus/activation.c 2009-07-14 13:06:31.000000000 -0400 ++++ hacked/bus/activation.c 2009-12-17 21:36:56.447546354 -0500 +@@ -736,6 +736,101 @@ + } + + BusActivation* ++bus_activation_reload (BusActivation *activation, ++ const DBusString *address, ++ DBusList **directories, ++ DBusError *error) ++{ ++ DBusList *link; ++ char *dir; ++ ++ dbus_free (activation->server_address); ++ if (!_dbus_string_copy_data (address, &activation->server_address)) ++ { ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ _dbus_hash_table_unref (activation->entries); ++ activation->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, ++ (DBusFreeFunction)bus_activation_entry_unref); ++ if (activation->entries == NULL) ++ { ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ _dbus_hash_table_unref (activation->directories); ++ activation->directories = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, ++ (DBusFreeFunction)bus_service_directory_unref); ++ ++ if (activation->directories == NULL) ++ { ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ link = _dbus_list_get_first_link (directories); ++ while (link != NULL) ++ { ++ BusServiceDirectory *s_dir; ++ ++ dir = _dbus_strdup ((const char *) link->data); ++ if (!dir) ++ { ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ s_dir = dbus_new0 (BusServiceDirectory, 1); ++ if (!s_dir) ++ { ++ dbus_free (dir); ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ s_dir->refcount = 1; ++ s_dir->dir_c = dir; ++ ++ s_dir->entries = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, ++ (DBusFreeFunction)bus_activation_entry_unref); ++ ++ if (!s_dir->entries) ++ { ++ bus_service_directory_unref (s_dir); ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ if (!_dbus_hash_table_insert_string (activation->directories, s_dir->dir_c, s_dir)) ++ { ++ bus_service_directory_unref (s_dir); ++ BUS_SET_OOM (error); ++ goto failed; ++ } ++ ++ /* only fail on OOM, it is ok if we can't read the directory */ ++ if (!update_directory (activation, s_dir, error)) ++ { ++ if (dbus_error_has_name (error, DBUS_ERROR_NO_MEMORY)) ++ goto failed; ++ else ++ dbus_error_free (error); ++ } ++ ++ link = _dbus_list_get_next_link (directories, link); ++ } ++ ++ return activation; ++ ++ failed: ++ if (activation) ++ bus_activation_unref (activation); ++ return NULL; ++} ++ ++BusActivation* + bus_activation_new (BusContext *context, + const DBusString *address, + DBusList **directories, +diff -u -r dbus-1.2.16/bus/activation.h hacked/bus/activation.h +--- dbus-1.2.16/bus/activation.h 2009-07-14 13:06:31.000000000 -0400 ++++ hacked/bus/activation.h 2009-12-17 20:02:53.347545761 -0500 +@@ -32,6 +32,10 @@ + const DBusString *address, + DBusList **directories, + DBusError *error); ++BusActivation* bus_activation_reload (BusActivation *activation, ++ const DBusString *address, ++ DBusList **directories, ++ DBusError *error); + BusActivation* bus_activation_ref (BusActivation *activation); + void bus_activation_unref (BusActivation *activation); + +diff -u -r dbus-1.2.16/bus/bus.c hacked/bus/bus.c +--- dbus-1.2.16/bus/bus.c 2009-07-14 13:06:31.000000000 -0400 ++++ hacked/bus/bus.c 2009-12-17 20:04:08.006546566 -0500 +@@ -503,19 +503,17 @@ + } + + /* Create activation subsystem */ +- new_activation = bus_activation_new (context, &full_address, +- dirs, error); +- if (new_activation == NULL) ++ if (context->activation) ++ bus_activation_reload (context->activation, &full_address, dirs, error); ++ else ++ context->activation = bus_activation_new (context, &full_address, dirs, error); ++ ++ if (context->activation == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + goto failed; + } + +- if (is_reload) +- bus_activation_unref (context->activation); +- +- context->activation = new_activation; +- + /* Drop existing conf-dir watches (if applicable) */ +