file://dbus-user.socket \
"
+#SRC_URI += " file://0001-Set-correct-address-when-using-address-systemd.patch "
+
+SRC_URI += " file://0002-Add-_DBUS_GNUC_WARN_UNUSED_RESULT-similar-to-GLib-s.patch \
+ file://0003-DBusAtomic-on-Unix-use-pthreads-mutexes-for-fallback.patch \
+ file://0004-dbus_threads_init-call-_dbus_threads_init_platform_s.patch \
+ file://0005-dbus_threads_init_default-dbus_threads_init-be-safe-.patch \
+ file://0006-Remove-unused-global-mutexes-for-win_fds-sid_atom_ca.patch \
+ file://0007-Turn-a-runtime-assertion-into-a-compile-time-asserti.patch \
+ file://0008-Replace-individual-global-lock-variables-with-an-arr.patch \
+ file://0009-Make-taking-a-global-lock-automatically-initialize-l.patch \
+ file://0010-Always-initialize-threading-before-allocating-a-dyna.patch \
+ file://0011-Add-a-statically-initialized-implementation-of-_dbus.patch \
+ file://0012-Enable-checking-of-smack-context-from-DBus-interface.patch \
+ file://0013-Enforce-smack-policy-from-conf-file.patch \
+ "
+
do_install_append() {
mkdir -p ${D}${systemd_unitdir}/user
install -m 0644 ${WORKDIR}/dbus-user.service ${D}${systemd_unitdir}/user/dbus.service
--- /dev/null
+From: Simon Peeters <peeters.simon@gmail.com>
+Date: Sun, 7 Oct 2012 16:59:30 +0200
+Subject: Set correct address when using --address=systemd:
+
+When dbus gets launched through systemd, we need to create an address
+string based on the sockets passed.
+
+The _dbus_append_addres_from_socket() function is responsible for
+extracting the address information from the file-descriptor and
+formatting it in a dbus friendly way.
+
+This fixes bus activation when running dbus under a systemd session.
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=50962
+Signed-off-by: Simon Peeters <peeters.simon@gmail.com>
+Applied-upstream: 1.7.0, commit:d728fdc655f17031da3bb129ab2fd17dadf0fe3a
+---
+ dbus/dbus-server-unix.c | 38 ++++++++++++++++++---------
+ dbus/dbus-sysdeps-unix.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
+ dbus/dbus-sysdeps-unix.h | 4 +++
+ 3 files changed, 97 insertions(+), 13 deletions(-)
+
+diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c
+index 130f66e..d995240 100644
+--- a/dbus/dbus-server-unix.c
++++ b/dbus/dbus-server-unix.c
+@@ -149,7 +149,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
+ }
+ else if (strcmp (method, "systemd") == 0)
+ {
+- int n, *fds;
++ int i, n, *fds;
+ DBusString address;
+
+ n = _dbus_listen_systemd_sockets (&fds, error);
+@@ -159,27 +159,39 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
+ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+ }
+
+- _dbus_string_init_const (&address, "systemd:");
++ if (!_dbus_string_init (&address))
++ goto systemd_oom;
+
+- *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
+- if (*server_p == NULL)
++ for (i = 0; i < n; i++)
+ {
+- int i;
+-
+- for (i = 0; i < n; i++)
++ if (i > 0)
+ {
+- _dbus_close_socket (fds[i], NULL);
++ if (!_dbus_string_append (&address, ";"))
++ goto systemd_oom;
+ }
+- dbus_free (fds);
+-
+- dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+- return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
++ if (!_dbus_append_address_from_socket (fds[i], &address, error))
++ goto systemd_err;
+ }
+
++ *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
++ if (*server_p == NULL)
++ goto systemd_oom;
++
+ dbus_free (fds);
+
+ return DBUS_SERVER_LISTEN_OK;
+- }
++ systemd_oom:
++ _DBUS_SET_OOM (error);
++ systemd_err:
++ for (i = 0; i < n; i++)
++ {
++ _dbus_close_socket (fds[i], NULL);
++ }
++ dbus_free (fds);
++ _dbus_string_free (&address);
++
++ return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
++ }
+ #ifdef DBUS_ENABLE_LAUNCHD
+ else if (strcmp (method, "launchd") == 0)
+ {
+diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
+index e31c735..7c9fb09 100644
+--- a/dbus/dbus-sysdeps-unix.c
++++ b/dbus/dbus-sysdeps-unix.c
+@@ -55,6 +55,7 @@
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <grp.h>
++#include <arpa/inet.h>
+
+ #ifdef HAVE_ERRNO_H
+ #include <errno.h>
+@@ -4173,4 +4174,71 @@ _dbus_check_setuid (void)
+ #endif
+ }
+
++/**
++ * Read the address from the socket and append it to the string
++ *
++ * @param fd the socket
++ * @param address
++ * @param error return location for error code
++ */
++dbus_bool_t
++_dbus_append_address_from_socket (int fd,
++ DBusString *address,
++ DBusError *error)
++{
++ union {
++ struct sockaddr sa;
++ struct sockaddr_storage storage;
++ struct sockaddr_un un;
++ struct sockaddr_in ipv4;
++ struct sockaddr_in6 ipv6;
++ } socket;
++ char hostip[INET6_ADDRSTRLEN];
++ int size = sizeof (socket);
++
++ if (getsockname (fd, &socket.sa, &size))
++ goto err;
++
++ switch (socket.sa.sa_family)
++ {
++ case AF_UNIX:
++ if (socket.un.sun_path[0]=='\0')
++ {
++ if (_dbus_string_append_printf (address, "unix:abstract=%s", &(socket.un.sun_path[1])))
++ return TRUE;
++ }
++ else
++ {
++ if (_dbus_string_append_printf (address, "unix:path=%s", socket.un.sun_path))
++ return TRUE;
++ }
++ break;
++ case AF_INET:
++ if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
++ if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
++ hostip, ntohs (socket.ipv4.sin_port)))
++ return TRUE;
++ break;
++#ifdef AF_INET6
++ case AF_INET6:
++ if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
++ if (_dbus_string_append_printf (address, "tcp:family=ipv6,host=%s,port=%u",
++ hostip, ntohs (socket.ipv6.sin6_port)))
++ return TRUE;
++ break;
++#endif
++ default:
++ dbus_set_error (error,
++ _dbus_error_from_errno (EINVAL),
++ "Failed to read address from socket: Unknown socket type.");
++ return FALSE;
++ }
++ err:
++ dbus_set_error (error,
++ _dbus_error_from_errno (errno),
++ "Failed to open socket: %s",
++ _dbus_strerror (errno));
++ return FALSE;
++}
++
+ /* tests in dbus-sysdeps-util.c */
+diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
+index 9b70896..a265b33 100644
+--- a/dbus/dbus-sysdeps-unix.h
++++ b/dbus/dbus-sysdeps-unix.h
+@@ -138,6 +138,10 @@ dbus_bool_t _dbus_parse_uid (const DBusString *uid_str,
+
+ void _dbus_close_all (void);
+
++dbus_bool_t _dbus_append_address_from_socket (int fd,
++ DBusString *address,
++ DBusError *error);
++
+ /** @} */
+
+ DBUS_END_DECLS
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Mon, 15 Apr 2013 20:40:21 +0100
+Subject: Add _DBUS_GNUC_WARN_UNUSED_RESULT, similar to GLib's
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Applied-upstream: 1.7.4, commit:7ac9b68220a2f48bc2942aaa909d6ba1f4605f73
+Bug-Tizen: TZPC-1971
+Change-Id: I9944ae3a1e9901728bbc3bedbcc6474022db586f
+---
+ dbus/dbus-macros.h | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/dbus/dbus-macros.h b/dbus/dbus-macros.h
+index dcd3eeb..cae4100 100644
+--- a/dbus/dbus-macros.h
++++ b/dbus/dbus-macros.h
+@@ -88,13 +88,21 @@
+ #define DBUS_ALLOC_SIZE2(x,y)
+ #endif
+
++#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
++#define _DBUS_GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
++#else
++#define _DBUS_GNUC_WARN_UNUSED_RESULT
++#endif
++
+ /** @def _DBUS_GNUC_PRINTF
+ * used to tell gcc about printf format strings
+ */
+ /** @def _DBUS_GNUC_NORETURN
+ * used to tell gcc about functions that never return, such as _dbus_abort()
+ */
+-
++/** @def _DBUS_GNUC_WARN_UNUSED_RESULT
++ * used to tell gcc about functions whose result must be used
++ */
+
+ /* Normally docs are in .c files, but there isn't a .c file for this. */
+ /**
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Mon, 15 Apr 2013 13:51:19 +0100
+Subject: DBusAtomic: on Unix, use pthreads mutexes for fallback
+
+On pthreads platforms, POSIX guarantees that we can "allocate" mutexes
+as library-global variables, without involving malloc. This means we
+don't need to error-check their allocation - if the dynamic linker
+succeeds, then we have enough memory for all our globals - which is an
+important step towards being thread-safe by default. In particular,
+making atomic operations never rely on DBusMutex means that we are free
+to implement parts of DBusMutex in terms of DBusAtomic, if it would help.
+
+We do not currently support any non-Windows platform that does not have
+pthreads. This is unlikely to change.
+
+On Windows, we already used real atomic operations; we can just
+delete the unused global variable.
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Applied-upstream: 1.7.4, commit:c36f21a2e91730e9ae52e8945305aa3072f0e508
+Bug-Tizen: TZPC-1971
+Change-Id: I91d99a86f25d49d63d79eebfe85767bb8cc66170
+---
+ dbus/dbus-internals.h | 5 -----
+ dbus/dbus-sysdeps-unix.c | 27 ++++++++++++++++++++-------
+ dbus/dbus-sysdeps-win.c | 2 --
+ dbus/dbus-threads.c | 3 ---
+ 4 files changed, 20 insertions(+), 17 deletions(-)
+
+diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
+index 8036a2b..eaf9603 100644
+--- a/dbus/dbus-internals.h
++++ b/dbus/dbus-internals.h
+@@ -327,12 +327,7 @@ _DBUS_DECLARE_GLOBAL_LOCK (win_fds);
+ _DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
+ _DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+
+-#if !DBUS_USE_SYNC
+-_DBUS_DECLARE_GLOBAL_LOCK (atomic);
+-#define _DBUS_N_GLOBAL_LOCKS (15)
+-#else
+ #define _DBUS_N_GLOBAL_LOCKS (14)
+-#endif
+
+ dbus_bool_t _dbus_threads_init_debug (void);
+
+diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
+index 7c9fb09..a67f5d3 100644
+--- a/dbus/dbus-sysdeps-unix.c
++++ b/dbus/dbus-sysdeps-unix.c
+@@ -82,6 +82,10 @@
+
+ #include "sd-daemon.h"
+
++#if !DBUS_USE_SYNC
++#include <pthread.h>
++#endif
++
+ #ifndef O_BINARY
+ #define O_BINARY 0
+ #endif
+@@ -2428,7 +2432,12 @@ _dbus_parse_uid (const DBusString *uid_str,
+ }
+
+ #if !DBUS_USE_SYNC
+-_DBUS_DEFINE_GLOBAL_LOCK (atomic);
++/* To be thread-safe by default on platforms that don't necessarily have
++ * atomic operations (notably Debian armel, which is armv4t), we must
++ * use a mutex that can be initialized statically, like this.
++ * GLib >= 2.32 uses a similar system.
++ */
++static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
+ #endif
+
+ /**
+@@ -2444,10 +2453,12 @@ _dbus_atomic_inc (DBusAtomic *atomic)
+ return __sync_add_and_fetch(&atomic->value, 1)-1;
+ #else
+ dbus_int32_t res;
+- _DBUS_LOCK (atomic);
++
++ pthread_mutex_lock (&atomic_mutex);
+ res = atomic->value;
+ atomic->value += 1;
+- _DBUS_UNLOCK (atomic);
++ pthread_mutex_unlock (&atomic_mutex);
++
+ return res;
+ #endif
+ }
+@@ -2466,10 +2477,11 @@ _dbus_atomic_dec (DBusAtomic *atomic)
+ #else
+ dbus_int32_t res;
+
+- _DBUS_LOCK (atomic);
++ pthread_mutex_lock (&atomic_mutex);
+ res = atomic->value;
+ atomic->value -= 1;
+- _DBUS_UNLOCK (atomic);
++ pthread_mutex_unlock (&atomic_mutex);
++
+ return res;
+ #endif
+ }
+@@ -2490,9 +2502,10 @@ _dbus_atomic_get (DBusAtomic *atomic)
+ #else
+ dbus_int32_t res;
+
+- _DBUS_LOCK (atomic);
++ pthread_mutex_lock (&atomic_mutex);
+ res = atomic->value;
+- _DBUS_UNLOCK (atomic);
++ pthread_mutex_unlock (&atomic_mutex);
++
+ return res;
+ #endif
+ }
+diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
+index c42316f..a17b210 100644
+--- a/dbus/dbus-sysdeps-win.c
++++ b/dbus/dbus-sysdeps-win.c
+@@ -3084,8 +3084,6 @@ _dbus_get_standard_system_servicedirs (DBusList **dirs)
+ return TRUE;
+ }
+
+-_DBUS_DEFINE_GLOBAL_LOCK (atomic);
+-
+ /**
+ * Atomically increments an integer
+ *
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index bb1169d..b464629 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -496,9 +496,6 @@ init_locks (void)
+ LOCK_ADDR (pending_call_slots),
+ LOCK_ADDR (server_slots),
+ LOCK_ADDR (message_slots),
+-#if !DBUS_USE_SYNC
+- LOCK_ADDR (atomic),
+-#endif
+ LOCK_ADDR (bus),
+ LOCK_ADDR (bus_datas),
+ LOCK_ADDR (shutdown_funcs),
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Mon, 15 Apr 2013 13:54:39 +0100
+Subject: dbus_threads_init: call _dbus_threads_init_platform_specific()
+
+This reverses the relationship between these two functions.
+Previously, dbus_threads_init() wouldn't allocate dbus_cond_event_tls
+on Windows, call check_monotonic_clock on Unix, or call
+_dbus_check_setuid on Unix.
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Applied-upstream: 1.7.4, commit:eabf6c42a1b779f57f2c08d35772035788657579
+Bug-Tizen: TZPC-1971
+Change-Id: Ice70cf1f3e2202b72016daf619c89206b96aac47
+---
+ dbus/dbus-sysdeps-pthread.c | 3 ++-
+ dbus/dbus-sysdeps-thread-win.c | 2 +-
+ dbus/dbus-threads.c | 7 ++++---
+ 3 files changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c
+index c60457b..36a1e4b 100644
+--- a/dbus/dbus-sysdeps-pthread.c
++++ b/dbus/dbus-sysdeps-pthread.c
+@@ -281,5 +281,6 @@ _dbus_threads_init_platform_specific (void)
+ */
+ check_monotonic_clock ();
+ (void) _dbus_check_setuid ();
+- return dbus_threads_init (NULL);
++
++ return TRUE;
+ }
+diff --git a/dbus/dbus-sysdeps-thread-win.c b/dbus/dbus-sysdeps-thread-win.c
+index e30e7b8..4c4442a 100644
+--- a/dbus/dbus-sysdeps-thread-win.c
++++ b/dbus/dbus-sysdeps-thread-win.c
+@@ -269,6 +269,6 @@ _dbus_threads_init_platform_specific (void)
+ return FALSE;
+ }
+
+- return dbus_threads_init (NULL);
++ return TRUE;
+ }
+
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index b464629..e7f2eb7 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -584,7 +584,8 @@ dbus_threads_init (const DBusThreadFunctions *functions)
+ if (thread_init_generation == _dbus_current_generation)
+ return TRUE;
+
+- if (!init_locks ())
++ if (!_dbus_threads_init_platform_specific() ||
++ !init_locks ())
+ return FALSE;
+
+ thread_init_generation = _dbus_current_generation;
+@@ -613,7 +614,7 @@ dbus_threads_init (const DBusThreadFunctions *functions)
+ dbus_bool_t
+ dbus_threads_init_default (void)
+ {
+- return _dbus_threads_init_platform_specific ();
++ return dbus_threads_init (NULL);
+ }
+
+
+@@ -624,7 +625,7 @@ dbus_threads_init_default (void)
+ dbus_bool_t
+ _dbus_threads_init_debug (void)
+ {
+- return _dbus_threads_init_platform_specific();
++ return dbus_threads_init (NULL);
+ }
+
+ #endif /* DBUS_BUILD_TESTS */
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 12:07:23 +0100
+Subject: dbus_threads_init_default,
+ dbus_threads_init: be safe to call at any time
+
+On Unix, we use a pthreads mutex, which can be allocated and
+initialized in global memory.
+
+On Windows, we use a CRITICAL_SECTION, together with a call to
+InitializeCriticalSection() from the constructor of a global static
+C++ object (thanks to Ralf Habacker for suggesting this approach).
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Applied-upstream: 1.7.4, commit:17a23d08b51cf21a2110047649a86445e99e2b3f
+Bug-Tizen: TZPC-1971
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Change-Id: Id6aa81b7d553965c4c6f511e2410673c2f222a66
+---
+ cmake/dbus/CMakeLists.txt | 1 +
+ dbus/Makefile.am | 1 +
+ dbus/dbus-init-win.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++
+ dbus/dbus-memory.c | 7 ++++++
+ dbus/dbus-sysdeps-pthread.c | 14 ++++++++++++
+ dbus/dbus-sysdeps-thread-win.c | 28 +++++++++++++++++++++++
+ dbus/dbus-sysdeps-win.h | 3 +++
+ dbus/dbus-sysdeps.h | 12 ++++++++++
+ dbus/dbus-threads.c | 28 +++++++++++++++++------
+ 9 files changed, 139 insertions(+), 7 deletions(-)
+ create mode 100644 dbus/dbus-init-win.cpp
+
+diff --git a/cmake/dbus/CMakeLists.txt b/cmake/dbus/CMakeLists.txt
+index d09e63d..9fcbb80 100644
+--- a/cmake/dbus/CMakeLists.txt
++++ b/cmake/dbus/CMakeLists.txt
+@@ -186,6 +186,7 @@ set (DBUS_UTIL_HEADERS
+ if (WIN32)
+ set (DBUS_SHARED_SOURCES ${DBUS_SHARED_SOURCES}
+ ${DBUS_DIR}/dbus-file-win.c
++ ${DBUS_DIR}/dbus-init-win.cpp
+ ${DBUS_DIR}/dbus-sysdeps-win.c
+ ${DBUS_DIR}/dbus-pipe-win.c
+ ${DBUS_DIR}/dbus-sysdeps-thread-win.c
+diff --git a/dbus/Makefile.am b/dbus/Makefile.am
+index bb5ccca..0e54c9f 100644
+--- a/dbus/Makefile.am
++++ b/dbus/Makefile.am
+@@ -68,6 +68,7 @@ endif
+ DBUS_SHARED_arch_sources = \
+ $(wince_source) \
+ dbus-file-win.c \
++ dbus-init-win.cpp \
+ dbus-pipe-win.c \
+ dbus-sockets-win.h \
+ dbus-sysdeps-win.c \
+diff --git a/dbus/dbus-init-win.cpp b/dbus/dbus-init-win.cpp
+new file mode 100644
+index 0000000..687f248
+--- /dev/null
++++ b/dbus/dbus-init-win.cpp
+@@ -0,0 +1,52 @@
++/*
++ * dbus-init-win.cpp - once-per-process initialization
++ *
++ * Copyright © 2013 Intel Corporation
++ *
++ * Licensed under the Academic Free License version 2.1
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#include <config.h>
++
++extern "C"
++{
++#include "dbus-sysdeps-win.h"
++}
++
++class DBusInternalInit
++ {
++ public:
++ DBusInternalInit ()
++ {
++ _dbus_threads_windows_init_global ();
++ }
++
++ void must_not_be_omitted ()
++ {
++ }
++ };
++
++static DBusInternalInit init;
++
++extern "C" void
++_dbus_threads_windows_ensure_ctor_linked ()
++{
++ /* Do nothing significant, just ensure that the global initializer gets
++ * linked in. */
++ init.must_not_be_omitted ();
++}
+diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
+index a033b54..317e37e 100644
+--- a/dbus/dbus-memory.c
++++ b/dbus/dbus-memory.c
+@@ -26,6 +26,7 @@
+ #include "dbus-internals.h"
+ #include "dbus-sysdeps.h"
+ #include "dbus-list.h"
++#include "dbus-threads.h"
+ #include <stdlib.h>
+
+ /**
+@@ -890,7 +891,13 @@ dbus_shutdown (void)
+ dbus_free (c);
+ }
+
++ /* We wrap this in the thread-initialization lock because
++ * dbus_threads_init() uses the current generation to tell whether
++ * we're initialized, so we need to make sure that un-initializing
++ * propagates into all threads. */
++ _dbus_threads_lock_platform_specific ();
+ _dbus_current_generation += 1;
++ _dbus_threads_unlock_platform_specific ();
+ }
+
+ /** @} */ /** End of public API docs block */
+diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c
+index 36a1e4b..1b5d0ba 100644
+--- a/dbus/dbus-sysdeps-pthread.c
++++ b/dbus/dbus-sysdeps-pthread.c
+@@ -284,3 +284,17 @@ _dbus_threads_init_platform_specific (void)
+
+ return TRUE;
+ }
++
++static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
++
++void
++_dbus_threads_lock_platform_specific (void)
++{
++ pthread_mutex_lock (&init_mutex);
++}
++
++void
++_dbus_threads_unlock_platform_specific (void)
++{
++ pthread_mutex_unlock (&init_mutex);
++}
+diff --git a/dbus/dbus-sysdeps-thread-win.c b/dbus/dbus-sysdeps-thread-win.c
+index 4c4442a..0887a54 100644
+--- a/dbus/dbus-sysdeps-thread-win.c
++++ b/dbus/dbus-sysdeps-thread-win.c
+@@ -30,6 +30,21 @@
+
+ #include <windows.h>
+
++static dbus_bool_t global_init_done = FALSE;
++static CRITICAL_SECTION init_lock;
++
++/* Called from C++ code in dbus-init-win.cpp. */
++void
++_dbus_threads_windows_init_global (void)
++{
++ /* this ensures that the object that acts as our global constructor
++ * actually gets linked in when we're linked statically */
++ _dbus_threads_windows_ensure_ctor_linked ();
++
++ InitializeCriticalSection (&init_lock);
++ global_init_done = TRUE;
++}
++
+ struct DBusCondVar {
+ DBusList *list; /**< list thread-local-stored events waiting on the cond variable */
+ CRITICAL_SECTION lock; /**< lock protecting the list */
+@@ -272,3 +287,16 @@ _dbus_threads_init_platform_specific (void)
+ return TRUE;
+ }
+
++void
++_dbus_threads_lock_platform_specific (void)
++{
++ _dbus_assert (global_init_done);
++ EnterCriticalSection (&init_lock);
++}
++
++void
++_dbus_threads_unlock_platform_specific (void)
++{
++ _dbus_assert (global_init_done);
++ LeaveCriticalSection (&init_lock);
++}
+diff --git a/dbus/dbus-sysdeps-win.h b/dbus/dbus-sysdeps-win.h
+index 74624b7..5e7f1e4 100644
+--- a/dbus/dbus-sysdeps-win.h
++++ b/dbus/dbus-sysdeps-win.h
+@@ -85,6 +85,9 @@ dbus_bool_t _dbus_get_config_file_name(DBusString *config_file,
+
+ dbus_bool_t _dbus_get_install_root(char *prefix, int len);
+
++void _dbus_threads_windows_init_global (void);
++void _dbus_threads_windows_ensure_ctor_linked (void);
++
+ #endif
+
+ /** @} end of sysdeps-win.h */
+diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
+index eee9160..c48d50f 100644
+--- a/dbus/dbus-sysdeps.h
++++ b/dbus/dbus-sysdeps.h
+@@ -507,6 +507,18 @@ dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id,
+ */
+ dbus_bool_t _dbus_threads_init_platform_specific (void);
+
++/**
++ * Lock a static mutex used to protect _dbus_threads_init_platform_specific().
++ *
++ * On Windows, this is currently unimplemented and does nothing.
++ */
++void _dbus_threads_lock_platform_specific (void);
++
++/**
++ * Undo _dbus_threads_lock_platform_specific().
++ */
++void _dbus_threads_unlock_platform_specific (void);
++
+ dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs,
+ const char *suffix,
+ DBusList **dir_list);
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index e7f2eb7..9a505de 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -581,15 +581,24 @@ init_locks (void)
+ dbus_bool_t
+ dbus_threads_init (const DBusThreadFunctions *functions)
+ {
++ _dbus_threads_lock_platform_specific ();
++
+ if (thread_init_generation == _dbus_current_generation)
+- return TRUE;
++ {
++ _dbus_threads_unlock_platform_specific ();
++ return TRUE;
++ }
+
+ if (!_dbus_threads_init_platform_specific() ||
+ !init_locks ())
+- return FALSE;
++ {
++ _dbus_threads_unlock_platform_specific ();
++ return FALSE;
++ }
+
+ thread_init_generation = _dbus_current_generation;
+-
++
++ _dbus_threads_unlock_platform_specific ();
+ return TRUE;
+ }
+
+@@ -600,11 +609,16 @@ dbus_threads_init (const DBusThreadFunctions *functions)
+ /**
+ * Initializes threads. If this function is not called, the D-Bus
+ * library will not lock any data structures. If it is called, D-Bus
+- * will do locking, at some cost in efficiency. Note that this
+- * function must be called BEFORE the second thread is started.
++ * will do locking, at some cost in efficiency.
++ *
++ * Since D-Bus 1.7 it is safe to call this function from any thread,
++ * any number of times (but it must be called before any other
++ * libdbus API is used).
+ *
+- * It's safe to call dbus_threads_init_default() as many times as you
+- * want, but only the first time will have an effect.
++ * In D-Bus 1.6 or older, this function must be called in the main thread
++ * before any other thread starts. As a result, it is not sufficient to
++ * call this function in a library or plugin, unless the library or plugin
++ * imposes a similar requirement on its callers.
+ *
+ * dbus_shutdown() reverses the effects of this function when it
+ * resets all global state in libdbus.
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 12:14:02 +0100
+Subject: Remove unused global mutexes for win_fds, sid_atom_cache
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Applied-upstream: 1.7.4, commit:d35f64339e401a7a47c1b088ef26e3dcb202cb9d
+Bug-Tizen: TZPC-1971
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Change-Id: I9619eaf477eaf1763133772b95e3845dd7c2b62e
+---
+ dbus/dbus-internals.h | 10 ++++------
+ dbus/dbus-sysdeps.c | 2 --
+ dbus/dbus-threads.c | 2 --
+ 3 files changed, 4 insertions(+), 10 deletions(-)
+
+diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
+index eaf9603..336d22e 100644
+--- a/dbus/dbus-internals.h
++++ b/dbus/dbus-internals.h
+@@ -309,25 +309,23 @@ extern int _dbus_current_generation;
+ #define _DBUS_LOCK(name) _dbus_rmutex_lock (_dbus_lock_##name)
+ #define _DBUS_UNLOCK(name) _dbus_rmutex_unlock (_dbus_lock_##name)
+
+-/* 1-5 */
++/* index 0-4 */
+ _DBUS_DECLARE_GLOBAL_LOCK (list);
+ _DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
+ _DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots);
+ _DBUS_DECLARE_GLOBAL_LOCK (server_slots);
+ _DBUS_DECLARE_GLOBAL_LOCK (message_slots);
+-/* 5-10 */
++/* index 5-9 */
+ _DBUS_DECLARE_GLOBAL_LOCK (bus);
+ _DBUS_DECLARE_GLOBAL_LOCK (bus_datas);
+ _DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
+ _DBUS_DECLARE_GLOBAL_LOCK (system_users);
+ _DBUS_DECLARE_GLOBAL_LOCK (message_cache);
+-/* 10-14 */
++/* index 10-11 */
+ _DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
+-_DBUS_DECLARE_GLOBAL_LOCK (win_fds);
+-_DBUS_DECLARE_GLOBAL_LOCK (sid_atom_cache);
+ _DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+
+-#define _DBUS_N_GLOBAL_LOCKS (14)
++#define _DBUS_N_GLOBAL_LOCKS (12)
+
+ dbus_bool_t _dbus_threads_init_debug (void);
+
+diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
+index 04fb8d7..4e14ac3 100644
+--- a/dbus/dbus-sysdeps.c
++++ b/dbus/dbus-sysdeps.c
+@@ -46,8 +46,6 @@
+ #include <errno.h>
+ #endif
+
+-_DBUS_DEFINE_GLOBAL_LOCK (win_fds);
+-_DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
+ _DBUS_DEFINE_GLOBAL_LOCK (system_users);
+
+ #ifdef DBUS_WIN
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index 9a505de..9fbbae5 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -489,8 +489,6 @@ init_locks (void)
+ DBusRMutex ***dynamic_global_locks;
+ DBusRMutex **global_locks[] = {
+ #define LOCK_ADDR(name) (& _dbus_lock_##name)
+- LOCK_ADDR (win_fds),
+- LOCK_ADDR (sid_atom_cache),
+ LOCK_ADDR (list),
+ LOCK_ADDR (connection_slots),
+ LOCK_ADDR (pending_call_slots),
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 12:14:14 +0100
+Subject: Turn a runtime assertion into a compile-time assertion
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Applied-upstream: 1.7.4, commit:24a9b93021908b6f2b20eaacc1b36fa8fb24edb4
+Bug-Tizen: TZPC-1971
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Change-Id: I2784b0aa9046fba5a83065d32305c127a2a2dc78
+---
+ dbus/dbus-threads.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index 9fbbae5..43676bc 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -504,8 +504,7 @@ init_locks (void)
+ #undef LOCK_ADDR
+ };
+
+- _dbus_assert (_DBUS_N_ELEMENTS (global_locks) ==
+- _DBUS_N_GLOBAL_LOCKS);
++ _DBUS_STATIC_ASSERT (_DBUS_N_ELEMENTS (global_locks) == _DBUS_N_GLOBAL_LOCKS);
+
+ i = 0;
+
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 15:39:54 +0100
+Subject: Replace individual global-lock variables with an array of DBusRMutex
+ *
+
+This means we can use a much simpler code structure in data-slot
+allocators: instead of giving them a DBusRMutex ** at first-allocation,
+we can just give them an index into the array, which can be done
+statically.
+
+It doesn't make us any more thread-safe-by-default - the mutexes will
+only actually be used if threads were already initialized - but it's
+substantially better than nothing.
+
+These locks really do have to be recursive: for instance,
+internal_bus_get() calls dbus_bus_register() under the bus lock,
+and dbus_bus_register() can call _dbus_connection_close_possibly_shared(),
+which takes the bus lock.
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Applied-upstream: 1.7.6, commit:c80c20af46c5f43dcbe672f2c6d8aec0e7f2bbd6
+Bug-Tizen: TZPC-1971
+Change-Id: I22a31a9278b5f9c88557c54723f86827a91de818
+---
+ Doxyfile.in | 1 -
+ cmake/Doxyfile.cmake | 1 -
+ dbus/dbus-bus.c | 13 ------
+ dbus/dbus-connection.c | 7 ++--
+ dbus/dbus-dataslot.c | 62 +++++++++--------------------
+ dbus/dbus-dataslot.h | 8 ++--
+ dbus/dbus-internals.c | 19 +--------
+ dbus/dbus-internals.h | 59 ++++++++++++++++------------
+ dbus/dbus-list.c | 2 +-
+ dbus/dbus-memory.c | 18 ++++++---
+ dbus/dbus-message.c | 7 ++--
+ dbus/dbus-pending-call.c | 5 +--
+ dbus/dbus-server.c | 6 +--
+ dbus/dbus-sysdeps.c | 2 -
+ dbus/dbus-threads.c | 100 +++++++++++++++++++++--------------------------
+ 15 files changed, 126 insertions(+), 184 deletions(-)
+
+diff --git a/Doxyfile.in b/Doxyfile.in
+index afac639..f0a37ed 100644
+--- a/Doxyfile.in
++++ b/Doxyfile.in
+@@ -147,7 +147,6 @@ PREDEFINED = "DBUS_BEGIN_DECLS=" \
+ "DBUS_END_DECLS=" \
+ "DOXYGEN_SHOULD_SKIP_THIS" \
+ "DBUS_GNUC_DEPRECATED=" \
+- "_DBUS_DEFINE_GLOBAL_LOCK(name)=" \
+ "_DBUS_GNUC_PRINTF(from,to)="
+ SKIP_FUNCTION_MACROS = YES
+ #---------------------------------------------------------------------------
+diff --git a/cmake/Doxyfile.cmake b/cmake/Doxyfile.cmake
+index e00984e..3c63d95 100644
+--- a/cmake/Doxyfile.cmake
++++ b/cmake/Doxyfile.cmake
+@@ -147,7 +147,6 @@ PREDEFINED = "DBUS_BEGIN_DECLS=" \
+ "DBUS_END_DECLS=" \
+ "DOXYGEN_SHOULD_SKIP_THIS" \
+ "DBUS_GNUC_DEPRECATED=" \
+- "_DBUS_DEFINE_GLOBAL_LOCK(name)=" \
+ "_DBUS_GNUC_PRINTF(from,to)=" \
+ "DBUS_EXPORT="
+ SKIP_FUNCTION_MACROS = YES
+diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
+index fadc3a8..7a31cbd 100644
+--- a/dbus/dbus-bus.c
++++ b/dbus/dbus-bus.c
+@@ -95,19 +95,6 @@ static DBusBusType activation_bus_type = DBUS_BUS_STARTER;
+
+ static dbus_bool_t initialized = FALSE;
+
+-/**
+- * Lock for globals in this file
+- */
+-_DBUS_DEFINE_GLOBAL_LOCK (bus);
+-
+-/**
+- * Global lock covering all BusData on any connection. The bet is
+- * that some lock contention is better than more memory
+- * for a per-connection lock, but it's tough to imagine it mattering
+- * either way.
+- */
+-_DBUS_DEFINE_GLOBAL_LOCK (bus_datas);
+-
+ static void
+ addresses_shutdown_func (void *data)
+ {
+diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
+index 66315b3..03ee066 100644
+--- a/dbus/dbus-connection.c
++++ b/dbus/dbus-connection.c
+@@ -1531,7 +1531,7 @@ _dbus_connection_handle_watch (DBusWatch *watch,
+ return retval;
+ }
+
+-_DBUS_DEFINE_GLOBAL_LOCK (shared_connections);
++/* Protected by _DBUS_LOCK (shared_connections) */
+ static DBusHashTable *shared_connections = NULL;
+ static DBusList *shared_connections_no_guid = NULL;
+
+@@ -5852,8 +5852,8 @@ dbus_connection_list_registered (DBusConnection *connection,
+ return retval;
+ }
+
+-static DBusDataSlotAllocator slot_allocator;
+-_DBUS_DEFINE_GLOBAL_LOCK (connection_slots);
++static DBusDataSlotAllocator slot_allocator =
++ _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots));
+
+ /**
+ * Allocates an integer ID to be used for storing application-specific
+@@ -5873,7 +5873,6 @@ dbus_bool_t
+ dbus_connection_allocate_data_slot (dbus_int32_t *slot_p)
+ {
+ return _dbus_data_slot_allocator_alloc (&slot_allocator,
+- &_DBUS_LOCK_NAME (connection_slots),
+ slot_p);
+ }
+
+diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c
+index 0369612..b3c8090 100644
+--- a/dbus/dbus-dataslot.c
++++ b/dbus/dbus-dataslot.c
+@@ -43,13 +43,14 @@
+ * @param allocator the allocator to initialize
+ */
+ dbus_bool_t
+-_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
++_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator,
++ DBusGlobalLock lock)
+ {
+ allocator->allocated_slots = NULL;
+ allocator->n_allocated_slots = 0;
+ allocator->n_used_slots = 0;
+- allocator->lock_loc = NULL;
+-
++ allocator->lock = lock;
++
+ return TRUE;
+ }
+
+@@ -61,29 +62,16 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
+ * is allocated and stored at *slot_id_p.
+ *
+ * @param allocator the allocator
+- * @param mutex_loc the location lock for this allocator
+ * @param slot_id_p address to fill with the slot ID
+ * @returns #TRUE on success
+ */
+ dbus_bool_t
+ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
+- DBusRMutex **mutex_loc,
+ dbus_int32_t *slot_id_p)
+ {
+ dbus_int32_t slot;
+
+- _dbus_rmutex_lock (*mutex_loc);
+-
+- if (allocator->n_allocated_slots == 0)
+- {
+- _dbus_assert (allocator->lock_loc == NULL);
+- allocator->lock_loc = mutex_loc;
+- }
+- else if (allocator->lock_loc != mutex_loc)
+- {
+- _dbus_warn_check_failed ("D-Bus threads were initialized after first using the D-Bus library. If your application does not directly initialize threads or use D-Bus, keep in mind that some library or plugin may have used D-Bus or initialized threads behind your back. You can often fix this problem by calling dbus_init_threads() or dbus_g_threads_init() early in your main() method, before D-Bus is used.\n");
+- _dbus_assert_not_reached ("exiting");
+- }
++ _dbus_lock (allocator->lock);
+
+ if (*slot_id_p >= 0)
+ {
+@@ -146,7 +134,7 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
+ slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots);
+
+ out:
+- _dbus_rmutex_unlock (*(allocator->lock_loc));
++ _dbus_unlock (allocator->lock);
+ return slot >= 0;
+ }
+
+@@ -165,7 +153,7 @@ void
+ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
+ dbus_int32_t *slot_id_p)
+ {
+- _dbus_rmutex_lock (*(allocator->lock_loc));
++ _dbus_lock (allocator->lock);
+
+ _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
+ _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
+@@ -175,7 +163,7 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
+
+ if (allocator->allocated_slots[*slot_id_p].refcount > 0)
+ {
+- _dbus_rmutex_unlock (*(allocator->lock_loc));
++ _dbus_unlock (allocator->lock);
+ return;
+ }
+
+@@ -190,19 +178,12 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
+
+ if (allocator->n_used_slots == 0)
+ {
+- DBusRMutex **mutex_loc = allocator->lock_loc;
+-
+ dbus_free (allocator->allocated_slots);
+ allocator->allocated_slots = NULL;
+ allocator->n_allocated_slots = 0;
+- allocator->lock_loc = NULL;
+-
+- _dbus_rmutex_unlock (*mutex_loc);
+- }
+- else
+- {
+- _dbus_rmutex_unlock (*(allocator->lock_loc));
+ }
++
++ _dbus_unlock (allocator->lock);
+ }
+
+ /**
+@@ -247,10 +228,10 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
+ * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
+ * are disabled, since then the asserts are empty.
+ */
+- _dbus_rmutex_lock (*(allocator->lock_loc));
++ _dbus_lock (allocator->lock);
+ _dbus_assert (slot < allocator->n_allocated_slots);
+ _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+- _dbus_rmutex_unlock (*(allocator->lock_loc));
++ _dbus_unlock (allocator->lock);
+ #endif
+
+ if (slot >= list->n_slots)
+@@ -304,11 +285,11 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
+ * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
+ * are disabled, since then the asserts are empty.
+ */
+- _dbus_rmutex_lock (*(allocator->lock_loc));
++ _dbus_lock (allocator->lock);
+ _dbus_assert (slot >= 0);
+ _dbus_assert (slot < allocator->n_allocated_slots);
+ _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+- _dbus_rmutex_unlock (*(allocator->lock_loc));
++ _dbus_unlock (allocator->lock);
+ #endif
+
+ if (slot >= list->n_slots)
+@@ -384,17 +365,12 @@ _dbus_data_slot_test (void)
+ int i;
+ DBusFreeFunction old_free_func;
+ void *old_data;
+- DBusRMutex *mutex;
+-
+- if (!_dbus_data_slot_allocator_init (&allocator))
++
++ if (!_dbus_data_slot_allocator_init (&allocator, _DBUS_LOCK_server_slots))
+ _dbus_assert_not_reached ("no memory for allocator");
+
+ _dbus_data_slot_list_init (&list);
+
+- _dbus_rmutex_new_at_location (&mutex);
+- if (mutex == NULL)
+- _dbus_assert_not_reached ("failed to alloc mutex");
+-
+ #define N_SLOTS 100
+
+ i = 0;
+@@ -405,8 +381,8 @@ _dbus_data_slot_test (void)
+ * here.
+ */
+ dbus_int32_t tmp = -1;
+-
+- _dbus_data_slot_allocator_alloc (&allocator, &mutex, &tmp);
++
++ _dbus_data_slot_allocator_alloc (&allocator, &tmp);
+
+ if (tmp != i)
+ _dbus_assert_not_reached ("did not allocate slots in numeric order\n");
+@@ -471,8 +447,6 @@ _dbus_data_slot_test (void)
+ ++i;
+ }
+
+- _dbus_rmutex_free_at_location (&mutex);
+-
+ return TRUE;
+ }
+
+diff --git a/dbus/dbus-dataslot.h b/dbus/dbus-dataslot.h
+index 3d9d5ed..1e04fcb 100644
+--- a/dbus/dbus-dataslot.h
++++ b/dbus/dbus-dataslot.h
+@@ -57,9 +57,11 @@ struct DBusDataSlotAllocator
+ DBusAllocatedSlot *allocated_slots; /**< Allocated slots */
+ int n_allocated_slots; /**< number of slots malloc'd */
+ int n_used_slots; /**< number of slots used */
+- DBusRMutex **lock_loc; /**< location of thread lock */
++ DBusGlobalLock lock; /**< index of thread lock */
+ };
+
++#define _DBUS_DATA_SLOT_ALLOCATOR_INIT(x) { NULL, 0, 0, x }
++
+ /**
+ * Data structure that stores the actual user data set at a given
+ * slot.
+@@ -70,9 +72,9 @@ struct DBusDataSlotList
+ int n_slots; /**< Slots we have storage for in data_slots */
+ };
+
+-dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator);
++dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator,
++ DBusGlobalLock lock);
+ dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
+- DBusRMutex **mutex_loc,
+ int *slot_id_p);
+ void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
+ int *slot_id_p);
+diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
+index 0e5d807..1a36734 100644
+--- a/dbus/dbus-internals.c
++++ b/dbus/dbus-internals.c
+@@ -163,23 +163,6 @@
+ */
+
+ /**
+- * @def _DBUS_DEFINE_GLOBAL_LOCK
+- *
+- * Defines a global lock variable with the given name.
+- * The lock must be added to the list to initialize
+- * in dbus_threads_init().
+- */
+-
+-/**
+- * @def _DBUS_DECLARE_GLOBAL_LOCK
+- *
+- * Expands to declaration of a global lock defined
+- * with _DBUS_DEFINE_GLOBAL_LOCK.
+- * The lock must be added to the list to initialize
+- * in dbus_threads_init().
+- */
+-
+-/**
+ * @def _DBUS_LOCK
+ *
+ * Locks a global lock
+@@ -847,7 +830,7 @@ _dbus_read_uuid_file (const DBusString *filename,
+ }
+ }
+
+-_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
++/* Protected by _DBUS_LOCK (machine_uuid) */
+ static int machine_uuid_initialized_generation = 0;
+ static DBusGUID machine_uuid;
+
+diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
+index 336d22e..22ad297 100644
+--- a/dbus/dbus-internals.h
++++ b/dbus/dbus-internals.h
+@@ -297,35 +297,42 @@ dbus_bool_t _dbus_test_oom_handling (const char *description,
+ #endif /* !DBUS_BUILD_TESTS */
+
+ typedef void (* DBusShutdownFunction) (void *data);
+-dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function,
+- void *data);
++dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function,
++ void *data);
++dbus_bool_t _dbus_register_shutdown_func_unlocked (DBusShutdownFunction function,
++ void *data);
+
+ extern int _dbus_current_generation;
+
+-/* Thread initializers */
+-#define _DBUS_LOCK_NAME(name) _dbus_lock_##name
+-#define _DBUS_DECLARE_GLOBAL_LOCK(name) extern DBusRMutex *_dbus_lock_##name
+-#define _DBUS_DEFINE_GLOBAL_LOCK(name) DBusRMutex *_dbus_lock_##name
+-#define _DBUS_LOCK(name) _dbus_rmutex_lock (_dbus_lock_##name)
+-#define _DBUS_UNLOCK(name) _dbus_rmutex_unlock (_dbus_lock_##name)
+-
+-/* index 0-4 */
+-_DBUS_DECLARE_GLOBAL_LOCK (list);
+-_DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
+-_DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots);
+-_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
+-_DBUS_DECLARE_GLOBAL_LOCK (message_slots);
+-/* index 5-9 */
+-_DBUS_DECLARE_GLOBAL_LOCK (bus);
+-_DBUS_DECLARE_GLOBAL_LOCK (bus_datas);
+-_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
+-_DBUS_DECLARE_GLOBAL_LOCK (system_users);
+-_DBUS_DECLARE_GLOBAL_LOCK (message_cache);
+-/* index 10-11 */
+-_DBUS_DECLARE_GLOBAL_LOCK (shared_connections);
+-_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid);
+-
+-#define _DBUS_N_GLOBAL_LOCKS (12)
++/* The weird case convention is to avoid having to change all the callers,
++ * which would be quite a mega-patch. */
++typedef enum
++{
++ /* index 0-4 */
++ _DBUS_LOCK_list,
++ _DBUS_LOCK_connection_slots,
++ _DBUS_LOCK_pending_call_slots,
++ _DBUS_LOCK_server_slots,
++ _DBUS_LOCK_message_slots,
++ /* index 5-9 */
++ _DBUS_LOCK_bus,
++ _DBUS_LOCK_bus_datas,
++ _DBUS_LOCK_shutdown_funcs,
++ _DBUS_LOCK_system_users,
++ _DBUS_LOCK_message_cache,
++ /* index 10-11 */
++ _DBUS_LOCK_shared_connections,
++ _DBUS_LOCK_machine_uuid,
++
++ _DBUS_N_GLOBAL_LOCKS
++} DBusGlobalLock;
++
++void _dbus_lock (DBusGlobalLock lock);
++void _dbus_unlock (DBusGlobalLock lock);
++
++#define _DBUS_LOCK_NAME(name) _DBUS_LOCK_##name
++#define _DBUS_LOCK(name) _dbus_lock (_DBUS_LOCK_##name)
++#define _DBUS_UNLOCK(name) _dbus_unlock (_DBUS_LOCK_##name)
+
+ dbus_bool_t _dbus_threads_init_debug (void);
+
+diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
+index 7e11cc8..e5a4940 100644
+--- a/dbus/dbus-list.c
++++ b/dbus/dbus-list.c
+@@ -35,8 +35,8 @@
+ * Types and functions related to DBusList.
+ */
+
++/* Protected by _DBUS_LOCK (list) */
+ static DBusMemPool *list_pool;
+-_DBUS_DEFINE_GLOBAL_LOCK (list);
+
+ /**
+ * @defgroup DBusListInternals Linked list implementation details
+diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
+index 317e37e..a13b951 100644
+--- a/dbus/dbus-memory.c
++++ b/dbus/dbus-memory.c
+@@ -795,7 +795,7 @@ struct ShutdownClosure
+ void *data; /**< Data for function */
+ };
+
+-_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs);
++/* Protected by _DBUS_LOCK (shutdown_funcs) */
+ static ShutdownClosure *registered_globals = NULL;
+
+ /**
+@@ -810,6 +810,18 @@ dbus_bool_t
+ _dbus_register_shutdown_func (DBusShutdownFunction func,
+ void *data)
+ {
++ dbus_bool_t ok;
++
++ _DBUS_LOCK (shutdown_funcs);
++ ok = _dbus_register_shutdown_func_unlocked (func, data);
++ _DBUS_UNLOCK (shutdown_funcs);
++ return ok;
++}
++
++dbus_bool_t
++_dbus_register_shutdown_func_unlocked (DBusShutdownFunction func,
++ void *data)
++{
+ ShutdownClosure *c;
+
+ c = dbus_new (ShutdownClosure, 1);
+@@ -820,13 +832,9 @@ _dbus_register_shutdown_func (DBusShutdownFunction func,
+ c->func = func;
+ c->data = data;
+
+- _DBUS_LOCK (shutdown_funcs);
+-
+ c->next = registered_globals;
+ registered_globals = c;
+
+- _DBUS_UNLOCK (shutdown_funcs);
+-
+ return TRUE;
+ }
+
+diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
+index 71bcee6..2814569 100644
+--- a/dbus/dbus-message.c
++++ b/dbus/dbus-message.c
+@@ -506,7 +506,7 @@ _dbus_message_set_signature (DBusMessage *message,
+ /** Avoid caching too many messages */
+ #define MAX_MESSAGE_CACHE_SIZE 5
+
+-_DBUS_DEFINE_GLOBAL_LOCK (message_cache);
++/* Protected by _DBUS_LOCK (message_cache) */
+ static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
+ static int message_cache_count = 0;
+ static dbus_bool_t message_cache_shutdown_registered = FALSE;
+@@ -4423,8 +4423,8 @@ _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader)
+ return loader->max_message_unix_fds;
+ }
+
+-static DBusDataSlotAllocator slot_allocator;
+-_DBUS_DEFINE_GLOBAL_LOCK (message_slots);
++static DBusDataSlotAllocator slot_allocator =
++ _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
+
+ /**
+ * Allocates an integer ID to be used for storing application-specific
+@@ -4444,7 +4444,6 @@ dbus_bool_t
+ dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
+ {
+ return _dbus_data_slot_allocator_alloc (&slot_allocator,
+- &_DBUS_LOCK_NAME (message_slots),
+ slot_p);
+ }
+
+diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c
+index 62c6c74..1604408 100644
+--- a/dbus/dbus-pending-call.c
++++ b/dbus/dbus-pending-call.c
+@@ -489,8 +489,8 @@ _dbus_pending_call_get_completed_unlocked (DBusPendingCall *pending)
+ return pending->completed;
+ }
+
+-static DBusDataSlotAllocator slot_allocator;
+-_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
++static DBusDataSlotAllocator slot_allocator =
++ _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (pending_call_slots));
+
+ /**
+ * Stores a pointer on a #DBusPendingCall, along
+@@ -768,7 +768,6 @@ dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
+ _dbus_return_val_if_fail (slot_p != NULL, FALSE);
+
+ return _dbus_data_slot_allocator_alloc (&slot_allocator,
+- &_DBUS_LOCK_NAME (pending_call_slots),
+ slot_p);
+ }
+
+diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
+index b62c2b4..e021266 100644
+--- a/dbus/dbus-server.c
++++ b/dbus/dbus-server.c
+@@ -1071,9 +1071,8 @@ dbus_server_set_auth_mechanisms (DBusServer *server,
+ return TRUE;
+ }
+
+-
+-static DBusDataSlotAllocator slot_allocator;
+-_DBUS_DEFINE_GLOBAL_LOCK (server_slots);
++static DBusDataSlotAllocator slot_allocator =
++ _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (server_slots));
+
+ /**
+ * Allocates an integer ID to be used for storing application-specific
+@@ -1093,7 +1092,6 @@ dbus_bool_t
+ dbus_server_allocate_data_slot (dbus_int32_t *slot_p)
+ {
+ return _dbus_data_slot_allocator_alloc (&slot_allocator,
+- (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots),
+ slot_p);
+ }
+
+diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
+index 4e14ac3..0fbf9e7 100644
+--- a/dbus/dbus-sysdeps.c
++++ b/dbus/dbus-sysdeps.c
+@@ -46,8 +46,6 @@
+ #include <errno.h>
+ #endif
+
+-_DBUS_DEFINE_GLOBAL_LOCK (system_users);
+-
+ #ifdef DBUS_WIN
+ #include <stdlib.h>
+ #elif (defined __APPLE__)
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index 43676bc..297a7e4 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -343,23 +343,19 @@ _dbus_condvar_wake_one (DBusCondVar *cond)
+ _dbus_platform_condvar_wake_one (cond);
+ }
+
++static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL };
++
+ static void
+-shutdown_global_locks (void *data)
++shutdown_global_locks (void *nil)
+ {
+- DBusRMutex ***locks = data;
+ int i;
+
+- i = 0;
+- while (i < _DBUS_N_GLOBAL_LOCKS)
++ for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++)
+ {
+- if (*(locks[i]) != NULL)
+- _dbus_platform_rmutex_free (*(locks[i]));
+-
+- *(locks[i]) = NULL;
+- ++i;
++ _dbus_assert (global_locks[i] != NULL);
++ _dbus_platform_rmutex_free (global_locks[i]);
++ global_locks[i] = NULL;
+ }
+-
+- dbus_free (locks);
+ }
+
+ static void
+@@ -483,67 +479,60 @@ init_uninitialized_locks (void)
+ }
+
+ static dbus_bool_t
+-init_locks (void)
++init_global_locks (void)
+ {
+ int i;
+- DBusRMutex ***dynamic_global_locks;
+- DBusRMutex **global_locks[] = {
+-#define LOCK_ADDR(name) (& _dbus_lock_##name)
+- LOCK_ADDR (list),
+- LOCK_ADDR (connection_slots),
+- LOCK_ADDR (pending_call_slots),
+- LOCK_ADDR (server_slots),
+- LOCK_ADDR (message_slots),
+- LOCK_ADDR (bus),
+- LOCK_ADDR (bus_datas),
+- LOCK_ADDR (shutdown_funcs),
+- LOCK_ADDR (system_users),
+- LOCK_ADDR (message_cache),
+- LOCK_ADDR (shared_connections),
+- LOCK_ADDR (machine_uuid)
+-#undef LOCK_ADDR
+- };
+-
+- _DBUS_STATIC_ASSERT (_DBUS_N_ELEMENTS (global_locks) == _DBUS_N_GLOBAL_LOCKS);
+-
+- i = 0;
+-
+- dynamic_global_locks = dbus_new (DBusRMutex**, _DBUS_N_GLOBAL_LOCKS);
+- if (dynamic_global_locks == NULL)
+- goto failed;
+-
+- while (i < _DBUS_N_ELEMENTS (global_locks))
++ dbus_bool_t ok;
++
++ for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++)
+ {
+- *global_locks[i] = _dbus_platform_rmutex_new ();
++ _dbus_assert (global_locks[i] == NULL);
++
++ global_locks[i] = _dbus_platform_rmutex_new ();
+
+- if (*global_locks[i] == NULL)
++ if (global_locks[i] == NULL)
+ goto failed;
++ }
+
+- dynamic_global_locks[i] = global_locks[i];
++ _dbus_lock (_DBUS_LOCK_NAME (shutdown_funcs));
++ ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL);
++ _dbus_unlock (_DBUS_LOCK_NAME (shutdown_funcs));
+
+- ++i;
+- }
+-
+- if (!_dbus_register_shutdown_func (shutdown_global_locks,
+- dynamic_global_locks))
++ if (!ok)
+ goto failed;
+
+- if (!init_uninitialized_locks ())
+- goto failed;
+-
+ return TRUE;
+
+ failed:
+- dbus_free (dynamic_global_locks);
+-
+ for (i = i - 1; i >= 0; i--)
+ {
+- _dbus_platform_rmutex_free (*global_locks[i]);
+- *global_locks[i] = NULL;
++ _dbus_platform_rmutex_free (global_locks[i]);
++ global_locks[i] = NULL;
+ }
++
+ return FALSE;
+ }
+
++void
++_dbus_lock (DBusGlobalLock lock)
++{
++ _dbus_assert (lock >= 0);
++ _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
++
++ if (thread_init_generation == _dbus_current_generation)
++ _dbus_platform_rmutex_lock (global_locks[lock]);
++}
++
++void
++_dbus_unlock (DBusGlobalLock lock)
++{
++ _dbus_assert (lock >= 0);
++ _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
++
++ if (thread_init_generation == _dbus_current_generation)
++ _dbus_platform_rmutex_unlock (global_locks[lock]);
++}
++
+ /** @} */ /* end of internals */
+
+ /**
+@@ -587,7 +576,8 @@ dbus_threads_init (const DBusThreadFunctions *functions)
+ }
+
+ if (!_dbus_threads_init_platform_specific() ||
+- !init_locks ())
++ !init_global_locks () ||
++ !init_uninitialized_locks ())
+ {
+ _dbus_threads_unlock_platform_specific ();
+ return FALSE;
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 16:28:44 +0100
+Subject: Make taking a global lock automatically initialize locking if needed
+
+This lets them be thread-safe by default, at the cost that they can
+now fail.
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Applied-upstream: 1.7.6, commit:2b3272c75ae48c93911bd6f656965cf77d6de3e8
+Bug-Tizen: TZPC-1971
+Change-Id: I7e547e5776d37051ec8b6eccc2c8bd34b8d1996b
+---
+ bus/stats.c | 4 +--
+ dbus/dbus-bus.c | 52 ++++++++++++++++++++++++++++++--------
+ dbus/dbus-connection.c | 50 ++++++++++++++++++++++++++----------
+ dbus/dbus-dataslot.c | 19 ++++++++++----
+ dbus/dbus-internals.c | 8 ++++--
+ dbus/dbus-internals.h | 4 +--
+ dbus/dbus-list.c | 17 ++++++++++---
+ dbus/dbus-memory.c | 4 ++-
+ dbus/dbus-message.c | 19 +++++++++++---
+ dbus/dbus-threads.c | 28 +++++++++++++-------
+ dbus/dbus-userdb-util.c | 20 ++++++++++++---
+ dbus/dbus-userdb.c | 43 +++++++++++++++++++++++--------
+ dbus/dbus-userdb.h | 2 +-
+ test/name-test/test-threads-init.c | 14 ++++++----
+ 14 files changed, 213 insertions(+), 71 deletions(-)
+
+diff --git a/bus/stats.c b/bus/stats.c
+index 28fd49b..4553191 100644
+--- a/bus/stats.c
++++ b/bus/stats.c
+@@ -203,8 +203,8 @@ bus_stats_handle_get_stats (DBusConnection *connection,
+ if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
+ goto oom;
+
+- _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
+- if (!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
++ if (!_dbus_list_get_stats (&in_use, &in_free_list, &allocated) ||
++ !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
+ !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolCachedBytes",
+ in_free_list) ||
+ !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolAllocatedBytes",
+diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
+index 7a31cbd..3aa5c09 100644
+--- a/dbus/dbus-bus.c
++++ b/dbus/dbus-bus.c
+@@ -317,7 +317,11 @@ bus_data_free (void *data)
+ if (bd->is_well_known)
+ {
+ int i;
+- _DBUS_LOCK (bus);
++
++ if (!_DBUS_LOCK (bus))
++ _dbus_assert_not_reached ("global locks should have been initialized "
++ "when we attached bus data");
++
+ /* We may be stored in more than one slot */
+ /* This should now be impossible - these slots are supposed to
+ * be cleared on disconnect, so should not need to be cleared on
+@@ -388,8 +392,13 @@ void
+ _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection)
+ {
+ int i;
+-
+- _DBUS_LOCK (bus);
++
++ if (!_DBUS_LOCK (bus))
++ {
++ /* If it was in bus_connections, we would have initialized global locks
++ * when we added it. So, it can't be. */
++ return;
++ }
+
+ /* We are expecting to have the connection saved in only one of these
+ * slots, but someone could in a pathological case set system and session
+@@ -423,7 +432,12 @@ internal_bus_get (DBusBusType type,
+
+ connection = NULL;
+
+- _DBUS_LOCK (bus);
++ if (!_DBUS_LOCK (bus))
++ {
++ _DBUS_SET_OOM (error);
++ /* do not "goto out", that would try to unlock */
++ return NULL;
++ }
+
+ if (!init_connections_unlocked ())
+ {
+@@ -493,8 +507,10 @@ internal_bus_get (DBusBusType type,
+ */
+ dbus_connection_set_exit_on_disconnect (connection,
+ TRUE);
+-
+- _DBUS_LOCK (bus_datas);
++
++ if (!_DBUS_LOCK (bus_datas))
++ _dbus_assert_not_reached ("global locks were initialized already");
++
+ bd = ensure_bus_data (connection);
+ _dbus_assert (bd != NULL); /* it should have been created on
+ register, so OOM not possible */
+@@ -647,7 +663,12 @@ dbus_bus_register (DBusConnection *connection,
+ message = NULL;
+ reply = NULL;
+
+- _DBUS_LOCK (bus_datas);
++ if (!_DBUS_LOCK (bus_datas))
++ {
++ _DBUS_SET_OOM (error);
++ /* do not "goto out", that would try to unlock */
++ return FALSE;
++ }
+
+ bd = ensure_bus_data (connection);
+ if (bd == NULL)
+@@ -756,8 +777,12 @@ dbus_bus_set_unique_name (DBusConnection *connection,
+ _dbus_return_val_if_fail (connection != NULL, FALSE);
+ _dbus_return_val_if_fail (unique_name != NULL, FALSE);
+
+- _DBUS_LOCK (bus_datas);
+-
++ if (!_DBUS_LOCK (bus_datas))
++ {
++ /* do not "goto out", that would try to unlock */
++ return FALSE;
++ }
++
+ bd = ensure_bus_data (connection);
+ if (bd == NULL)
+ goto out;
+@@ -799,8 +824,13 @@ dbus_bus_get_unique_name (DBusConnection *connection)
+
+ _dbus_return_val_if_fail (connection != NULL, NULL);
+
+- _DBUS_LOCK (bus_datas);
+-
++ if (!_DBUS_LOCK (bus_datas))
++ {
++ /* We'd have initialized locks when we gave it its unique name, if it
++ * had one. Don't "goto out", that would try to unlock. */
++ return NULL;
++ }
++
+ bd = ensure_bus_data (connection);
+ if (bd == NULL)
+ goto out;
+diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
+index 03ee066..87cfeb0 100644
+--- a/dbus/dbus-connection.c
++++ b/dbus/dbus-connection.c
+@@ -1555,9 +1555,14 @@ static void
+ shared_connections_shutdown (void *data)
+ {
+ int n_entries;
+-
+- _DBUS_LOCK (shared_connections);
+-
++
++ if (!_DBUS_LOCK (shared_connections))
++ {
++ /* We'd have initialized locks before adding anything, so there
++ * can't be anything there. */
++ return;
++ }
++
+ /* This is a little bit unpleasant... better ideas? */
+ while ((n_entries = _dbus_hash_table_get_n_entries (shared_connections)) > 0)
+ {
+@@ -1571,7 +1576,8 @@ shared_connections_shutdown (void *data)
+
+ _DBUS_UNLOCK (shared_connections);
+ close_connection_on_shutdown (connection);
+- _DBUS_LOCK (shared_connections);
++ if (!_DBUS_LOCK (shared_connections))
++ _dbus_assert_not_reached ("global locks were already initialized");
+
+ /* The connection should now be dead and not in our hash ... */
+ _dbus_assert (_dbus_hash_table_get_n_entries (shared_connections) < n_entries);
+@@ -1590,7 +1596,8 @@ shared_connections_shutdown (void *data)
+ {
+ _DBUS_UNLOCK (shared_connections);
+ close_connection_on_shutdown (connection);
+- _DBUS_LOCK (shared_connections);
++ if (!_DBUS_LOCK (shared_connections))
++ _dbus_assert_not_reached ("global locks were already initialized");
+ connection = _dbus_list_pop_first (&shared_connections_no_guid);
+ }
+ }
+@@ -1607,8 +1614,13 @@ connection_lookup_shared (DBusAddressEntry *entry,
+ _dbus_verbose ("checking for existing connection\n");
+
+ *result = NULL;
+-
+- _DBUS_LOCK (shared_connections);
++
++ if (!_DBUS_LOCK (shared_connections))
++ {
++ /* If it was shared, we'd have initialized global locks when we put
++ * it in shared_connections. */
++ return FALSE;
++ }
+
+ if (shared_connections == NULL)
+ {
+@@ -1706,7 +1718,8 @@ connection_record_shared_unlocked (DBusConnection *connection,
+
+ if (guid == NULL)
+ {
+- _DBUS_LOCK (shared_connections);
++ if (!_DBUS_LOCK (shared_connections))
++ return FALSE;
+
+ if (!_dbus_list_prepend (&shared_connections_no_guid, connection))
+ {
+@@ -1733,8 +1746,14 @@ connection_record_shared_unlocked (DBusConnection *connection,
+ dbus_free (guid_key);
+ return FALSE;
+ }
+-
+- _DBUS_LOCK (shared_connections);
++
++ if (!_DBUS_LOCK (shared_connections))
++ {
++ dbus_free (guid_in_connection);
++ dbus_free (guid_key);
++ return FALSE;
++ }
++
+ _dbus_assert (shared_connections != NULL);
+
+ if (!_dbus_hash_table_insert_string (shared_connections,
+@@ -1765,9 +1784,14 @@ connection_forget_shared_unlocked (DBusConnection *connection)
+
+ if (!connection->shareable)
+ return;
+-
+- _DBUS_LOCK (shared_connections);
+-
++
++ if (!_DBUS_LOCK (shared_connections))
++ {
++ /* If it was shared, we'd have initialized global locks when we put
++ * it in the table; so it can't be there. */
++ return;
++ }
++
+ if (connection->server_guid != NULL)
+ {
+ _dbus_verbose ("dropping connection to %s out of the shared table\n",
+diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c
+index b3c8090..412e7f4 100644
+--- a/dbus/dbus-dataslot.c
++++ b/dbus/dbus-dataslot.c
+@@ -71,7 +71,8 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
+ {
+ dbus_int32_t slot;
+
+- _dbus_lock (allocator->lock);
++ if (!_dbus_lock (allocator->lock))
++ return FALSE;
+
+ if (*slot_id_p >= 0)
+ {
+@@ -153,8 +154,10 @@ void
+ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
+ dbus_int32_t *slot_id_p)
+ {
+- _dbus_lock (allocator->lock);
+-
++ if (!_dbus_lock (allocator->lock))
++ _dbus_assert_not_reached ("we should have initialized global locks "
++ "before we allocated this slot");
++
+ _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
+ _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
+ _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);
+@@ -228,7 +231,10 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
+ * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
+ * are disabled, since then the asserts are empty.
+ */
+- _dbus_lock (allocator->lock);
++ if (!_dbus_lock (allocator->lock))
++ _dbus_assert_not_reached ("we should have initialized global locks "
++ "before we allocated this slot");
++
+ _dbus_assert (slot < allocator->n_allocated_slots);
+ _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+ _dbus_unlock (allocator->lock);
+@@ -285,7 +291,10 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
+ * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
+ * are disabled, since then the asserts are empty.
+ */
+- _dbus_lock (allocator->lock);
++ if (!_dbus_lock (allocator->lock))
++ _dbus_assert_not_reached ("we should have initialized global locks "
++ "before we allocated this slot");
++
+ _dbus_assert (slot >= 0);
+ _dbus_assert (slot < allocator->n_allocated_slots);
+ _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
+diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
+index 1a36734..63559be 100644
+--- a/dbus/dbus-internals.c
++++ b/dbus/dbus-internals.c
+@@ -165,7 +165,9 @@
+ /**
+ * @def _DBUS_LOCK
+ *
+- * Locks a global lock
++ * Locks a global lock, initializing it first if necessary.
++ *
++ * @returns #FALSE if not enough memory
+ */
+
+ /**
+@@ -849,7 +851,9 @@ _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
+ {
+ dbus_bool_t ok;
+
+- _DBUS_LOCK (machine_uuid);
++ if (!_DBUS_LOCK (machine_uuid))
++ return FALSE;
++
+ if (machine_uuid_initialized_generation != _dbus_current_generation)
+ {
+ DBusError error = DBUS_ERROR_INIT;
+diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h
+index 22ad297..edde80b 100644
+--- a/dbus/dbus-internals.h
++++ b/dbus/dbus-internals.h
+@@ -327,8 +327,8 @@ typedef enum
+ _DBUS_N_GLOBAL_LOCKS
+ } DBusGlobalLock;
+
+-void _dbus_lock (DBusGlobalLock lock);
+-void _dbus_unlock (DBusGlobalLock lock);
++dbus_bool_t _dbus_lock (DBusGlobalLock lock) _DBUS_GNUC_WARN_UNUSED_RESULT;
++void _dbus_unlock (DBusGlobalLock lock);
+
+ #define _DBUS_LOCK_NAME(name) _DBUS_LOCK_##name
+ #define _DBUS_LOCK(name) _dbus_lock (_DBUS_LOCK_##name)
+diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
+index e5a4940..525e067 100644
+--- a/dbus/dbus-list.c
++++ b/dbus/dbus-list.c
+@@ -56,7 +56,8 @@ alloc_link (void *data)
+ {
+ DBusList *link;
+
+- _DBUS_LOCK (list);
++ if (!_DBUS_LOCK (list))
++ return FALSE;
+
+ if (list_pool == NULL)
+ {
+@@ -93,7 +94,10 @@ alloc_link (void *data)
+ static void
+ free_link (DBusList *link)
+ {
+- _DBUS_LOCK (list);
++ if (!_DBUS_LOCK (list))
++ _dbus_assert_not_reached ("we should have initialized global locks "
++ "before we allocated a linked-list link");
++
+ if (_dbus_mem_pool_dealloc (list_pool, link))
+ {
+ _dbus_mem_pool_free (list_pool);
+@@ -152,7 +156,14 @@ _dbus_list_get_stats (dbus_uint32_t *in_use_p,
+ dbus_uint32_t *in_free_list_p,
+ dbus_uint32_t *allocated_p)
+ {
+- _DBUS_LOCK (list);
++ if (!_DBUS_LOCK (list))
++ {
++ *in_use_p = 0;
++ *in_free_list_p = 0;
++ *allocated_p = 0;
++ return;
++ }
++
+ _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
+ _DBUS_UNLOCK (list);
+ }
+diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
+index a13b951..6cf0449 100644
+--- a/dbus/dbus-memory.c
++++ b/dbus/dbus-memory.c
+@@ -812,7 +812,9 @@ _dbus_register_shutdown_func (DBusShutdownFunction func,
+ {
+ dbus_bool_t ok;
+
+- _DBUS_LOCK (shutdown_funcs);
++ if (!_DBUS_LOCK (shutdown_funcs))
++ return FALSE;
++
+ ok = _dbus_register_shutdown_func_unlocked (func, data);
+ _DBUS_UNLOCK (shutdown_funcs);
+ return ok;
+diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
+index 2814569..275c425 100644
+--- a/dbus/dbus-message.c
++++ b/dbus/dbus-message.c
+@@ -516,7 +516,9 @@ dbus_message_cache_shutdown (void *data)
+ {
+ int i;
+
+- _DBUS_LOCK (message_cache);
++ if (!_DBUS_LOCK (message_cache))
++ _dbus_assert_not_reached ("we would have initialized global locks "
++ "before registering a shutdown function");
+
+ i = 0;
+ while (i < MAX_MESSAGE_CACHE_SIZE)
+@@ -548,7 +550,12 @@ dbus_message_get_cached (void)
+
+ message = NULL;
+
+- _DBUS_LOCK (message_cache);
++ if (!_DBUS_LOCK (message_cache))
++ {
++ /* we'd have initialized global locks before caching anything,
++ * so there can't be anything in the cache */
++ return NULL;
++ }
+
+ _dbus_assert (message_cache_count >= 0);
+
+@@ -660,7 +667,13 @@ dbus_message_cache_or_finalize (DBusMessage *message)
+
+ was_cached = FALSE;
+
+- _DBUS_LOCK (message_cache);
++ if (!_DBUS_LOCK (message_cache))
++ {
++ /* The only way to get a non-null message goes through
++ * dbus_message_get_cached() which takes the lock. */
++ _dbus_assert_not_reached ("we would have initialized global locks "
++ "the first time we constructed a message");
++ }
+
+ if (!message_cache_shutdown_registered)
+ {
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index 297a7e4..2c2a816 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -366,10 +366,12 @@ shutdown_uninitialized_locks (void *data)
+ _dbus_list_clear (&uninitialized_condvar_list);
+ }
+
++/* init_global_locks() must be called first. */
+ static dbus_bool_t
+ init_uninitialized_locks (void)
+ {
+ DBusList *link;
++ dbus_bool_t ok;
+
+ _dbus_assert (thread_init_generation != _dbus_current_generation);
+
+@@ -422,8 +424,12 @@ init_uninitialized_locks (void)
+ _dbus_list_clear (&uninitialized_cmutex_list);
+ _dbus_list_clear (&uninitialized_condvar_list);
+
+- if (!_dbus_register_shutdown_func (shutdown_uninitialized_locks,
+- NULL))
++ /* This assumes that init_global_locks() has already been called. */
++ _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
++ ok = _dbus_register_shutdown_func_unlocked (shutdown_uninitialized_locks, NULL);
++ _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
++
++ if (!ok)
+ goto fail_condvar;
+
+ return TRUE;
+@@ -494,9 +500,9 @@ init_global_locks (void)
+ goto failed;
+ }
+
+- _dbus_lock (_DBUS_LOCK_NAME (shutdown_funcs));
++ _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
+ ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL);
+- _dbus_unlock (_DBUS_LOCK_NAME (shutdown_funcs));
++ _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
+
+ if (!ok)
+ goto failed;
+@@ -513,14 +519,18 @@ init_global_locks (void)
+ return FALSE;
+ }
+
+-void
++dbus_bool_t
+ _dbus_lock (DBusGlobalLock lock)
+ {
+ _dbus_assert (lock >= 0);
+ _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
+
+- if (thread_init_generation == _dbus_current_generation)
+- _dbus_platform_rmutex_lock (global_locks[lock]);
++ if (thread_init_generation != _dbus_current_generation &&
++ !dbus_threads_init_default ())
++ return FALSE;
++
++ _dbus_platform_rmutex_lock (global_locks[lock]);
++ return TRUE;
+ }
+
+ void
+@@ -529,8 +539,7 @@ _dbus_unlock (DBusGlobalLock lock)
+ _dbus_assert (lock >= 0);
+ _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
+
+- if (thread_init_generation == _dbus_current_generation)
+- _dbus_platform_rmutex_unlock (global_locks[lock]);
++ _dbus_platform_rmutex_unlock (global_locks[lock]);
+ }
+
+ /** @} */ /* end of internals */
+@@ -576,6 +585,7 @@ dbus_threads_init (const DBusThreadFunctions *functions)
+ }
+
+ if (!_dbus_threads_init_platform_specific() ||
++ /* init_global_locks() must be called before init_uninitialized_locks. */
+ !init_global_locks () ||
+ !init_uninitialized_locks ())
+ {
+diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c
+index 16bf229..a8cc3d1 100644
+--- a/dbus/dbus-userdb-util.c
++++ b/dbus/dbus-userdb-util.c
+@@ -103,7 +103,11 @@ _dbus_is_console_user (dbus_uid_t uid,
+
+ #endif /* HAVE_CONSOLE_OWNER_FILE */
+
+- _dbus_user_database_lock_system ();
++ if (!_dbus_user_database_lock_system ())
++ {
++ _DBUS_SET_OOM (error);
++ return FALSE;
++ }
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+@@ -157,7 +161,10 @@ _dbus_get_group_id (const DBusString *groupname,
+ {
+ DBusUserDatabase *db;
+ const DBusGroupInfo *info;
+- _dbus_user_database_lock_system ();
++
++ /* FIXME: this can't distinguish ENOMEM from other errors */
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+@@ -194,7 +201,10 @@ _dbus_get_user_id_and_primary_group (const DBusString *username,
+ {
+ DBusUserDatabase *db;
+ const DBusUserInfo *info;
+- _dbus_user_database_lock_system ();
++
++ /* FIXME: this can't distinguish ENOMEM from other errors */
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+@@ -387,7 +397,9 @@ _dbus_groups_from_uid (dbus_uid_t uid,
+ *group_ids = NULL;
+ *n_group_ids = 0;
+
+- _dbus_user_database_lock_system ();
++ /* FIXME: this can't distinguish ENOMEM from other errors */
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c
+index 4e8b39a..73f8fce 100644
+--- a/dbus/dbus-userdb.c
++++ b/dbus/dbus-userdb.c
+@@ -306,11 +306,18 @@ init_system_db (void)
+ /**
+ * Locks global system user database.
+ */
+-void
++dbus_bool_t
+ _dbus_user_database_lock_system (void)
+ {
+- _DBUS_LOCK (system_users);
+- database_locked = TRUE;
++ if (_DBUS_LOCK (system_users))
++ {
++ database_locked = TRUE;
++ return TRUE;
++ }
++ else
++ {
++ return FALSE;
++ }
+ }
+
+ /**
+@@ -345,8 +352,12 @@ _dbus_user_database_get_system (void)
+ void
+ _dbus_user_database_flush_system (void)
+ {
+- _dbus_user_database_lock_system ();
+-
++ if (!_dbus_user_database_lock_system ())
++ {
++ /* nothing to flush */
++ return;
++ }
++
+ if (system_db != NULL)
+ _dbus_user_database_flush (system_db);
+
+@@ -363,7 +374,9 @@ _dbus_user_database_flush_system (void)
+ dbus_bool_t
+ _dbus_username_from_current_process (const DBusString **username)
+ {
+- _dbus_user_database_lock_system ();
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
++
+ if (!init_system_db ())
+ {
+ _dbus_user_database_unlock_system ();
+@@ -385,7 +398,9 @@ _dbus_username_from_current_process (const DBusString **username)
+ dbus_bool_t
+ _dbus_homedir_from_current_process (const DBusString **homedir)
+ {
+- _dbus_user_database_lock_system ();
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
++
+ if (!init_system_db ())
+ {
+ _dbus_user_database_unlock_system ();
+@@ -410,7 +425,10 @@ _dbus_homedir_from_username (const DBusString *username,
+ {
+ DBusUserDatabase *db;
+ const DBusUserInfo *info;
+- _dbus_user_database_lock_system ();
++
++ /* FIXME: this can't distinguish ENOMEM from other errors */
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+@@ -449,7 +467,10 @@ _dbus_homedir_from_uid (dbus_uid_t uid,
+ {
+ DBusUserDatabase *db;
+ const DBusUserInfo *info;
+- _dbus_user_database_lock_system ();
++
++ /* FIXME: this can't distinguish ENOMEM from other errors */
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+@@ -496,7 +517,9 @@ _dbus_credentials_add_from_user (DBusCredentials *credentials,
+ DBusUserDatabase *db;
+ const DBusUserInfo *info;
+
+- _dbus_user_database_lock_system ();
++ /* FIXME: this can't distinguish ENOMEM from other errors */
++ if (!_dbus_user_database_lock_system ())
++ return FALSE;
+
+ db = _dbus_user_database_get_system ();
+ if (db == NULL)
+diff --git a/dbus/dbus-userdb.h b/dbus/dbus-userdb.h
+index cb49d9e..d6b72d8 100644
+--- a/dbus/dbus-userdb.h
++++ b/dbus/dbus-userdb.h
+@@ -86,7 +86,7 @@ void _dbus_group_info_free_allocated (DBusGroupInfo *info);
+ #endif /* DBUS_USERDB_INCLUDES_PRIVATE */
+
+ DBusUserDatabase* _dbus_user_database_get_system (void);
+-void _dbus_user_database_lock_system (void);
++dbus_bool_t _dbus_user_database_lock_system (void) _DBUS_GNUC_WARN_UNUSED_RESULT;
+ void _dbus_user_database_unlock_system (void);
+ void _dbus_user_database_flush_system (void);
+
+diff --git a/test/name-test/test-threads-init.c b/test/name-test/test-threads-init.c
+index 5e22852..580ffe1 100644
+--- a/test/name-test/test-threads-init.c
++++ b/test/name-test/test-threads-init.c
+@@ -149,11 +149,15 @@ main (int argc, char *argv[])
+ &dispatch_cond1,
+ &io_path_cond1);
+
+- check_mutex_lock (mutex1, mutex2, FALSE);
+- check_mutex_lock (dispatch_mutex1, dispatch_mutex2, FALSE);
+- check_mutex_lock (io_path_mutex1, io_path_mutex2, FALSE);
+- check_condvar_lock (dispatch_cond1, dispatch_cond2, FALSE);
+- check_condvar_lock (io_path_cond1, io_path_cond2, FALSE);
++ /* Since 1.7 it is no longer the case that mutex1 != mutex2, because
++ * initializing global locks automatically initializes locks
++ * in general. However, it is true that the mutex is not the dummy
++ * implementation, which is what we really wanted to check here. */
++ _dbus_assert (mutex1 != (DBusMutex *) 0xABCDEF);
++ _dbus_assert (dispatch_mutex1 != (DBusMutex *) 0xABCDEF);
++ _dbus_assert (dispatch_cond1 != (DBusCondVar *) 0xABCDEF2);
++ _dbus_assert (io_path_mutex1 != (DBusMutex *) 0xABCDEF);
++ _dbus_assert (io_path_cond1 != (DBusCondVar *) 0xABCDEF2);
+
+ _run_iteration (conn);
+ _dbus_connection_test_get_locks (conn, &mutex2,
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 16:37:51 +0100
+Subject: Always initialize threading before allocating a dynamic mutex
+
+Dynamic allocation of mutexes can fail anyway, so this is easy.
+
+Justification for not keeping the dummy mutex code-paths, even as an
+opt-in thing for processes known to be high-performance and
+single-threaded: real mutexes only cut the throughput of
+test/dbus-daemon.c by a couple of percent on my laptop (from around
+6700 to around 6600 messages per second), and libdbus crashes caused
+by not calling dbus_threads_init_default() are sufficiently widespread
+that they're wasting a lot of everyone's time.
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Bug-Tizen: TZPC-1971
+Applied-upstream: 1.7.6, commit:08391b14616c248458e838691d068aa48dc70d18
+Change-Id: I62e4fc541f6868ef44dc0654337b895e5392c16e
+---
+ dbus/dbus-threads.c | 300 ++++++++++------------------------------------------
+ 1 file changed, 56 insertions(+), 244 deletions(-)
+
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index 2c2a816..29462eb 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -27,18 +27,6 @@
+ #include "dbus-list.h"
+
+ static int thread_init_generation = 0;
+-
+-static DBusList *uninitialized_rmutex_list = NULL;
+-static DBusList *uninitialized_cmutex_list = NULL;
+-static DBusList *uninitialized_condvar_list = NULL;
+-
+-/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */
+-#define _DBUS_DUMMY_MUTEX ((DBusMutex*)0xABCDEF)
+-#define _DBUS_DUMMY_RMUTEX ((DBusRMutex *) _DBUS_DUMMY_MUTEX)
+-#define _DBUS_DUMMY_CMUTEX ((DBusCMutex *) _DBUS_DUMMY_MUTEX)
+-
+-/** This is used for the no-op default mutex pointer, just to be distinct from #NULL */
+-#define _DBUS_DUMMY_CONDVAR ((DBusCondVar*)0xABCDEF2)
+
+ /**
+ * @defgroup DBusThreadsInternals Thread functions
+@@ -59,11 +47,6 @@ static DBusList *uninitialized_condvar_list = NULL;
+ * If possible, the mutex returned by this function is recursive, to
+ * avoid deadlocks. However, that cannot be relied on.
+ *
+- * The extra level of indirection given by allocating a pointer
+- * to point to the mutex location allows the threading
+- * module to swap out dummy mutexes for a real mutex so libraries
+- * can initialize threads even after the D-Bus API has been used.
+- *
+ * @param location_p the location of the new mutex, can return #NULL on OOM
+ */
+ void
+@@ -71,17 +54,13 @@ _dbus_rmutex_new_at_location (DBusRMutex **location_p)
+ {
+ _dbus_assert (location_p != NULL);
+
+- if (thread_init_generation == _dbus_current_generation)
++ if (!dbus_threads_init_default ())
+ {
+- *location_p = _dbus_platform_rmutex_new ();
++ *location_p = NULL;
++ return;
+ }
+- else
+- {
+- *location_p = _DBUS_DUMMY_RMUTEX;
+
+- if (!_dbus_list_append (&uninitialized_rmutex_list, location_p))
+- *location_p = NULL;
+- }
++ *location_p = _dbus_platform_rmutex_new ();
+ }
+
+ /**
+@@ -92,11 +71,6 @@ _dbus_rmutex_new_at_location (DBusRMutex **location_p)
+ *
+ * The returned mutex is suitable for use with condition variables.
+ *
+- * The extra level of indirection given by allocating a pointer
+- * to point to the mutex location allows the threading
+- * module to swap out dummy mutexes for a real mutex so libraries
+- * can initialize threads even after the D-Bus API has been used.
+- *
+ * @param location_p the location of the new mutex, can return #NULL on OOM
+ */
+ void
+@@ -104,22 +78,17 @@ _dbus_cmutex_new_at_location (DBusCMutex **location_p)
+ {
+ _dbus_assert (location_p != NULL);
+
+- if (thread_init_generation == _dbus_current_generation)
++ if (!dbus_threads_init_default ())
+ {
+- *location_p = _dbus_platform_cmutex_new ();
++ *location_p = NULL;
++ return;
+ }
+- else
+- {
+- *location_p = _DBUS_DUMMY_CMUTEX;
+
+- if (!_dbus_list_append (&uninitialized_cmutex_list, location_p))
+- *location_p = NULL;
+- }
++ *location_p = _dbus_platform_cmutex_new ();
+ }
+
+ /**
+- * Frees a DBusRMutex or removes it from the uninitialized mutex list;
+- * does nothing if passed a #NULL pointer.
++ * Frees a DBusRMutex; does nothing if passed a #NULL pointer.
+ */
+ void
+ _dbus_rmutex_free_at_location (DBusRMutex **location_p)
+@@ -127,23 +96,12 @@ _dbus_rmutex_free_at_location (DBusRMutex **location_p)
+ if (location_p == NULL)
+ return;
+
+- if (thread_init_generation == _dbus_current_generation)
+- {
+- if (*location_p != NULL)
+- _dbus_platform_rmutex_free (*location_p);
+- }
+- else
+- {
+- _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_RMUTEX);
+-
+- _dbus_list_remove (&uninitialized_rmutex_list, location_p);
+- }
++ if (*location_p != NULL)
++ _dbus_platform_rmutex_free (*location_p);
+ }
+
+ /**
+- * Frees a DBusCMutex and removes it from the
+- * uninitialized mutex list;
+- * does nothing if passed a #NULL pointer.
++ * Frees a DBusCMutex; does nothing if passed a #NULL pointer.
+ */
+ void
+ _dbus_cmutex_free_at_location (DBusCMutex **location_p)
+@@ -151,17 +109,8 @@ _dbus_cmutex_free_at_location (DBusCMutex **location_p)
+ if (location_p == NULL)
+ return;
+
+- if (thread_init_generation == _dbus_current_generation)
+- {
+- if (*location_p != NULL)
+- _dbus_platform_cmutex_free (*location_p);
+- }
+- else
+- {
+- _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CMUTEX);
+-
+- _dbus_list_remove (&uninitialized_cmutex_list, location_p);
+- }
++ if (*location_p != NULL)
++ _dbus_platform_cmutex_free (*location_p);
+ }
+
+ /**
+@@ -172,8 +121,10 @@ _dbus_cmutex_free_at_location (DBusCMutex **location_p)
+ void
+ _dbus_rmutex_lock (DBusRMutex *mutex)
+ {
+- if (mutex && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_rmutex_lock (mutex);
++ if (mutex == NULL)
++ return;
++
++ _dbus_platform_rmutex_lock (mutex);
+ }
+
+ /**
+@@ -184,8 +135,10 @@ _dbus_rmutex_lock (DBusRMutex *mutex)
+ void
+ _dbus_cmutex_lock (DBusCMutex *mutex)
+ {
+- if (mutex && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_cmutex_lock (mutex);
++ if (mutex == NULL)
++ return;
++
++ _dbus_platform_cmutex_lock (mutex);
+ }
+
+ /**
+@@ -196,8 +149,10 @@ _dbus_cmutex_lock (DBusCMutex *mutex)
+ void
+ _dbus_rmutex_unlock (DBusRMutex *mutex)
+ {
+- if (mutex && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_rmutex_unlock (mutex);
++ if (mutex == NULL)
++ return;
++
++ _dbus_platform_rmutex_unlock (mutex);
+ }
+
+ /**
+@@ -208,8 +163,10 @@ _dbus_rmutex_unlock (DBusRMutex *mutex)
+ void
+ _dbus_cmutex_unlock (DBusCMutex *mutex)
+ {
+- if (mutex && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_cmutex_unlock (mutex);
++ if (mutex == NULL)
++ return;
++
++ _dbus_platform_cmutex_unlock (mutex);
+ }
+
+ /**
+@@ -223,19 +180,17 @@ _dbus_cmutex_unlock (DBusCMutex *mutex)
+ DBusCondVar *
+ _dbus_condvar_new (void)
+ {
+- if (thread_init_generation == _dbus_current_generation)
+- return _dbus_platform_condvar_new ();
+- else
+- return _DBUS_DUMMY_CONDVAR;
++ if (!dbus_threads_init_default ())
++ return NULL;
++
++ return _dbus_platform_condvar_new ();
+ }
+
+
+ /**
+ * This does the same thing as _dbus_condvar_new. It however
+ * gives another level of indirection by allocating a pointer
+- * to point to the condvar location. This allows the threading
+- * module to swap out dummy condvars for a real condvar so libraries
+- * can initialize threads even after the D-Bus API has been used.
++ * to point to the condvar location; this used to be useful.
+ *
+ * @returns the location of a new condvar or #NULL on OOM
+ */
+@@ -245,17 +200,7 @@ _dbus_condvar_new_at_location (DBusCondVar **location_p)
+ {
+ _dbus_assert (location_p != NULL);
+
+- if (thread_init_generation == _dbus_current_generation)
+- {
+- *location_p = _dbus_condvar_new();
+- }
+- else
+- {
+- *location_p = _DBUS_DUMMY_CONDVAR;
+-
+- if (!_dbus_list_append (&uninitialized_condvar_list, location_p))
+- *location_p = NULL;
+- }
++ *location_p = _dbus_condvar_new();
+ }
+
+
+@@ -266,14 +211,14 @@ _dbus_condvar_new_at_location (DBusCondVar **location_p)
+ void
+ _dbus_condvar_free (DBusCondVar *cond)
+ {
+- if (cond && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_condvar_free (cond);
++ if (cond == NULL)
++ return;
++
++ _dbus_platform_condvar_free (cond);
+ }
+
+ /**
+- * Frees a conditional variable and removes it from the
+- * uninitialized_condvar_list;
+- * does nothing if passed a #NULL pointer.
++ * Frees a condition variable; does nothing if passed a #NULL pointer.
+ */
+ void
+ _dbus_condvar_free_at_location (DBusCondVar **location_p)
+@@ -281,17 +226,8 @@ _dbus_condvar_free_at_location (DBusCondVar **location_p)
+ if (location_p == NULL)
+ return;
+
+- if (thread_init_generation == _dbus_current_generation)
+- {
+- if (*location_p != NULL)
+- _dbus_platform_condvar_free (*location_p);
+- }
+- else
+- {
+- _dbus_assert (*location_p == NULL || *location_p == _DBUS_DUMMY_CONDVAR);
+-
+- _dbus_list_remove (&uninitialized_condvar_list, location_p);
+- }
++ if (*location_p != NULL)
++ _dbus_platform_condvar_free (*location_p);
+ }
+
+ /**
+@@ -304,8 +240,10 @@ void
+ _dbus_condvar_wait (DBusCondVar *cond,
+ DBusCMutex *mutex)
+ {
+- if (cond && mutex && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_condvar_wait (cond, mutex);
++ if (cond == NULL || mutex == NULL)
++ return;
++
++ _dbus_platform_condvar_wait (cond, mutex);
+ }
+
+ /**
+@@ -324,11 +262,11 @@ _dbus_condvar_wait_timeout (DBusCondVar *cond,
+ DBusCMutex *mutex,
+ int timeout_milliseconds)
+ {
+- if (cond && mutex && thread_init_generation == _dbus_current_generation)
+- return _dbus_platform_condvar_wait_timeout (cond, mutex,
+- timeout_milliseconds);
+- else
++ if (cond == NULL || mutex == NULL)
+ return TRUE;
++
++ return _dbus_platform_condvar_wait_timeout (cond, mutex,
++ timeout_milliseconds);
+ }
+
+ /**
+@@ -339,8 +277,10 @@ _dbus_condvar_wait_timeout (DBusCondVar *cond,
+ void
+ _dbus_condvar_wake_one (DBusCondVar *cond)
+ {
+- if (cond && thread_init_generation == _dbus_current_generation)
+- _dbus_platform_condvar_wake_one (cond);
++ if (cond == NULL)
++ return;
++
++ _dbus_platform_condvar_wake_one (cond);
+ }
+
+ static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL };
+@@ -358,132 +298,6 @@ shutdown_global_locks (void *nil)
+ }
+ }
+
+-static void
+-shutdown_uninitialized_locks (void *data)
+-{
+- _dbus_list_clear (&uninitialized_rmutex_list);
+- _dbus_list_clear (&uninitialized_cmutex_list);
+- _dbus_list_clear (&uninitialized_condvar_list);
+-}
+-
+-/* init_global_locks() must be called first. */
+-static dbus_bool_t
+-init_uninitialized_locks (void)
+-{
+- DBusList *link;
+- dbus_bool_t ok;
+-
+- _dbus_assert (thread_init_generation != _dbus_current_generation);
+-
+- link = uninitialized_rmutex_list;
+- while (link != NULL)
+- {
+- DBusRMutex **mp;
+-
+- mp = link->data;
+- _dbus_assert (*mp == _DBUS_DUMMY_RMUTEX);
+-
+- *mp = _dbus_platform_rmutex_new ();
+- if (*mp == NULL)
+- goto fail_mutex;
+-
+- link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link);
+- }
+-
+- link = uninitialized_cmutex_list;
+- while (link != NULL)
+- {
+- DBusCMutex **mp;
+-
+- mp = link->data;
+- _dbus_assert (*mp == _DBUS_DUMMY_CMUTEX);
+-
+- *mp = _dbus_platform_cmutex_new ();
+- if (*mp == NULL)
+- goto fail_mutex;
+-
+- link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link);
+- }
+-
+- link = uninitialized_condvar_list;
+- while (link != NULL)
+- {
+- DBusCondVar **cp;
+-
+- cp = (DBusCondVar **)link->data;
+- _dbus_assert (*cp == _DBUS_DUMMY_CONDVAR);
+-
+- *cp = _dbus_platform_condvar_new ();
+- if (*cp == NULL)
+- goto fail_condvar;
+-
+- link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
+- }
+-
+- _dbus_list_clear (&uninitialized_rmutex_list);
+- _dbus_list_clear (&uninitialized_cmutex_list);
+- _dbus_list_clear (&uninitialized_condvar_list);
+-
+- /* This assumes that init_global_locks() has already been called. */
+- _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
+- ok = _dbus_register_shutdown_func_unlocked (shutdown_uninitialized_locks, NULL);
+- _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
+-
+- if (!ok)
+- goto fail_condvar;
+-
+- return TRUE;
+-
+- fail_condvar:
+- link = uninitialized_condvar_list;
+- while (link != NULL)
+- {
+- DBusCondVar **cp;
+-
+- cp = link->data;
+-
+- if (*cp != _DBUS_DUMMY_CONDVAR && *cp != NULL)
+- _dbus_platform_condvar_free (*cp);
+-
+- *cp = _DBUS_DUMMY_CONDVAR;
+-
+- link = _dbus_list_get_next_link (&uninitialized_condvar_list, link);
+- }
+-
+- fail_mutex:
+- link = uninitialized_rmutex_list;
+- while (link != NULL)
+- {
+- DBusRMutex **mp;
+-
+- mp = link->data;
+-
+- if (*mp != _DBUS_DUMMY_RMUTEX && *mp != NULL)
+- _dbus_platform_rmutex_free (*mp);
+-
+- *mp = _DBUS_DUMMY_RMUTEX;
+-
+- link = _dbus_list_get_next_link (&uninitialized_rmutex_list, link);
+- }
+-
+- link = uninitialized_cmutex_list;
+- while (link != NULL)
+- {
+- DBusCMutex **mp;
+-
+- mp = link->data;
+-
+- if (*mp != _DBUS_DUMMY_CMUTEX && *mp != NULL)
+- _dbus_platform_cmutex_free (*mp);
+-
+- *mp = _DBUS_DUMMY_CMUTEX;
+-
+- link = _dbus_list_get_next_link (&uninitialized_cmutex_list, link);
+- }
+-
+- return FALSE;
+-}
+-
+ static dbus_bool_t
+ init_global_locks (void)
+ {
+@@ -585,9 +399,7 @@ dbus_threads_init (const DBusThreadFunctions *functions)
+ }
+
+ if (!_dbus_threads_init_platform_specific() ||
+- /* init_global_locks() must be called before init_uninitialized_locks. */
+- !init_global_locks () ||
+- !init_uninitialized_locks ())
++ !init_global_locks ())
+ {
+ _dbus_threads_unlock_platform_specific ();
+ return FALSE;
--- /dev/null
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Tue, 16 Apr 2013 16:48:11 +0100
+Subject: Add a statically-initialized implementation of _dbus_lock() on glibc
+ systems
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54972
+Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Reviewed-by: Alban Crequy <alban.crequy@collabora.co.uk>
+Reviewed-by: Anas Nashif <anas.nashif@intel.com>
+Bug-Tizen: TZPC-1971
+Applied-upstream: 1.7.6, commit:83aaa9f359e90d3b8cae5d17f6d9ba4600cff68b
+Change-Id: Iee8ec5e2138ad8398efbe1cd16b46e61cee08670
+---
+ dbus/dbus-sysdeps-pthread.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
+ dbus/dbus-threads-internal.h | 6 ++++++
+ dbus/dbus-threads.c | 14 +++++++++++++
+ 3 files changed, 67 insertions(+)
+
+diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c
+index 1b5d0ba..da7d937 100644
+--- a/dbus/dbus-sysdeps-pthread.c
++++ b/dbus/dbus-sysdeps-pthread.c
+@@ -298,3 +298,50 @@ _dbus_threads_unlock_platform_specific (void)
+ {
+ pthread_mutex_unlock (&init_mutex);
+ }
++
++#ifdef DBUS_HAVE_STATIC_RECURSIVE_MUTEXES
++
++static pthread_mutex_t global_locks[] = {
++ /* 0-4 */
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ /* 5-9 */
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ /* 10-11 */
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
++};
++
++_DBUS_STATIC_ASSERT (_DBUS_N_ELEMENTS (global_locks) == _DBUS_N_GLOBAL_LOCKS);
++
++dbus_bool_t
++_dbus_lock (DBusGlobalLock lock)
++{
++ /* No initialization is needed. */
++ _dbus_assert (lock >= 0);
++ _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
++
++ PTHREAD_CHECK ("pthread_mutex_lock",
++ pthread_mutex_lock (&(global_locks[lock])));
++ return TRUE;
++}
++
++void
++_dbus_unlock (DBusGlobalLock lock)
++{
++ /* No initialization is needed. */
++ _dbus_assert (lock >= 0);
++ _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
++
++ PTHREAD_CHECK ("pthread_mutex_unlock",
++ pthread_mutex_unlock (&(global_locks[lock])));
++}
++
++#endif
+diff --git a/dbus/dbus-threads-internal.h b/dbus/dbus-threads-internal.h
+index 64e8bac..228a8c0 100644
+--- a/dbus/dbus-threads-internal.h
++++ b/dbus/dbus-threads-internal.h
+@@ -32,6 +32,12 @@
+ * @{
+ */
+
++/* glibc can implement global locks without needing an initialization step,
++ * which improves our thread-safety-by-default further. */
++#if defined(__GLIBC__) && defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
++# define DBUS_HAVE_STATIC_RECURSIVE_MUTEXES 1
++#endif
++
+ /**
+ * A mutex which is recursive if possible, else non-recursive.
+ * This is typically recursive, but that cannot be relied upon.
+diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c
+index 29462eb..1781bda 100644
+--- a/dbus/dbus-threads.c
++++ b/dbus/dbus-threads.c
+@@ -283,6 +283,18 @@ _dbus_condvar_wake_one (DBusCondVar *cond)
+ _dbus_platform_condvar_wake_one (cond);
+ }
+
++#ifdef DBUS_HAVE_STATIC_RECURSIVE_MUTEXES
++
++static dbus_bool_t
++init_global_locks (void)
++{
++ return TRUE;
++}
++
++/* implementations in dbus-sysdeps-pthread.c */
++
++#else /* !defined(DBUS_HAVE_STATIC_RECURSIVE_MUTEXES) */
++
+ static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL };
+
+ static void
+@@ -356,6 +368,8 @@ _dbus_unlock (DBusGlobalLock lock)
+ _dbus_platform_rmutex_unlock (global_locks[lock]);
+ }
+
++#endif /* !defined(DBUS_HAVE_STATIC_RECURSIVE_MUTEXES) */
++
+ /** @} */ /* end of internals */
+
+ /**
--- /dev/null
+From: Brian McGillion <brian.mcgillion@intel.com>
+Date: Mon, 6 Feb 2012 18:46:05 +0200
+Subject: Enable checking of smack context from DBus interface
+
+---
+ bus/Makefile.am | 4 ++
+ bus/driver.c | 6 +++
+ bus/smack.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++
+ bus/smack.h | 36 +++++++++++++
+ cmake/CMakeLists.txt | 3 ++
+ cmake/bus/CMakeLists.txt | 4 +-
+ configure.ac | 17 +++++-
+ 7 files changed, 199 insertions(+), 3 deletions(-)
+ create mode 100644 bus/smack.c
+ create mode 100644 bus/smack.h
+
+diff --git a/bus/Makefile.am b/bus/Makefile.am
+index 6cbc09a..7f63d86 100644
+--- a/bus/Makefile.am
++++ b/bus/Makefile.am
+@@ -7,6 +7,7 @@ DBUS_BUS_LIBS = \
+ $(THREAD_LIBS) \
+ $(ADT_LIBS) \
+ $(NETWORK_libs) \
++ $(LIBSMACK_LIBS) \
+ $(NULL)
+
+ DBUS_LAUNCHER_LIBS = \
+@@ -21,6 +22,7 @@ AM_CPPFLAGS = \
+ -DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \
+ -DDBUS_COMPILATION \
+ -DDBUS_STATIC_BUILD \
++ $(LIBSMACK_CFLAGS) \
+ $(NULL)
+
+ # if assertions are enabled, improve backtraces
+@@ -93,6 +95,8 @@ BUS_SOURCES= \
+ services.h \
+ signals.c \
+ signals.h \
++ smack.c \
++ smack.h \
+ stats.c \
+ stats.h \
+ test.c \
+diff --git a/bus/driver.c b/bus/driver.c
+index 574e0f3..c6298d7 100644
+--- a/bus/driver.c
++++ b/bus/driver.c
+@@ -30,6 +30,7 @@
+ #include "services.h"
+ #include "selinux.h"
+ #include "signals.h"
++#include "smack.h"
+ #include "stats.h"
+ #include "utils.h"
+ #include <dbus/dbus-string.h>
+@@ -38,6 +39,7 @@
+ #include <dbus/dbus-marshal-recursive.h>
+ #include <string.h>
+
++
+ static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
+ DBusMessage *hello_message,
+ BusTransaction *transaction,
+@@ -1736,6 +1738,10 @@ static const MessageHandler dbus_message_handlers[] = {
+ "",
+ DBUS_TYPE_STRING_AS_STRING,
+ bus_driver_handle_get_id },
++ { "GetConnectionSmackContext",
++ DBUS_TYPE_STRING_AS_STRING,
++ DBUS_TYPE_STRING_AS_STRING,
++ bus_smack_handle_get_connection_context },
+ { NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/bus/smack.c b/bus/smack.c
+new file mode 100644
+index 0000000..b8542c2
+--- /dev/null
++++ b/bus/smack.c
+@@ -0,0 +1,132 @@
++/* smack.c - Provide interface to query smack context
++ *
++ * Author: Brian McGillion <brian.mcgillion@intel.com>
++ * Copyright © 2011 Intel Corporation
++ *
++ * Licensed under the Academic Free License version 2.1
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <config.h>
++#include "smack.h"
++
++#include <dbus/dbus-internals.h>
++
++#include "connection.h"
++#include "services.h"
++#include "utils.h"
++
++#ifdef DBUS_ENABLE_SMACK
++#include <sys/smack.h>
++#endif
++
++#ifdef DBUS_ENABLE_SMACK
++static char *
++bus_smack_get_label (DBusConnection *connection)
++{
++ char *label;
++ int sock_fd;
++
++ if (!dbus_connection_get_socket(connection, &sock_fd))
++ return NULL;
++
++ if (smack_new_label_from_socket(sock_fd, &label) < 0)
++ return NULL;
++ return label;
++}
++#endif
++
++dbus_bool_t
++bus_smack_handle_get_connection_context (DBusConnection *connection,
++ BusTransaction *transaction,
++ DBusMessage *message,
++ DBusError *error)
++{
++#ifdef DBUS_ENABLE_SMACK
++ const char *remote_end = NULL;
++ BusRegistry *registry;
++ DBusString remote_end_str;
++ BusService *service;
++ DBusConnection *remote_connection;
++ DBusMessage *reply = NULL;
++ char *label;
++
++ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
++
++ registry = bus_connection_get_registry (connection);
++
++ if (!dbus_message_get_args (message, error, DBUS_TYPE_STRING, &remote_end,
++ DBUS_TYPE_INVALID))
++ return FALSE;
++
++ _dbus_verbose ("asked for label of connection %s\n", remote_end);
++
++ _dbus_string_init_const (&remote_end_str, remote_end);
++
++ service = bus_registry_lookup (registry, &remote_end_str);
++ if (service == NULL)
++ {
++ dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
++ "Bus name '%s' has no owner", remote_end);
++ return FALSE;
++ }
++
++ remote_connection = bus_service_get_primary_owners_connection (service);
++ if (remote_connection == NULL)
++ goto oom;
++
++ reply = dbus_message_new_method_return (message);
++ if (reply == NULL)
++ goto oom;
++
++ label = bus_smack_get_label (remote_connection);
++ if (label == NULL)
++ {
++ dbus_set_error (error, DBUS_ERROR_FAILED,
++ "Failed to get the socket fd of the connection",
++ remote_end);
++ goto err;
++ }
++
++ if (!dbus_message_append_args (reply, DBUS_TYPE_STRING,
++ &label, DBUS_TYPE_INVALID))
++ goto oom;
++
++ if (!bus_transaction_send_from_driver (transaction, connection, reply))
++ goto oom;
++
++ dbus_message_unref (reply);
++ dbus_free(label);
++
++ return TRUE;
++
++oom:
++ BUS_SET_OOM (error);
++
++err:
++ if (reply != NULL)
++ dbus_message_unref (reply);
++
++ dbus_free(label);
++
++ return FALSE;
++#else
++ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
++ "SMACK support is not enabled");
++ return FALSE;
++#endif
++}
+diff --git a/bus/smack.h b/bus/smack.h
+new file mode 100644
+index 0000000..04a4a2a
+--- /dev/null
++++ b/bus/smack.h
+@@ -0,0 +1,36 @@
++/* smack.h - Provide interface to query smack context
++ *
++ * Author: Brian McGillion <brian.mcgillion@intel.com>
++ * Copyright © 2011 Intel Corporation
++ *
++ * Based on example from Stats interface
++ *
++ * Licensed under the Academic Free License version 2.1
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#ifndef SMACK_H
++#define SMACK_H
++
++#include "bus.h"
++
++dbus_bool_t bus_smack_handle_get_connection_context (DBusConnection *connection,
++ BusTransaction *transaction,
++ DBusMessage *message,
++ DBusError *error);
++
++#endif // SMACK_H
+diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
+index 000acda..68b7a9e 100644
+--- a/cmake/CMakeLists.txt
++++ b/cmake/CMakeLists.txt
+@@ -94,6 +94,8 @@ option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
+
+ option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
+
++option (DBUS_ENABLE_SMACK "enable smack checks in the daemon" OFF)
++
+ if (DBUS_USE_EXPAT)
+ find_package(LibExpat)
+ else ()
+@@ -555,6 +557,7 @@ message(" Building bus stats API: ${DBUS_ENABLE_STATS} "
+ message(" installing system libs: ${DBUS_INSTALL_SYSTEM_LIBS} ")
+ #message(" Building SELinux support: ${have_selinux} ")
+ #message(" Building dnotify support: ${have_dnotify} ")
++message(" Building Smack support: ${DBUS_ENABLE_SMACK} ")
+ message(" Building Doxygen docs: ${DBUS_ENABLE_DOXYGEN_DOCS} ")
+ message(" Building XML docs: ${DBUS_ENABLE_XML_DOCS} ")
+ #message(" Gettext libs (empty OK): ${INTLLIBS} ")
+diff --git a/cmake/bus/CMakeLists.txt b/cmake/bus/CMakeLists.txt
+index 2657605..13fb34c 100644
+--- a/cmake/bus/CMakeLists.txt
++++ b/cmake/bus/CMakeLists.txt
+@@ -72,7 +72,9 @@ set (BUS_SOURCES
+ ${BUS_DIR}/test.c
+ ${BUS_DIR}/test.h
+ ${BUS_DIR}/utils.c
+- ${BUS_DIR}/utils.h
++ ${BUS_DIR}/utils.h
++ ${BUS_DIR}/smack.c
++ ${BUS_DIR}/smack.h
+ ${XML_SOURCES}
+ ${DIR_WATCH_SOURCE}
+ )
+diff --git a/configure.ac b/configure.ac
+index a963d4d..95216c5 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -207,6 +207,9 @@ if test "x$enable_embedded_tests" = xyes; then
+ [Define to build test code into the library and binaries])
+ fi
+
++# call early to ensure availability
++PKG_PROG_PKG_CONFIG
++
+ # DBUS_ENABLE_MODULAR_TESTS controls tests that work based on public API.
+ # These use GTest, from GLib, because life's too short. They're enabled by
+ # default (unless you don't have GLib), because they don't bloat the library
+@@ -907,8 +910,6 @@ fi
+ # unix:path=/foo or unix:abstract=/foo
+ AC_SUBST(DBUS_PATH_OR_ABSTRACT)
+
+-PKG_PROG_PKG_CONFIG
+-
+ #### Sort out XML library
+
+ # see what we have
+@@ -1703,6 +1704,17 @@ if test "x$enable_stats" = xyes; then
+ [Define to enable bus daemon usage statistics])
+ fi
+
++#enable smack label support
++AC_ARG_ENABLE([smack], [AS_HELP_STRING([--enable-smack], [enable SMACK security checks])], [], [enable_smack=no])
++if test "x$enable_smack" = xyes; then
++ PKG_CHECK_MODULES([LIBSMACK], [libsmack >= 1.0],
++ [AC_DEFINE([DBUS_ENABLE_SMACK], [1], [Define to enable SMACK security features])],
++ [AC_MSG_ERROR([libsmack is required to enable smack support])])
++fi
++
++AC_SUBST([LIBSMACK_CFLAGS])
++AC_SUBST([LIBSMACK_LIBS])
++
+ AC_CONFIG_FILES([
+ Doxyfile
+ dbus/versioninfo.rc
+@@ -1781,6 +1793,7 @@ echo "
+ Building checks: ${enable_checks}
+ Building bus stats API: ${enable_stats}
+ Building SELinux support: ${have_selinux}
++ Building SMACK support: ${enable_smack}
+ Building inotify support: ${have_inotify}
+ Building dnotify support: ${have_dnotify}
+ Building kqueue support: ${have_kqueue}
--- /dev/null
+From: Brian McGillion <brian.mcgillion@intel.com>
+Date: Mon, 6 Feb 2012 18:48:30 +0200
+Subject: Enforce smack policy from conf file
+
+---
+ bus/config-parser.c | 38 ++++++++++----
+ bus/policy.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++---
+ bus/policy.h | 3 ++
+ bus/smack.c | 111 +++++++++++++++++++++++++++++++++++++++++
+ bus/smack.h | 4 ++
+ 5 files changed, 278 insertions(+), 19 deletions(-)
+
+diff --git a/bus/config-parser.c b/bus/config-parser.c
+index 07e8fbb..d7ba549 100644
+--- a/bus/config-parser.c
++++ b/bus/config-parser.c
+@@ -43,6 +43,7 @@ typedef enum
+ POLICY_MANDATORY,
+ POLICY_USER,
+ POLICY_GROUP,
++ POLICY_SMACK,
+ POLICY_CONSOLE
+ } PolicyType;
+
+@@ -64,7 +65,11 @@ typedef struct
+ struct
+ {
+ PolicyType type;
+- unsigned long gid_uid_or_at_console;
++ union
++ {
++ unsigned long gid_uid_or_at_console;
++ char *smack_label;
++ };
+ } policy;
+
+ struct
+@@ -150,6 +155,8 @@ element_free (Element *e)
+ {
+ if (e->type == ELEMENT_LIMIT)
+ dbus_free (e->d.limit.name);
++ else if (e->type == ELEMENT_POLICY && e->d.policy.type == POLICY_SMACK)
++ dbus_free (e->d.policy.smack_label);
+
+ dbus_free (e);
+ }
+@@ -972,6 +979,7 @@ start_busconfig_child (BusConfigParser *parser,
+ const char *user;
+ const char *group;
+ const char *at_console;
++ const char *smack;
+
+ if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
+ {
+@@ -988,20 +996,16 @@ start_busconfig_child (BusConfigParser *parser,
+ "context", &context,
+ "user", &user,
+ "group", &group,
++ "smack", &smack,
+ "at_console", &at_console,
+ NULL))
+ return FALSE;
+
+- if (((context && user) ||
+- (context && group) ||
+- (context && at_console)) ||
+- ((user && group) ||
+- (user && at_console)) ||
+- (group && at_console) ||
+- !(context || user || group || at_console))
++ if (((context != NULL) + (user != NULL) + (group != NULL) +
++ (smack != NULL) + (at_console != NULL)) != 1)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+- "<policy> element must have exactly one of (context|user|group|at_console) attributes");
++ "<policy> element must have exactly one of (context|user|group|smack|at_console) attributes");
+ return FALSE;
+ }
+
+@@ -1047,6 +1051,16 @@ start_busconfig_child (BusConfigParser *parser,
+ _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
+ group);
+ }
++ else if (smack != NULL)
++ {
++ e->d.policy.type = POLICY_SMACK;
++ e->d.policy.smack_label = _dbus_strdup (smack);
++ if (e->d.policy.smack_label == NULL)
++ {
++ BUS_SET_OOM (error);
++ return FALSE;
++ }
++ }
+ else if (at_console != NULL)
+ {
+ dbus_bool_t t;
+@@ -1631,8 +1645,10 @@ append_rule_from_element (BusConfigParser *parser,
+ rule))
+ goto nomem;
+ break;
+-
+-
++ case POLICY_SMACK:
++ if (!bus_policy_append_smack_rule (parser->policy, pe->d.policy.smack_label, rule))
++ goto nomem;
++ break;
+ case POLICY_CONSOLE:
+ if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
+ rule))
+diff --git a/bus/policy.c b/bus/policy.c
+index 379cea9..836354a 100644
+--- a/bus/policy.c
++++ b/bus/policy.c
+@@ -26,6 +26,7 @@
+ #include "services.h"
+ #include "test.h"
+ #include "utils.h"
++#include "smack.h"
+ #include <dbus/dbus-list.h>
+ #include <dbus/dbus-hash.h>
+ #include <dbus/dbus-internals.h>
+@@ -126,12 +127,13 @@ struct BusPolicy
+ {
+ int refcount;
+
+- DBusList *default_rules; /**< Default policy rules */
+- DBusList *mandatory_rules; /**< Mandatory policy rules */
+- DBusHashTable *rules_by_uid; /**< per-UID policy rules */
+- DBusHashTable *rules_by_gid; /**< per-GID policy rules */
+- DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
+- DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
++ DBusList *default_rules; /**< Default policy rules */
++ DBusList *mandatory_rules; /**< Mandatory policy rules */
++ DBusHashTable *rules_by_uid; /**< per-UID policy rules */
++ DBusHashTable *rules_by_gid; /**< per-GID policy rules */
++ DBusHashTable *rules_by_smack_label; /**< per-SMACK label policy rules */
++ DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
++ DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
+ };
+
+ static void
+@@ -181,6 +183,14 @@ bus_policy_new (void)
+ if (policy->rules_by_gid == NULL)
+ goto failed;
+
++#ifdef DBUS_ENABLE_SMACK
++ policy->rules_by_smack_label = _dbus_hash_table_new (DBUS_HASH_STRING,
++ (DBusFreeFunction) dbus_free,
++ free_rule_list_func);
++ if (policy->rules_by_smack_label == NULL)
++ goto failed;
++#endif
++
+ return policy;
+
+ failed:
+@@ -230,7 +240,13 @@ bus_policy_unref (BusPolicy *policy)
+ _dbus_hash_table_unref (policy->rules_by_gid);
+ policy->rules_by_gid = NULL;
+ }
+-
++
++ if (policy->rules_by_smack_label)
++ {
++ _dbus_hash_table_unref (policy->rules_by_smack_label);
++ policy->rules_by_smack_label = NULL;
++ }
++
+ dbus_free (policy);
+ }
+ }
+@@ -356,6 +372,24 @@ bus_policy_create_client_policy (BusPolicy *policy,
+ }
+ }
+
++ if (policy->rules_by_smack_label &&
++ _dbus_hash_table_get_n_entries (policy->rules_by_smack_label) > 0)
++ {
++ DBusList **list;
++ dbus_bool_t nomem_err = FALSE;
++
++ list = bus_smack_generate_allowed_list(connection, policy->rules_by_smack_label, &nomem_err);
++
++ if (list != NULL)
++ {
++ nomem_err = !add_list_to_client (list, client);
++ _dbus_list_clear (list);
++ }
++
++ if (nomem_err)
++ goto nomem;
++ }
++
+ if (!add_list_to_client (&policy->mandatory_rules,
+ client))
+ goto nomem;
+@@ -576,6 +610,66 @@ bus_policy_append_group_rule (BusPolicy *policy,
+ return TRUE;
+ }
+
++#ifdef DBUS_ENABLE_SMACK
++static DBusList **
++get_list_string (DBusHashTable *table,
++ const char *key)
++{
++ DBusList **list;
++
++ if (key == NULL)
++ return NULL;
++
++ list = _dbus_hash_table_lookup_string (table, key);
++
++ if (list == NULL)
++ {
++ char *new_key;
++
++ list = dbus_new0 (DBusList*, 1);
++ if (list == NULL)
++ return NULL;
++
++ new_key = _dbus_strdup (key);
++ if (new_key == NULL)
++ {
++ dbus_free (list);
++ return NULL;
++ }
++
++ if (!_dbus_hash_table_insert_string (table, new_key, list))
++ {
++ dbus_free (list);
++ dbus_free (new_key);
++ return NULL;
++ }
++ }
++
++ return list;
++}
++#endif
++
++dbus_bool_t
++bus_policy_append_smack_rule (BusPolicy *policy,
++ const char *label,
++ BusPolicyRule *rule)
++{
++#ifdef DBUS_ENABLE_SMACK
++ DBusList **list;
++
++ list = get_list_string (policy->rules_by_smack_label, label);
++ if (list == NULL)
++ return FALSE;
++
++ if (!_dbus_list_append (list, rule))
++ return FALSE;
++
++ bus_policy_rule_ref (rule);
++#endif
++
++ return TRUE;
++}
++
+ dbus_bool_t
+ bus_policy_append_console_rule (BusPolicy *policy,
+ dbus_bool_t at_console,
+@@ -653,6 +747,31 @@ merge_id_hash (DBusHashTable *dest,
+ return TRUE;
+ }
+
++#ifdef DBUS_ENABLE_SMACK
++static dbus_bool_t
++merge_string_hash (DBusHashTable *dest,
++ DBusHashTable *to_absorb)
++{
++ DBusHashIter iter;
++
++ _dbus_hash_iter_init (to_absorb, &iter);
++ while (_dbus_hash_iter_next (&iter))
++ {
++ const char *absorb_label = _dbus_hash_iter_get_string_key(&iter);
++ DBusList **list = _dbus_hash_iter_get_value (&iter);
++ DBusList **target = get_list_string (dest, absorb_label);
++
++ if (target == NULL)
++ return FALSE;
++
++ if (!append_copy_of_policy_list (target, list))
++ return FALSE;
++ }
++
++ return TRUE;
++}
++#endif
++
+ dbus_bool_t
+ bus_policy_merge (BusPolicy *policy,
+ BusPolicy *to_absorb)
+@@ -685,6 +804,12 @@ bus_policy_merge (BusPolicy *policy,
+ to_absorb->rules_by_gid))
+ return FALSE;
+
++#ifdef DBUS_ENABLE_SMACK
++ if (!merge_string_hash (policy->rules_by_smack_label,
++ to_absorb->rules_by_smack_label))
++ return FALSE;
++#endif
++
+ return TRUE;
+ }
+
+@@ -873,7 +998,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
+ {
+ DBusList *link;
+ dbus_bool_t allowed;
+-
++
+ /* policy->rules is in the order the rules appeared
+ * in the config file, i.e. last rule that applies wins
+ */
+diff --git a/bus/policy.h b/bus/policy.h
+index 3ff6f48..20d0a39 100644
+--- a/bus/policy.h
++++ b/bus/policy.h
+@@ -130,6 +130,9 @@ dbus_bool_t bus_policy_append_user_rule (BusPolicy *policy,
+ dbus_bool_t bus_policy_append_group_rule (BusPolicy *policy,
+ dbus_gid_t gid,
+ BusPolicyRule *rule);
++dbus_bool_t bus_policy_append_smack_rule (BusPolicy *policy,
++ const char *label,
++ BusPolicyRule *rule);
+ dbus_bool_t bus_policy_append_console_rule (BusPolicy *policy,
+ dbus_bool_t at_console,
+ BusPolicyRule *rule);
+diff --git a/bus/smack.c b/bus/smack.c
+index b8542c2..d4546a3 100644
+--- a/bus/smack.c
++++ b/bus/smack.c
+@@ -29,11 +29,17 @@
+ #include "connection.h"
+ #include "services.h"
+ #include "utils.h"
++#include "policy.h"
+
+ #ifdef DBUS_ENABLE_SMACK
+ #include <sys/smack.h>
+ #endif
+
++#define SMACK_WRITE "W"
++#define SMACK_READ "R"
++#define SMACK_READ_WRITE "RW"
++
++
+ #ifdef DBUS_ENABLE_SMACK
+ static char *
+ bus_smack_get_label (DBusConnection *connection)
+@@ -130,3 +136,108 @@ err:
+ return FALSE;
+ #endif
+ }
++
++#ifdef DBUS_ENABLE_SMACK
++static dbus_bool_t
++bus_smack_has_access (const char *subject, const char *object,
++ const char *access)
++{
++ return (smack_have_access (subject, object, access) == 1 ? TRUE : FALSE);
++}
++#endif
++
++
++/**
++ * Calculate the list of rules that apply to a connection.
++ *
++ * @param connection The inbound conenction
++ * @param rules_by_smack_label The table of object labels -> rules mapping
++ * @param nomem_err (out) If a nomem situation is encountered this value is set to TRUE.
++ * @returns the list of permitted rules if it exists and no errors were encountered otherwise NULL.
++ */
++DBusList**
++bus_smack_generate_allowed_list (DBusConnection *connection,
++ DBusHashTable *rules_by_smack_label,
++ dbus_bool_t *nomem_err)
++{
++#ifdef DBUS_ENABLE_SMACK
++ char *subject_label;
++ DBusHashIter iter;
++ dbus_bool_t is_allowed;
++ DBusList **allowed_list;
++
++ /* the label of the subject, is the label on the new connection,
++ either the service itself or one of its clients */
++ subject_label = bus_smack_get_label (connection);
++ if (subject_label == NULL)
++ return NULL;
++
++ allowed_list = dbus_new0 (DBusList*, 1);
++ if (allowed_list == NULL)
++ goto nomem;
++
++ /* Iterate over all the smack labels we have parsed from the .conf files */
++ _dbus_hash_iter_init (rules_by_smack_label, &iter);
++ while (_dbus_hash_iter_next (&iter))
++ {
++ DBusList *link;
++ const char *object_label = _dbus_hash_iter_get_string_key (&iter);
++ /* the list here is all the rules that are 'protected'
++ by the SMACK label named $object_label */
++ DBusList **list = _dbus_hash_iter_get_value (&iter);
++
++ link = _dbus_list_get_first_link (list);
++ while (link != NULL)
++ {
++ BusPolicyRule *rule = link->data;
++ link = _dbus_list_get_next_link (list, link);
++ is_allowed = FALSE;
++
++ switch (rule->type)
++ {
++ case BUS_POLICY_RULE_OWN:
++ is_allowed = bus_smack_has_access (subject_label,
++ object_label,
++ SMACK_READ_WRITE);
++ break;
++ case BUS_POLICY_RULE_SEND:
++ is_allowed = bus_smack_has_access (subject_label,
++ object_label,
++ SMACK_WRITE);
++ break;
++ case BUS_POLICY_RULE_RECEIVE:
++ is_allowed = bus_smack_has_access (subject_label,
++ object_label,
++ SMACK_READ);
++ break;
++ default:
++ continue;
++ }
++
++ if (is_allowed)
++ {
++ if (!_dbus_list_append (allowed_list, rule))
++ goto nomem;
++
++ bus_policy_rule_ref (rule);
++ }
++
++ _dbus_verbose ("permission request subject (%s) -> object (%s) : %s", subject_label, object_label, (is_allowed ? "GRANTED" : "REJECTED"));
++ }
++ }
++
++ dbus_free(subject_label);
++ return allowed_list;
++
++nomem:
++ if (allowed_list != NULL)
++ _dbus_list_clear (allowed_list);
++
++ dbus_free(subject_label);
++ *nomem_err = TRUE;
++ return NULL;
++
++#else
++ return NULL;
++#endif
++}
+diff --git a/bus/smack.h b/bus/smack.h
+index 04a4a2a..6b1dfad 100644
+--- a/bus/smack.h
++++ b/bus/smack.h
+@@ -27,10 +27,14 @@
+ #define SMACK_H
+
+ #include "bus.h"
++#include <dbus/dbus-hash.h>
+
+ dbus_bool_t bus_smack_handle_get_connection_context (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+
++DBusList **bus_smack_generate_allowed_list (DBusConnection *connection,
++ DBusHashTable *label_rules,
++ dbus_bool_t *error);
+ #endif // SMACK_H