summaryrefslogtreecommitdiff
path: root/gio
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-10-29 10:27:37 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-10-29 10:27:37 +0900
commitb47d6166aeba31fa97d89743cfcc730a09c39090 (patch)
tree99f42979d032f357dc6abdc7a125734265438b93 /gio
parent40ed3381d56b5e6d3700e465b70085e6820fe787 (diff)
downloadglib-b47d6166aeba31fa97d89743cfcc730a09c39090.tar.gz
glib-b47d6166aeba31fa97d89743cfcc730a09c39090.tar.bz2
glib-b47d6166aeba31fa97d89743cfcc730a09c39090.zip
Imported Upstream version 2.66.5upstream/2.66.5
Diffstat (limited to 'gio')
-rw-r--r--gio/gdbusaddress.c38
-rw-r--r--gio/gdesktopappinfo.c79
-rw-r--r--gio/giomodule.c24
-rw-r--r--gio/gresource.c9
-rw-r--r--gio/gsettingsschema.c6
-rw-r--r--gio/gsocket.c4
-rw-r--r--gio/tests/desktop-app-info.c6
-rw-r--r--gio/tests/desktop-files/usr/applications/invalid-desktop.desktop5
-rw-r--r--gio/tests/file.c4
9 files changed, 138 insertions, 37 deletions
diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c
index 3dd3cc84b..0044cd3c6 100644
--- a/gio/gdbusaddress.c
+++ b/gio/gdbusaddress.c
@@ -30,6 +30,7 @@
#include "gdbusaddress.h"
#include "gdbuserror.h"
#include "gioenumtypes.h"
+#include "glib-private.h"
#include "gnetworkaddress.h"
#include "gsocketclient.h"
#include "giostream.h"
@@ -1279,6 +1280,7 @@ g_dbus_address_get_for_bus_sync (GBusType bus_type,
GCancellable *cancellable,
GError **error)
{
+ gboolean has_elevated_privileges = GLIB_PRIVATE_CALL (g_check_setuid) ();
gchar *ret, *s = NULL;
const gchar *starter_bus;
GError *local_error;
@@ -1317,10 +1319,16 @@ g_dbus_address_get_for_bus_sync (GBusType bus_type,
_g_dbus_debug_print_unlock ();
}
+ /* Don’t load the addresses from the environment if running as setuid, as they
+ * come from an unprivileged caller. */
switch (bus_type)
{
case G_BUS_TYPE_SYSTEM:
- ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
+ if (has_elevated_privileges)
+ ret = NULL;
+ else
+ ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
+
if (ret == NULL)
{
ret = g_strdup ("unix:path=/var/run/dbus/system_bus_socket");
@@ -1328,7 +1336,33 @@ g_dbus_address_get_for_bus_sync (GBusType bus_type,
break;
case G_BUS_TYPE_SESSION:
- ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
+ if (has_elevated_privileges)
+ {
+#ifdef G_OS_UNIX
+ if (geteuid () == getuid ())
+ {
+ /* Ideally we shouldn't do this, because setgid and
+ * filesystem capabilities are also elevated privileges
+ * with which we should not be trusting environment variables
+ * from the caller. Unfortunately, there are programs with
+ * elevated privileges that rely on the session bus being
+ * available. We already prevent the really dangerous
+ * transports like autolaunch: and unixexec: when our
+ * privileges are elevated, so this can only make us connect
+ * to the wrong AF_UNIX or TCP socket. */
+ ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
+ }
+ else
+#endif
+ {
+ ret = NULL;
+ }
+ }
+ else
+ {
+ ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
+ }
+
if (ret == NULL)
{
ret = get_session_address_platform_specific (&local_error);
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index b779b309b..2b139a01c 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -305,6 +305,55 @@ desktop_file_dir_app_name_is_masked (DesktopFileDir *dir,
return FALSE;
}
+/* Not much to go on from https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
+ * so validate it as a non-empty alphanumeric ASCII string with `-` and `_` allowed.
+ *
+ * Validation is important as the desktop IDs are used to construct filenames,
+ * and may be set by an unprivileged caller if running in a setuid program. */
+static gboolean
+validate_xdg_desktop (const gchar *desktop)
+{
+ gsize i;
+
+ for (i = 0; desktop[i] != '\0'; i++)
+ if (desktop[i] != '-' && desktop[i] != '_' &&
+ !g_ascii_isalnum (desktop[i]))
+ return FALSE;
+
+ if (i == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static char **
+get_valid_current_desktops (const char *value)
+{
+ char **tmp;
+ gsize i;
+ GPtrArray *valid_desktops;
+
+ if (value == NULL)
+ value = g_getenv ("XDG_CURRENT_DESKTOP");
+ if (value == NULL)
+ value = "";
+
+ tmp = g_strsplit (value, G_SEARCHPATH_SEPARATOR_S, 0);
+ valid_desktops = g_ptr_array_new_full (g_strv_length (tmp) + 1, g_free);
+ for (i = 0; tmp[i]; i++)
+ {
+ if (validate_xdg_desktop (tmp[i]))
+ g_ptr_array_add (valid_desktops, tmp[i]);
+ else
+ g_free (tmp[i]);
+ }
+ g_ptr_array_add (valid_desktops, NULL);
+ g_free (tmp);
+ tmp = (char **) g_ptr_array_steal (valid_desktops, NULL);
+ g_ptr_array_unref (valid_desktops);
+ return tmp;
+}
+
static const gchar * const *
get_lowercase_current_desktops (void)
{
@@ -312,23 +361,15 @@ get_lowercase_current_desktops (void)
if (g_once_init_enter (&result))
{
- const gchar *envvar;
- gchar **tmp;
-
- envvar = g_getenv ("XDG_CURRENT_DESKTOP");
+ char **tmp = get_valid_current_desktops (NULL);
+ gsize i, j;
- if (envvar)
+ for (i = 0; tmp[i]; i++)
{
- gint i, j;
-
- tmp = g_strsplit (envvar, G_SEARCHPATH_SEPARATOR_S, 0);
-
- for (i = 0; tmp[i]; i++)
- for (j = 0; tmp[i][j]; j++)
- tmp[i][j] = g_ascii_tolower (tmp[i][j]);
+ /* Convert to lowercase. */
+ for (j = 0; tmp[i][j]; j++)
+ tmp[i][j] = g_ascii_tolower (tmp[i][j]);
}
- else
- tmp = g_new0 (gchar *, 0 + 1);
g_once_init_leave (&result, tmp);
}
@@ -343,15 +384,7 @@ get_current_desktops (const gchar *value)
if (g_once_init_enter (&result))
{
- gchar **tmp;
-
- if (!value)
- value = g_getenv ("XDG_CURRENT_DESKTOP");
-
- if (!value)
- value = "";
-
- tmp = g_strsplit (value, ":", 0);
+ char **tmp = get_valid_current_desktops (value);
g_once_init_leave (&result, tmp);
}
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;
diff --git a/gio/gresource.c b/gio/gresource.c
index b7222b8eb..13632d971 100644
--- a/gio/gresource.c
+++ b/gio/gresource.c
@@ -32,6 +32,8 @@
#include <gio/gzlibdecompressor.h>
#include <gio/gconverterinputstream.h>
+#include "glib-private.h"
+
struct _GResource
{
int ref_count;
@@ -159,7 +161,7 @@ G_DEFINE_BOXED_TYPE (GResource, g_resource, g_resource_ref, g_resource_unref)
* replace resources in the program or library, without recompiling, for debugging or quick hacking and testing
* purposes. Since GLib 2.50, it is possible to use the `G_RESOURCE_OVERLAYS` environment variable to selectively overlay
* resources with replacements from the filesystem. It is a %G_SEARCHPATH_SEPARATOR-separated list of substitutions to perform
- * during resource lookups.
+ * during resource lookups. It is ignored when running in a setuid process.
*
* A substitution has the form
*
@@ -330,10 +332,13 @@ g_resource_find_overlay (const gchar *path,
if (g_once_init_enter (&overlay_dirs))
{
+ gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
const gchar * const *result;
const gchar *envvar;
- envvar = g_getenv ("G_RESOURCE_OVERLAYS");
+ /* Don’t load overlays if setuid, as they could allow reading privileged
+ * files. */
+ envvar = !is_setuid ? g_getenv ("G_RESOURCE_OVERLAYS") : NULL;
if (envvar != NULL)
{
gchar **parts;
diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index 0b94f76f6..8e203db01 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -18,6 +18,7 @@
#include "config.h"
+#include "glib-private.h"
#include "gsettingsschema-internal.h"
#include "gsettings.h"
@@ -343,6 +344,7 @@ initialise_schema_sources (void)
*/
if G_UNLIKELY (g_once_init_enter (&initialised))
{
+ gboolean is_setuid = GLIB_PRIVATE_CALL (g_check_setuid) ();
const gchar * const *dirs;
const gchar *path;
gchar **extra_schema_dirs;
@@ -357,7 +359,9 @@ initialise_schema_sources (void)
try_prepend_data_dir (g_get_user_data_dir ());
- if ((path = g_getenv ("GSETTINGS_SCHEMA_DIR")) != NULL)
+ /* Disallow loading extra schemas if running as setuid, as that could
+ * allow reading privileged files. */
+ if (!is_setuid && (path = g_getenv ("GSETTINGS_SCHEMA_DIR")) != NULL)
{
extra_schema_dirs = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 0);
for (i = 0; extra_schema_dirs[i]; i++);
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 0f8f9259f..e911de781 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -5475,10 +5475,10 @@ g_socket_receive_message_with_timeout (GSocket *socket,
if (errsv == WSAEINTR)
continue;
+ win32_unset_event_mask (socket, FD_READ);
+
if (errsv == WSAEWOULDBLOCK)
{
- win32_unset_event_mask (socket, FD_READ);
-
if (timeout_us != 0)
{
if (!block_on_timeout (socket, G_IO_IN, timeout_us,
diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c
index f4e509a59..bc50ff491 100644
--- a/gio/tests/desktop-app-info.c
+++ b/gio/tests/desktop-app-info.c
@@ -571,7 +571,8 @@ assert_implementations (const gchar *interface,
"gnome-terminal.desktop nautilus-autorun-software.desktop gcr-viewer.desktop " \
"nautilus-connect-server.desktop kde4-dolphin.desktop gnome-music.desktop " \
"kde4-konqbrowser.desktop gucharmap.desktop kde4-okular.desktop nautilus.desktop " \
- "gedit.desktop evince.desktop file-roller.desktop dconf-editor.desktop glade.desktop"
+ "gedit.desktop evince.desktop file-roller.desktop dconf-editor.desktop glade.desktop " \
+ "invalid-desktop.desktop"
#define HOME_APPS "epiphany-weather-for-toronto-island-9c6a4e022b17686306243dada811d550d25eb1fb.desktop"
#define ALL_HOME_APPS HOME_APPS " eog.desktop"
@@ -726,6 +727,9 @@ test_show_in (void)
assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic");
assert_shown ("gcr-prompter.desktop", TRUE, "GNOME-Classic:KDE");
assert_shown ("gcr-prompter.desktop", TRUE, "KDE:GNOME-Classic");
+ assert_shown ("invalid-desktop.desktop", TRUE, "GNOME");
+ assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop");
+ assert_shown ("invalid-desktop.desktop", FALSE, "../invalid/desktop:../invalid/desktop");
}
/* Test g_desktop_app_info_launch_uris_as_manager() and
diff --git a/gio/tests/desktop-files/usr/applications/invalid-desktop.desktop b/gio/tests/desktop-files/usr/applications/invalid-desktop.desktop
new file mode 100644
index 000000000..dffaa2469
--- /dev/null
+++ b/gio/tests/desktop-files/usr/applications/invalid-desktop.desktop
@@ -0,0 +1,5 @@
+[Desktop Entry]
+Type=Application
+Name=appinfo-test
+OnlyShowIn=../invalid/desktop;GNOME
+NotShowIn=ROX;
diff --git a/gio/tests/file.c b/gio/tests/file.c
index c3877af4b..d8769656c 100644
--- a/gio/tests/file.c
+++ b/gio/tests/file.c
@@ -1041,7 +1041,7 @@ test_measure (void)
if (size > 0)
g_assert_cmpuint (num_bytes, ==, size);
g_assert_cmpuint (num_dirs, ==, 6);
- g_assert_cmpuint (num_files, ==, 31);
+ g_assert_cmpuint (num_files, ==, 32);
g_object_unref (file);
g_free (path);
@@ -1131,7 +1131,7 @@ test_measure_async (void)
g_free (path);
data->expected_dirs = 6;
- data->expected_files = 31;
+ data->expected_files = 32;
g_file_measure_disk_usage_async (file,
G_FILE_MEASURE_APPARENT_SIZE,