From a0be0380d5543bbd3952b454fe358bcd447b08ea Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 8 Jan 2015 14:48:59 +0000 Subject: [PATCH 2/7] Add support for unix:runtime=yes as an address mode This is not used by default, but can be configured by OS builders (or regression-test environments) if desired. If used, this listens on $XDG_RUNTIME_DIR/bus, or fails if $XDG_RUNTIME_DIR is not set. Fallback behaviour is unnecessary, because it is already possible to use a string of semicolon-separated addresses like unix:runtime=yes;unix:tmpdir=/tmp, resulting in listening on either $XDG_RUNTIME_DIR/bus or /tmp/something. We use a non-abstract socket here, because that is desirable for use with Linux containers: abstract sockets are attached to the network namespace, whereas non-abstract sockets are part of the filesystem and can be bind-mounted between domains if necessary. The major advantage of abstract sockets is that they do not need cleanup, but the specification of XDG_RUNTIME_DIR guarantees to provide cleanup anyway. Based on prior work by Simon McVittie, Colin Walters and Alexander Larsson. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=61303 --- dbus/dbus-server-unix.c | 59 ++++++++++++++++++++++++++++++++++++++++------ doc/dbus-specification.xml | 7 +++++- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index d995240..3669872 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -66,25 +66,70 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry, const char *path = dbus_address_entry_get_value (entry, "path"); const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); const char *abstract = dbus_address_entry_get_value (entry, "abstract"); + const char *runtime = dbus_address_entry_get_value (entry, "runtime"); + int mutually_exclusive_modes = 0; - if (path == NULL && tmpdir == NULL && abstract == NULL) + mutually_exclusive_modes = (path != NULL) + (tmpdir != NULL) + + (abstract != NULL) + (runtime != NULL); + + if (mutually_exclusive_modes < 1) { _dbus_set_bad_address(error, "unix", - "path or tmpdir or abstract", + "path or tmpdir or abstract or runtime", NULL); return DBUS_SERVER_LISTEN_BAD_ADDRESS; } - if ((path && tmpdir) || - (path && abstract) || - (tmpdir && abstract)) + if (mutually_exclusive_modes > 1) { _dbus_set_bad_address(error, NULL, NULL, - "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time"); + "cannot specify two of \"path\", \"tmpdir\", \"abstract\" and \"runtime\" at the same time"); return DBUS_SERVER_LISTEN_BAD_ADDRESS; } - if (tmpdir != NULL) + if (runtime != NULL) + { + DBusString full_path; + DBusString filename; + const char *runtimedir; + + if (strcmp (runtime, "yes") != 0) + { + _dbus_set_bad_address(error, NULL, NULL, + "if given, the only value allowed for \"runtime\" is \"yes\""); + return DBUS_SERVER_LISTEN_BAD_ADDRESS; + } + + runtimedir = _dbus_getenv ("XDG_RUNTIME_DIR"); + + if (runtimedir == NULL) + { + dbus_set_error (error, + DBUS_ERROR_NOT_SUPPORTED, "\"XDG_RUNTIME_DIR\" is not set"); + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } + + _dbus_string_init_const (&filename, "bus"); + + if (!_dbus_string_init (&full_path) || + !_dbus_string_append (&full_path, runtimedir) || + !_dbus_concat_dir_and_file (&full_path, &filename)) + { + _DBUS_SET_OOM (error); + return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; + } + + /* We can safely use filesystem sockets in the runtime directory, + * and they are preferred because they can be bind-mounted between + * Linux containers. */ + *server_p = _dbus_server_new_for_domain_socket ( + _dbus_string_get_const_data (&full_path), + FALSE, error); + + _dbus_string_free (&full_path); + _dbus_string_free (&filename); + } + else if (tmpdir != NULL) { DBusString full_path; DBusString filename; diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml index a9a8c59..f4dce10 100644 --- a/doc/dbus-specification.xml +++ b/doc/dbus-specification.xml @@ -3175,12 +3175,17 @@ (string) unique string (path) in the abstract namespace. If set, the "path" or "tmpdir" key must not be set. This key is only supported on platforms with "abstract Unix sockets", of which Linux is the only known example. + + runtime + yes + If given, This key can only be used in server addresses, not in client addresses. If set, its value must be yes. This is typically used in an address string like unix:runtime=yes;unix:tmpdir=/tmp so that there can be a fallback if XDG_RUNTIME_DIR is not set. + Exactly one of the keys path, - abstract or + abstract, runtime or tmpdir must be provided. -- 2.1.4