[glib/glib-2-66: 1/6] giomodule: Ignore GIO_MODULE_DIR when running as setuid




commit 5bdda2a6b5196f49b4a5ecd2faa980a19dd49be8
Author: Philip Withnall <pwithnall endlessos org>
Date:   Fri Dec 4 23:33:43 2020 +0000

    giomodule: Ignore GIO_MODULE_DIR when running as setuid
    
    Even if the modules in the given directory never get chosen to be used,
    loading arbitrary code from a user-provided directory is not safe when
    running as setuid, as the process’ environment comes from an untrusted
    source.
    
    Also ignore `GIO_EXTRA_MODULES`.
    
    Spotted by Simon McVittie.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #2168

 docs/reference/gio/overview.xml |  6 ++++++
 gio/giomodule.c                 | 24 ++++++++++++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)
---
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.
       </para>
+      <para>
+        This environment variable is ignored when running in a setuid program.
+      </para>
     </formalpara>
 
     <formalpara>
@@ -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.
       </para>
+      <para>
+        This environment variable is ignored when running in a setuid program.
+      </para>
     </formalpara>
 
     <formalpara>
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;
-
-  module_dir = g_strdup (g_getenv ("GIO_MODULE_DIR"));
+  gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
+
+  /* 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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]