File gypsy-CVE-2011-0523.patch of Package gypsy
From aa071099802f3bf866cffbfb25196dcdf1fbba1e Mon Sep 17 00:00:00 2001
From: Michael Leibowitz <michael.leibowitz@intel.com>
Date: Wed, 16 Mar 2011 22:29:06 -0700
Subject: [PATCH] Add a config file that specifies a whitelist of allowed
devices
This is in response to Bug 33431 "CVE-2011-0523: arbitrary file access
and buffer overflows" A new config file, /etc/gypsy.conf, is added
that specifies a whitelist of globs. By default, they are
"/dev/tty*", "/dev/pgps", and "bluetooth" (which matches Bluetooth
addresses).
Signed-off-by: Michael Leibowitz <michael.leibowitz@intel.com>
Further changes by Bastien Nocera <hadess@hadess.net>
---
Makefile.am | 2 +-
configure.ac | 3 ++
etc/Makefile.am | 2 +
etc/gypsy.conf | 2 +
src/gypsy-server.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gypsy-server.h | 1 +
6 files changed, 78 insertions(+), 1 deletions(-)
create mode 100644 etc/Makefile.am
create mode 100644 etc/gypsy.conf
diff --git a/Makefile.am b/Makefile.am
index 8b4090e..174a2af 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = interfaces src gypsy examples docs
+SUBDIRS = interfaces src gypsy examples docs etc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gypsy.pc
diff --git a/configure.ac b/configure.ac
index 3484051..a441ceb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -43,6 +43,8 @@ DBUS_SYS_DIR="${sysconfdir}/dbus-1/system.d"
AC_SUBST(DBUS_SYS_DIR)
AC_DEFINE_UNQUOTED(DBUS_SYS_DIR, "$DBUS_SYS_DIR", [Where the system dir for D-Bus is])
+AC_DEFINE_UNQUOTED(CONFIG_FILE_PATH, "${sysconfdir}/gypsy.conf", [The absolute path of the config file])
+
DBUS_SERVICES_DIR="${datadir}/dbus-1/system-services"
AC_SUBST(DBUS_SERVICES_DIR)
AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for D-Bus is])
@@ -72,6 +74,7 @@ docs/Makefile
docs/reference/Makefile
docs/reference/version.xml
docs/tools/Makefile
+etc/Makefile
gypsy.pc
])
diff --git a/etc/Makefile.am b/etc/Makefile.am
new file mode 100644
index 0000000..77d58f4
--- /dev/null
+++ b/etc/Makefile.am
@@ -0,0 +1,2 @@
+configdir = $(sysconfdir)
+dist_config_DATA = gypsy.conf
diff --git a/etc/gypsy.conf b/etc/gypsy.conf
new file mode 100644
index 0000000..be76a35
--- /dev/null
+++ b/etc/gypsy.conf
@@ -0,0 +1,2 @@
+[gypsy]
+AllowedDeviceGlobs=/dev/tty*;/dev/pgps;bluetooth
diff --git a/src/gypsy-server.c b/src/gypsy-server.c
index e2e3c1c..3ff13f4 100644
--- a/src/gypsy-server.c
+++ b/src/gypsy-server.c
@@ -28,12 +28,17 @@
/*
* GypsyServer - The main control object that creates GPS connection objects.
*/
+#include "config.h"
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-bindings.h>
#include <dbus/dbus-glib-lowlevel.h>
+#ifdef HAVE_BLUEZ
+#include <bluetooth/bluetooth.h>
+#endif
+
#include "gypsy-server.h"
#include "gypsy-client.h"
@@ -49,6 +54,9 @@ typedef struct _GypsyServerPrivate {
int client_count; /* When client_count returns to 0,
we quit the daemon after TERMINATE_TIMEOUT */
guint32 terminate_id;
+
+ gchar **allowed_device_globs;
+ gsize allowed_device_glob_count;
} GypsyServerPrivate;
static guint32 signals[LAST_SIGNAL] = {0, };
@@ -60,6 +68,9 @@ G_DEFINE_TYPE (GypsyServer, gypsy_server, G_TYPE_OBJECT);
#define GYPSY_GPS_PATH "/org/freedesktop/Gypsy/"
#define TERMINATE_TIMEOUT 10000 /* 10 second timeout */
+#define GYPSY_CONF_GROUP "gypsy"
+#define GYPSY_CONF_GLOB_KEY "AllowedDeviceGlobs"
+
static void gypsy_server_create (GypsyServer *gps,
const char *IN_device_path,
DBusGMethodInvocation *context);
@@ -102,6 +113,8 @@ gypsy_server_create (GypsyServer *gps,
GypsyClient *client;
char *path, *device_name, *sender;
GList *list;
+ int i;
+ gboolean allowed;
priv = GET_PRIVATE (gps);
@@ -113,6 +126,40 @@ gypsy_server_create (GypsyServer *gps,
}
g_debug ("Creating client for %s", IN_device_path);
+
+ /* compare priv->device_path to allowed globs
+ * if not allowed, error out */
+ allowed = FALSE;
+ for (i = 0; i < priv->allowed_device_glob_count; i++) {
+ if (g_str_equal (priv->allowed_device_globs[i], "bluetooth")) {
+#ifdef HAVE_BLUEZ
+ if (bachk (IN_device_path) == 0) {
+ allowed = TRUE;
+ break;
+ }
+#else
+ continue;
+#endif /* HAVE_BLUEZ */
+ }
+ if (g_pattern_match_simple (priv->allowed_device_globs[i],
+ IN_device_path)) {
+ allowed = TRUE;
+ break;
+ }
+ }
+ if (allowed == FALSE) {
+ g_warning ("The device path %s is not allowed by config file",
+ IN_device_path);
+ GError *error = NULL;
+ error = g_error_new (GYPSY_SERVER_ERROR,
+ GYPSY_SERVER_ERROR_BAD_PATH,
+ "Bad path: %s",
+ IN_device_path);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return;
+ }
+
device_name = g_path_get_basename (IN_device_path);
g_debug ("Device name: %s", device_name);
path = g_strdup_printf ("%s%s", GYPSY_GPS_PATH,
@@ -250,6 +297,7 @@ gypsy_server_init (GypsyServer *gps)
{
GypsyServerPrivate *priv = GET_PRIVATE (gps);
GError *error = NULL;
+ GKeyFile *key_file = NULL;
priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (priv->connection == NULL) {
@@ -265,6 +313,27 @@ gypsy_server_init (GypsyServer *gps)
priv->client_count = 0;
priv->terminate_id = 0;
+
+ key_file = g_key_file_new();
+ if (!g_key_file_load_from_file (key_file, CONFIG_FILE_PATH,
+ G_KEY_FILE_NONE, &error))
+ goto error;
+
+ priv->allowed_device_globs = g_key_file_get_string_list (key_file,
+ GYPSY_CONF_GROUP,
+ GYPSY_CONF_GLOB_KEY,
+ &(priv->allowed_device_glob_count),
+ &error);
+ if (!priv->allowed_device_globs)
+ goto error;
+
+ return;
+
+error:
+ g_warning ("Error parsing config file:\n%s",
+ error->message);
+ g_error_free (error);
+ g_key_file_free (key_file);
}
void
diff --git a/src/gypsy-server.h b/src/gypsy-server.h
index 465f18e..3470ba7 100644
--- a/src/gypsy-server.h
+++ b/src/gypsy-server.h
@@ -37,6 +37,7 @@ G_BEGIN_DECLS
typedef enum {
GYPSY_SERVER_ERROR_NO_CLIENT,
+ GYPSY_SERVER_ERROR_BAD_PATH
} GypsyServerError;
typedef struct _GypsyServer {
--
1.7.6.2