diff --git a/docs/reference/gio/overview.xml b/docs/reference/gio/overview.xml
index 7817ab60f..d82f1ac94 100644
--- a/docs/reference/gio/overview.xml
+++ b/docs/reference/gio/overview.xml
@@ -436,6 +436,9 @@ Gvfs is also heavily distributed and relies on a session bus to be present.
modules from this alternate directory instead of the directory
built into GIO. This is useful when running tests, for example.
+
+ This environment variable is ignored when running in a setuid program.
+
@@ -446,6 +449,9 @@ Gvfs is also heavily distributed and relies on a session bus to be present.
paths separated by a colon, GIO will attempt to load
additional modules from within the path.
+
+ This environment variable is ignored when running in a setuid program.
+
diff --git a/gio/giomodule.c b/gio/giomodule.c
index dc4d6d3b3..aaf46364c 100644
--- a/gio/giomodule.c
+++ b/gio/giomodule.c
@@ -30,6 +30,7 @@
#include "giomodule.h"
#include "giomodule-priv.h"
+#include "glib-private.h"
#include "glocalfilemonitor.h"
#include "gnativevolumemonitor.h"
#include "gproxyresolver.h"
@@ -806,6 +807,9 @@ _g_io_module_get_default_type (const gchar *extension_point,
return G_TYPE_INVALID;
}
+ /* It’s OK to query the environment here, even when running as setuid, because
+ * it only allows a choice between existing already-loaded modules. No new
+ * code is loaded based on the environment variable value. */
use_this = envvar ? g_getenv (envvar) : NULL;
if (g_strcmp0 (use_this, "help") == 0)
{
@@ -955,6 +959,9 @@ _g_io_module_get_default (const gchar *extension_point,
return NULL;
}
+ /* It’s OK to query the environment here, even when running as setuid, because
+ * it only allows a choice between existing already-loaded modules. No new
+ * code is loaded based on the environment variable value. */
use_this = envvar ? g_getenv (envvar) : NULL;
if (g_strcmp0 (use_this, "help") == 0)
{
@@ -1150,8 +1157,16 @@ static gchar *
get_gio_module_dir (void)
{
gchar *module_dir;
+ gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
- module_dir = g_strdup (g_getenv ("GIO_MODULE_DIR"));
+ /* If running as setuid, loading modules from an arbitrary directory
+ * controlled by the unprivileged user who is running the program could allow
+ * for execution of arbitrary code (in constructors in modules).
+ * Don’t allow it.
+ *
+ * If a setuid program somehow needs to load additional GIO modules, it should
+ * explicitly call g_io_modules_scan_all_in_directory(). */
+ module_dir = !is_setuid ? g_strdup (g_getenv ("GIO_MODULE_DIR")) : NULL;
if (module_dir == NULL)
{
#ifdef G_OS_WIN32
@@ -1183,13 +1198,14 @@ _g_io_modules_ensure_loaded (void)
if (!loaded_dirs)
{
+ gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
gchar *module_dir;
loaded_dirs = TRUE;
scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
- /* First load any overrides, extras */
- module_path = g_getenv ("GIO_EXTRA_MODULES");
+ /* First load any overrides, extras (but not if running as setuid!) */
+ module_path = !is_setuid ? g_getenv ("GIO_EXTRA_MODULES") : NULL;
if (module_path)
{
gchar **paths;