summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2013-08-20 20:42:10 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2013-09-06 15:49:02 +0100
commitf4076dffc10600006dd6415c3584f97bd36907a6 (patch)
tree7657b2f4113f4db0a5adfbc2939a082adbc8f5f1
parent21b395c356549d821b30253f6ec5be8dbd15e333 (diff)
downloadtelepathy-glib-f4076dffc10600006dd6415c3584f97bd36907a6.tar.gz
_tp_create_temp_unix_socket: avoid using tmpnam()
On current Debian unstable, gcc/ld issues a warning about tmpnam(), because it's usually used in an unsafe way. "gcc -Wl,--fatal-warnings" (which I'm using in my development environment) upgrades that to fatal. Our usage was in fact safe (trying to listen on a socket always behaves like O_EXCL|O_CREAT, which can DoS'd but is not subject to symlink attacks), but we're swimming against the current by trying to use tmpnam(). Instead, create a secure private temporary directory with g_dir_make_tmp(), and put our socket in there. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68350 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
-rw-r--r--telepathy-glib/stream-tube-channel.c10
-rw-r--r--telepathy-glib/util-internal.h1
-rw-r--r--telepathy-glib/util.c51
3 files changed, 44 insertions, 18 deletions
diff --git a/telepathy-glib/stream-tube-channel.c b/telepathy-glib/stream-tube-channel.c
index 607abad54..8a110d756 100644
--- a/telepathy-glib/stream-tube-channel.c
+++ b/telepathy-glib/stream-tube-channel.c
@@ -145,6 +145,7 @@ struct _TpStreamTubeChannelPrivate
/* Offering side */
GSocketService *service;
GSocketAddress *address;
+ gchar *unix_tmpdir;
/* GSocketConnection we have accepted but are still waiting a
* NewRemoteConnection to identify them. Owned ConnWaitingSig. */
GSList *conn_waiting_sig;
@@ -266,6 +267,13 @@ tp_stream_tube_channel_dispose (GObject *obj)
self->priv->address = NULL;
}
+ if (self->priv->unix_tmpdir != NULL)
+ {
+ g_rmdir (self->priv->unix_tmpdir);
+ g_free (self->priv->unix_tmpdir);
+ self->priv->unix_tmpdir = NULL;
+ }
+
tp_clear_pointer (&self->priv->access_control_param, tp_g_value_slice_free);
tp_clear_object (&self->priv->local_conn_waiting_id);
tp_clear_object (&self->priv->client_socket);
@@ -1466,7 +1474,7 @@ tp_stream_tube_channel_offer_async (TpStreamTubeChannel *self,
case TP_SOCKET_ADDRESS_TYPE_UNIX:
{
self->priv->address = _tp_create_temp_unix_socket (
- self->priv->service, &error);
+ self->priv->service, &self->priv->unix_tmpdir, &error);
/* check there wasn't an error on the final attempt */
if (self->priv->address == NULL)
diff --git a/telepathy-glib/util-internal.h b/telepathy-glib/util-internal.h
index 941064832..b1ecaa414 100644
--- a/telepathy-glib/util-internal.h
+++ b/telepathy-glib/util-internal.h
@@ -39,6 +39,7 @@ void _tp_quark_array_merge_valist (GArray *array,
#ifdef HAVE_GIO_UNIX
GSocketAddress * _tp_create_temp_unix_socket (GSocketService *service,
+ gchar **tmpdir,
GError **error);
#endif /* HAVE_GIO_UNIX */
diff --git a/telepathy-glib/util.c b/telepathy-glib/util.c
index 91a42d5a0..c89bc66d7 100644
--- a/telepathy-glib/util.c
+++ b/telepathy-glib/util.c
@@ -31,6 +31,7 @@
#include "config.h"
+#include <glib/gstdio.h>
#include <gobject/gvaluecollector.h>
#ifdef HAVE_GIO_UNIX
@@ -43,6 +44,7 @@
#include <telepathy-glib/util-internal.h>
#include <telepathy-glib/util.h>
+#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -1563,32 +1565,47 @@ _tp_quark_array_merge_valist (GArray *array,
#ifdef HAVE_GIO_UNIX
GSocketAddress *
_tp_create_temp_unix_socket (GSocketService *service,
+ gchar **tmpdir,
GError **error)
{
- guint i;
GSocketAddress *address;
+ gchar *dir = g_dir_make_tmp ("tp-glib-socket.XXXXXX", error);
+ gchar *name;
+
+ if (dir == NULL)
+ return NULL;
- /* why doesn't GIO provide a method to create a socket we don't
- * care about? Iterate until we find a valid temporary name.
- *
- * Try a maximum of 10 times to get a socket */
- for (i = 0; i < 10; i++)
+ if (g_chmod (dir, 0700) != 0)
{
- address = g_unix_socket_address_new (tmpnam (NULL));
+ int e = errno;
- g_clear_error (error);
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (e),
+ "unable to set permissions of %s to 0700: %s", dir,
+ g_strerror (e));
+ g_free (dir);
+ return NULL;
+ }
- if (g_socket_listener_add_address (
- G_SOCKET_LISTENER (service),
- address, G_SOCKET_TYPE_STREAM,
- G_SOCKET_PROTOCOL_DEFAULT,
- NULL, NULL, error))
- return address;
- else
- g_object_unref (address);
+ name = g_build_filename (dir, "s", NULL);
+ address = g_unix_socket_address_new (name);
+ g_free (name);
+
+ if (!g_socket_listener_add_address (G_SOCKET_LISTENER (service),
+ address, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_DEFAULT,
+ NULL, NULL, error))
+ {
+ g_object_unref (address);
+ g_free (dir);
+ return NULL;
}
- return NULL;
+ if (tmpdir != NULL)
+ *tmpdir = dir;
+ else
+ g_free (dir);
+
+ return address;
}
#endif /* HAVE_GIO_UNIX */