summaryrefslogtreecommitdiff
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-server-unix.c9
-rw-r--r--dbus/dbus-server-unix.h1
-rw-r--r--dbus/dbus-server.c32
-rw-r--r--dbus/dbus-sysdeps.c91
-rw-r--r--dbus/dbus-sysdeps.h2
-rw-r--r--dbus/dbus-transport-unix.c14
-rw-r--r--dbus/dbus-transport-unix.h1
-rw-r--r--dbus/dbus-transport.c20
8 files changed, 126 insertions, 44 deletions
diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c
index fe4dbaa4..036446af 100644
--- a/dbus/dbus-server-unix.c
+++ b/dbus/dbus-server-unix.c
@@ -268,11 +268,13 @@ _dbus_server_new_for_fd (int fd,
* Creates a new server listening on the given Unix domain socket.
*
* @param path the path for the domain socket.
+ * @param abstract #TRUE to use abstract socket namespace
* @param error location to store reason for failure.
* @returns the new server, or #NULL on failure.
*/
DBusServer*
_dbus_server_new_for_domain_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error)
{
DBusServer *server;
@@ -289,7 +291,10 @@ _dbus_server_new_for_domain_socket (const char *path,
return NULL;
}
- if (!_dbus_string_append (&address, "unix:path=") ||
+ if ((abstract &&
+ !_dbus_string_append (&address, "unix:abstract=")) ||
+ (!abstract &&
+ !_dbus_string_append (&address, "unix:path=")) ||
!_dbus_string_append (&address, path))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
@@ -303,7 +308,7 @@ _dbus_server_new_for_domain_socket (const char *path,
goto failed_0;
}
- listen_fd = _dbus_listen_unix_socket (path, error);
+ listen_fd = _dbus_listen_unix_socket (path, abstract, error);
_dbus_fd_set_close_on_exec (listen_fd);
if (listen_fd < 0)
diff --git a/dbus/dbus-server-unix.h b/dbus/dbus-server-unix.h
index 1d038db0..95f0b756 100644
--- a/dbus/dbus-server-unix.h
+++ b/dbus/dbus-server-unix.h
@@ -31,6 +31,7 @@ DBUS_BEGIN_DECLS;
DBusServer* _dbus_server_new_for_fd (int fd,
const DBusString *address);
DBusServer* _dbus_server_new_for_domain_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error);
DBusServer* _dbus_server_new_for_tcp_socket (const char *host,
dbus_uint32_t port,
diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c
index e62c0284..4007d7a5 100644
--- a/dbus/dbus-server.c
+++ b/dbus/dbus-server.c
@@ -295,17 +295,20 @@ dbus_server_listen (const char *address,
{
const char *path = dbus_address_entry_get_value (entries[i], "path");
const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
+ const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
- if (path == NULL && tmpdir == NULL)
+ if (path == NULL && tmpdir == NULL && abstract == NULL)
{
address_problem_type = "unix";
- address_problem_field = "path or tmpdir";
+ address_problem_field = "path or tmpdir or abstract";
goto bad_address;
}
- if (path && tmpdir)
+ if ((path && tmpdir) ||
+ (path && abstract) ||
+ (tmpdir && abstract))
{
- address_problem_other = "cannot specify both \"path\" and \"tmpdir\" at the same time";
+ address_problem_other = "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time";
goto bad_address;
}
@@ -339,14 +342,22 @@ dbus_server_listen (const char *address,
goto out;
}
- /* FIXME - we will unconditionally unlink() the path.
- * unlink() does not follow symlinks, but would like
- * independent confirmation this is safe enough. See
- * also _dbus_listen_unix_socket() and comments therein.
+ /* FIXME - we will unconditionally unlink() the path if
+ * we don't support abstract namespace. unlink() does
+ * not follow symlinks, but would like independent
+ * confirmation this is safe enough. See also
+ * _dbus_listen_unix_socket() and comments therein.
*/
+
+ /* Always use abstract namespace if possible with tmpdir */
server =
_dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path),
+#ifdef HAVE_ABSTRACT_SOCKETS
+ TRUE,
+#else
+ FALSE,
+#endif
error);
_dbus_string_free (&full_path);
@@ -354,7 +365,10 @@ dbus_server_listen (const char *address,
}
else
{
- server = _dbus_server_new_for_domain_socket (path, error);
+ if (path)
+ server = _dbus_server_new_for_domain_socket (path, FALSE, error);
+ else
+ server = _dbus_server_new_for_domain_socket (abstract, TRUE, error);
}
}
else if (strcmp (method, "tcp") == 0)
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index ab79a722..35900d70 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -373,13 +373,19 @@ _dbus_write_two (int fd,
* Creates a socket and connects it to the UNIX domain socket at the
* given path. The connection fd is returned, and is set up as
* nonblocking.
+ *
+ * Uses abstract sockets instead of filesystem-linked sockets if
+ * requested (it's possible only on Linux; see "man 7 unix" on Linux).
+ * On non-Linux abstract socket usage always fails.
*
* @param path the path to UNIX domain socket
+ * @param abstract #TRUE to use abstract namespace
* @param error return location for error code
* @returns connection file descriptor or -1 on error
*/
int
_dbus_connect_unix_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error)
{
int fd;
@@ -401,7 +407,23 @@ _dbus_connect_unix_socket (const char *path,
_DBUS_ZERO (addr);
addr.sun_family = AF_UNIX;
- strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
+
+ if (abstract)
+ {
+#ifdef HAVE_ABSTRACT_SOCKETS
+ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+ strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
+#else /* HAVE_ABSTRACT_SOCKETS */
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+ "Operating system does not support abstract socket namespace\n");
+ close (fd);
+ return -1;
+#endif /* ! HAVE_ABSTRACT_SOCKETS */
+ }
+ else
+ {
+ strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
+ }
if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
{
@@ -434,18 +456,19 @@ _dbus_connect_unix_socket (const char *path,
* then listens on the socket. The socket is
* set to be nonblocking.
*
- * @todo we'd like to be able to use the abstract namespace on linux
- * (see "man 7 unix"). The question is whether to silently move all
- * paths into that namespace if we can (I think that's best) or to
- * require it to be specified explicitly in the dbus address. Also,
- * need to sort out how to check for abstract namespace support.
+ * Uses abstract sockets instead of filesystem-linked
+ * sockets if requested (it's possible only on Linux;
+ * see "man 7 unix" on Linux).
+ * On non-Linux abstract socket usage always fails.
*
* @param path the socket name
+ * @param abstract #TRUE to use abstract namespace
* @param error return location for errors
* @returns the listening file descriptor or -1 on error
*/
int
_dbus_listen_unix_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error)
{
int listen_fd;
@@ -463,27 +486,43 @@ _dbus_listen_unix_socket (const char *path,
return -1;
}
- /* FIXME discussed security implications of this with Nalin,
- * and we couldn't think of where it would kick our ass, but
- * it still seems a bit sucky. It also has non-security suckage;
- * really we'd prefer to exit if the socket is already in use.
- * But there doesn't seem to be a good way to do this.
- *
- * Just to be extra careful, I threw in the stat() - clearly
- * the stat() can't *fix* any security issue, but it at least
- * avoids inadvertent/accidental data loss.
- */
- {
- struct stat sb;
-
- if (stat (path, &sb) == 0 &&
- S_ISSOCK (sb.st_mode))
- unlink (path);
- }
-
_DBUS_ZERO (addr);
addr.sun_family = AF_UNIX;
- strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
+
+ if (abstract)
+ {
+#ifdef HAVE_ABSTRACT_SOCKETS
+ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
+ strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
+#else /* HAVE_ABSTRACT_SOCKETS */
+ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
+ "Operating system does not support abstract socket namespace\n");
+ close (listen_fd);
+ return -1;
+#endif /* ! HAVE_ABSTRACT_SOCKETS */
+ }
+ else
+ {
+ /* FIXME discussed security implications of this with Nalin,
+ * and we couldn't think of where it would kick our ass, but
+ * it still seems a bit sucky. It also has non-security suckage;
+ * really we'd prefer to exit if the socket is already in use.
+ * But there doesn't seem to be a good way to do this.
+ *
+ * Just to be extra careful, I threw in the stat() - clearly
+ * the stat() can't *fix* any security issue, but it at least
+ * avoids inadvertent/accidental data loss.
+ */
+ {
+ struct stat sb;
+
+ if (stat (path, &sb) == 0 &&
+ S_ISSOCK (sb.st_mode))
+ unlink (path);
+ }
+
+ strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
+ }
if (bind (listen_fd, (struct sockaddr*) &addr, SUN_LEN (&addr)) < 0)
{
@@ -513,7 +552,7 @@ _dbus_listen_unix_socket (const char *path,
/* Try opening up the permissions, but if we can't, just go ahead
* and continue, maybe it will be good enough.
*/
- if (chmod (path, 0777) < 0)
+ if (!abstract && chmod (path, 0777) < 0)
_dbus_warn ("Could not set mode 0777 on socket %s\n",
path);
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 7a4696f3..cfe0cd25 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -105,8 +105,10 @@ typedef struct
} DBusCredentials;
int _dbus_connect_unix_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error);
int _dbus_listen_unix_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error);
int _dbus_connect_tcp_socket (const char *host,
dbus_uint32_t port,
diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c
index 5df1c461..e5e446c2 100644
--- a/dbus/dbus-transport-unix.c
+++ b/dbus/dbus-transport-unix.c
@@ -1080,12 +1080,17 @@ _dbus_transport_new_for_fd (int fd,
* Creates a new transport for the given Unix domain socket
* path. This creates a client-side of a transport.
*
+ * @todo once we add a way to escape paths in a dbus
+ * address, this function needs to do escaping.
+ *
* @param path the path to the domain socket.
+ * @param abstract #TRUE to use abstract socket namespace
* @param error address where an error can be returned.
* @returns a new transport, or #NULL on failure.
*/
DBusTransport*
_dbus_transport_new_for_domain_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error)
{
int fd;
@@ -1101,15 +1106,18 @@ _dbus_transport_new_for_domain_socket (const char *path,
}
fd = -1;
-
- if (!_dbus_string_append (&address, "unix:path=") ||
+
+ if ((abstract &&
+ !_dbus_string_append (&address, "unix:abstract=")) ||
+ (!abstract &&
+ !_dbus_string_append (&address, "unix:path=")) ||
!_dbus_string_append (&address, path))
{
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto failed_0;
}
- fd = _dbus_connect_unix_socket (path, error);
+ fd = _dbus_connect_unix_socket (path, abstract, error);
if (fd < 0)
{
_DBUS_ASSERT_ERROR_IS_SET (error);
diff --git a/dbus/dbus-transport-unix.h b/dbus/dbus-transport-unix.h
index ef7ac9b1..8d3f5b10 100644
--- a/dbus/dbus-transport-unix.h
+++ b/dbus/dbus-transport-unix.h
@@ -31,6 +31,7 @@ DBusTransport* _dbus_transport_new_for_fd (int fd,
dbus_bool_t server,
const DBusString *address);
DBusTransport* _dbus_transport_new_for_domain_socket (const char *path,
+ dbus_bool_t abstract,
DBusError *error);
DBusTransport* _dbus_transport_new_for_tcp_socket (const char *host,
dbus_int32_t port,
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index af1cb421..59ec6ea1 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -243,21 +243,33 @@ _dbus_transport_open (const char *address,
{
const char *path = dbus_address_entry_get_value (entries[i], "path");
const char *tmpdir = dbus_address_entry_get_value (entries[i], "tmpdir");
-
+ const char *abstract = dbus_address_entry_get_value (entries[i], "abstract");
+
if (tmpdir != NULL)
{
address_problem_other = "cannot use the \"tmpdir\" option for an address to connect to, only in an address to listen on";
goto bad_address;
}
- if (path == NULL)
+ if (path == NULL && abstract == NULL)
{
address_problem_type = "unix";
- address_problem_field = "path";
+ address_problem_field = "path or abstract";
goto bad_address;
}
- transport = _dbus_transport_new_for_domain_socket (path, &tmp_error);
+ if (path != NULL && abstract != NULL)
+ {
+ address_problem_other = "can't specify both \"path\" and \"abstract\" options in an address";
+ goto bad_address;
+ }
+
+ if (path)
+ transport = _dbus_transport_new_for_domain_socket (path, FALSE,
+ &tmp_error);
+ else
+ transport = _dbus_transport_new_for_domain_socket (abstract, TRUE,
+ &tmp_error);
}
else if (strcmp (method, "tcp") == 0)
{