Add unix:dir=/something addresses
authorSimon McVittie <smcv@collabora.com>
Tue, 20 Jun 2017 13:37:04 +0000 (14:37 +0100)
committerSimon McVittie <smcv@collabora.com>
Thu, 29 Jun 2017 13:03:03 +0000 (14:03 +0100)
These are like unix:tmpdir=/something, except that the resulting
socket is always path-based, never abstract.

This is desirable for two reasons:

* If a Linux container manager wants to expose a path-based socket
  into the container, it can do so by bind-mounting it in the
  container's filesystem namespace. That cannot work for abstract
  sockets because they are not files.

* Conversely, if a Linux container manager does not want to expose
  a path-based socket in the container, it can avoid bind-mounting it,
  or bind-mount some harmless object like /dev/null over it.
  That cannot work for abstract sockets because access to abstract
  sockets is part of the network namespace, which is all-or-nothing.

Signed-off-by: Simon McVittie <smcv@collabora.com>
Reviewed-by: Philip Withnall <withnall@endlessm.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=101567

dbus/dbus-server-unix.c
doc/dbus-specification.xml

index 92664a8..fd9348a 100644 (file)
@@ -64,18 +64,19 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
   if (strcmp (method, "unix") == 0)
     {
       const char *path = dbus_address_entry_get_value (entry, "path");
+      const char *dir = dbus_address_entry_get_value (entry, "dir");
       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;
 
       mutually_exclusive_modes = (path != NULL) + (tmpdir != NULL) +
-        (abstract != NULL) + (runtime != NULL);
+        (abstract != NULL) + (runtime != NULL) + (dir != NULL);
 
       if (mutually_exclusive_modes < 1)
         {
           _dbus_set_bad_address(error, "unix",
-                                "path or tmpdir or abstract or runtime",
+                                "path or tmpdir or abstract or runtime or dir",
                                 NULL);
           return DBUS_SERVER_LISTEN_BAD_ADDRESS;
         }
@@ -83,7 +84,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
       if (mutually_exclusive_modes > 1)
         {
           _dbus_set_bad_address(error, NULL, NULL,
-                                "cannot specify two of \"path\", \"tmpdir\", \"abstract\" and \"runtime\" at the same time");
+                                "cannot specify two of \"path\", \"tmpdir\", \"abstract\", \"runtime\" and \"dir\" at the same time");
           return DBUS_SERVER_LISTEN_BAD_ADDRESS;
         }
 
@@ -134,10 +135,23 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
 
           _dbus_string_free (&full_path);
         }
-      else if (tmpdir != NULL)
+      else if (tmpdir != NULL || dir != NULL)
         {
           DBusString full_path;
           DBusString filename;
+          dbus_bool_t use_abstract = FALSE;
+
+          if (tmpdir != NULL)
+            {
+              dir = tmpdir;
+
+#ifdef HAVE_ABSTRACT_SOCKETS
+              /* Use abstract sockets for tmpdir if supported, so that it
+               * never needs to be cleaned up. Use dir instead if you want a
+               * path-based socket. */
+              use_abstract = TRUE;
+#endif
+            }
 
           if (!_dbus_string_init (&full_path))
             {
@@ -167,7 +181,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
               return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
             }
 
-          if (!_dbus_string_append (&full_path, tmpdir) ||
+          if (!_dbus_string_append (&full_path, dir) ||
               !_dbus_concat_dir_and_file (&full_path, &filename))
             {
               _dbus_string_free (&full_path);
@@ -176,15 +190,9 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
               return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
             }
 
-          /* Always use abstract namespace if possible with tmpdir */
-
           *server_p =
             _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
-#ifdef HAVE_ABSTRACT_SOCKETS
-                                                TRUE,
-#else
-                                                FALSE,
-#endif
+                                                use_abstract,
                                                 error);
 
           _dbus_string_free (&full_path);
index 7013e8b..5145581 100644 (file)
       <para>
         Unix addresses that specify <literal>path</literal> or
         <literal>abstract</literal> are both listenable and connectable.
-        Unix addresses that specify <literal>tmpdir</literal> are only
+        Unix addresses that specify <literal>tmpdir</literal>
+        or <literal>dir</literal> are only
         listenable: the corresponding connectable address will specify
         either <literal>path</literal> or <literal>abstract</literal>.
         Similarly, Unix addresses that specify <literal>runtime</literal>
            <row>
             <entry>path</entry>
             <entry>(path)</entry>
-            <entry>path of the unix domain socket. If set, the "tmpdir" and "abstract" key must not be set.</entry>
+            <entry>
+              Path of the unix domain socket.
+            </entry>
+          </row>
+          <row>
+            <entry>dir</entry>
+            <entry>(path)</entry>
+            <entry>
+              Directory in which a socket file with a random file name
+              starting with 'dbus-' will be created by the server. This key
+              can only be used in server addresses, not in client addresses;
+              the resulting client address will have the "path" key instead.
+              be set.
+            </entry>
           </row>
           <row>
             <entry>tmpdir</entry>
             <entry>(path)</entry>
-            <entry>temporary directory in which a socket file with a random file name starting with 'dbus-' will be created by the server. This key can only be used in server addresses, not in client addresses. If set, the "path" and "abstract" key must not be set.</entry>
+            <entry>
+              The same as "dir", except that on platforms with
+              abstract sockets, the server may attempt to create an
+              abstract socket whose name starts with this directory instead
+              of a path-based socket. This key can only be used in server
+              addresses, not in client addresses; the resulting client address
+              will have the "abstract" or "path" key instead.
+            </entry>
           </row>
           <row>
             <entry>abstract</entry>
             <entry>(string)</entry>
-            <entry>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.</entry>
+            <entry>
+              Unique string in the abstract namespace, often syntactically
+              resembling a path but unconnected to the filesystem namespace.
+              This key is only supported on platforms with abstract Unix
+              sockets, of which Linux is the only known example.
+            </entry>
           </row>
           <row>
             <entry>runtime</entry>
        </informaltable>
        <para>
          Exactly one of the keys <literal>path</literal>,
-         <literal>abstract</literal>, <literal>runtime</literal> or
-         <literal>tmpdir</literal> must be provided.
+         <literal>abstract</literal>, <literal>runtime</literal>,
+         <literal>dir</literal> or <literal>tmpdir</literal> must be provided.
        </para>
       </sect3>
     </sect2>