summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/glib-2.0
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/glib-2.0')
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch129
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch170
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch249
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch131
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch298
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch54
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch101
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch76
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch101
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch100
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch59
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch63
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch36
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch38
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch38
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch100
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch49
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch43
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch232
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch27
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch42
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch57
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch265
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch55
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch290
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch89
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch255
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch49
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch154
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch103
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch210
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch417
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch113
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch80
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch396
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch49
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch394
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch97
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb38
-rw-r--r--meta/recipes-core/glib-2.0/glib.inc2
40 files changed, 5248 insertions, 1 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch
new file mode 100644
index 0000000000..6257763d8d
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch
@@ -0,0 +1,129 @@
+Backport of:
+
+From 0f384c88a241bbbd884487b1c40b7b75f1e638d3 Mon Sep 17 00:00:00 2001
+From: Krzesimir Nowak <qdlacz@gmail.com>
+Date: Wed, 10 Feb 2021 23:51:07 +0100
+Subject: [PATCH] gbytearray: Do not accept too large byte arrays
+
+GByteArray uses guint for storing the length of the byte array, but it
+also has a constructor (g_byte_array_new_take) that takes length as a
+gsize. gsize may be larger than guint (64 bits for gsize vs 32 bits
+for guint). It is possible to call the function with a value greater
+than G_MAXUINT, which will result in silent length truncation. This
+may happen as a result of unreffing GBytes into GByteArray, so rather
+be loud about it.
+
+(Test case tweaked by Philip Withnall.)
+
+(Backport 2.66: Add #include gstrfuncsprivate.h in the test case for
+`g_memdup2()`.)
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27218
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ glib/garray.c | 6 ++++++
+ glib/gbytes.c | 4 ++++
+ glib/tests/bytes.c | 35 ++++++++++++++++++++++++++++++++++-
+ 3 files changed, 44 insertions(+), 1 deletion(-)
+
+--- a/glib/garray.c
++++ b/glib/garray.c
+@@ -2234,6 +2234,10 @@ g_byte_array_steal (GByteArray *array,
+ * Create byte array containing the data. The data will be owned by the array
+ * and will be freed with g_free(), i.e. it could be allocated using g_strdup().
+ *
++ * Do not use it if @len is greater than %G_MAXUINT. #GByteArray
++ * stores the length of its data in #guint, which may be shorter than
++ * #gsize.
++ *
+ * Since: 2.32
+ *
+ * Returns: (transfer full): a new #GByteArray
+@@ -2245,6 +2249,8 @@ g_byte_array_new_take (guint8 *data,
+ GByteArray *array;
+ GRealArray *real;
+
++ g_return_val_if_fail (len <= G_MAXUINT, NULL);
++
+ array = g_byte_array_new ();
+ real = (GRealArray *)array;
+ g_assert (real->data == NULL);
+--- a/glib/gbytes.c
++++ b/glib/gbytes.c
+@@ -519,6 +519,10 @@ g_bytes_unref_to_data (GBytes *bytes,
+ * g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all
+ * other cases the data is copied.
+ *
++ * Do not use it if @bytes contains more than %G_MAXUINT
++ * bytes. #GByteArray stores the length of its data in #guint, which
++ * may be shorter than #gsize, that @bytes is using.
++ *
+ * Returns: (transfer full): a new mutable #GByteArray containing the same byte data
+ *
+ * Since: 2.32
+--- a/glib/tests/bytes.c
++++ b/glib/tests/bytes.c
+@@ -10,12 +10,12 @@
+ */
+
+ #undef G_DISABLE_ASSERT
+-#undef G_LOG_DOMAIN
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include "glib.h"
++#include "glib/gstrfuncsprivate.h"
+
+ /* Keep in sync with glib/gbytes.c */
+ struct _GBytes
+@@ -334,6 +334,38 @@ test_to_array_transferred (void)
+ }
+
+ static void
++test_to_array_transferred_oversize (void)
++{
++ g_test_message ("g_bytes_unref_to_array() can only take GBytes up to "
++ "G_MAXUINT in length; test that longer ones are rejected");
++
++ if (sizeof (guint) >= sizeof (gsize))
++ {
++ g_test_skip ("Skipping test as guint is not smaller than gsize");
++ }
++ else if (g_test_undefined ())
++ {
++ GByteArray *array = NULL;
++ GBytes *bytes = NULL;
++ gpointer data = g_memdup2 (NYAN, N_NYAN);
++ gsize len = ((gsize) G_MAXUINT) + 1;
++
++ bytes = g_bytes_new_take (data, len);
++ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
++ "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed");
++ array = g_bytes_unref_to_array (g_steal_pointer (&bytes));
++ g_test_assert_expected_messages ();
++ g_assert_null (array);
++
++ g_free (data);
++ }
++ else
++ {
++ g_test_skip ("Skipping test as testing undefined behaviour is disabled");
++ }
++}
++
++static void
+ test_to_array_two_refs (void)
+ {
+ gconstpointer memory;
+@@ -410,6 +442,7 @@ main (int argc, char *argv[])
+ g_test_add_func ("/bytes/to-array/transfered", test_to_array_transferred);
+ g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
+ g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
++ g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize);
+ g_test_add_func ("/bytes/null", test_null);
+
+ return g_test_run ();
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch
new file mode 100644
index 0000000000..2af9dd6aa4
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch
@@ -0,0 +1,170 @@
+Backport of:
+
+From 5e5f75a77e399c638be66d74e5daa8caeb433e00 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:30:52 +0000
+Subject: [PATCH 01/11] gstrfuncs: Add internal g_memdup2() function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This will replace the existing `g_memdup()` function for use within
+GLib. It has an unavoidable security flaw of taking its `byte_size`
+argument as a `guint` rather than as a `gsize`. Most callers will
+expect it to be a `gsize`, and may pass in large values which could
+silently be truncated, resulting in an undersize allocation compared
+to what the caller expects.
+
+This could lead to a classic buffer overflow vulnerability for many
+callers of `g_memdup()`.
+
+`g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`.
+
+Spotted by Kevin Backhouse of GHSL.
+
+In GLib 2.68, `g_memdup2()` will be a new public API. In this version
+for backport to older stable releases, it’s a new `static inline` API
+in a private header, so that use of `g_memdup()` within GLib can be
+fixed without adding a new API in a stable release series.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: GHSL-2021-045
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ docs/reference/glib/meson.build | 1 +
+ glib/gstrfuncsprivate.h | 55 +++++++++++++++++++++++++++++++++
+ glib/meson.build | 1 +
+ glib/tests/strfuncs.c | 23 ++++++++++++++
+ 4 files changed, 80 insertions(+)
+ create mode 100644 glib/gstrfuncsprivate.h
+
+--- a/docs/reference/glib/meson.build
++++ b/docs/reference/glib/meson.build
+@@ -22,6 +22,7 @@ if get_option('gtk_doc')
+ 'gprintfint.h',
+ 'gmirroringtable.h',
+ 'gscripttable.h',
++ 'gstrfuncsprivate.h',
+ 'glib-mirroring-tab',
+ 'gnulib',
+ 'pcre',
+--- /dev/null
++++ b/glib/gstrfuncsprivate.h
+@@ -0,0 +1,55 @@
++/* GLIB - Library of useful routines for C programming
++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <glib.h>
++#include <string.h>
++
++/*
++ * g_memdup2:
++ * @mem: (nullable): the memory to copy.
++ * @byte_size: the number of bytes to copy.
++ *
++ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
++ * from @mem. If @mem is %NULL it returns %NULL.
++ *
++ * This replaces g_memdup(), which was prone to integer overflows when
++ * converting the argument from a #gsize to a #guint.
++ *
++ * This static inline version is a backport of the new public API from
++ * GLib 2.68, kept internal to GLib for backport to older stable releases.
++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
++ *
++ * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
++ * or %NULL if @mem is %NULL.
++ * Since: 2.68
++ */
++static inline gpointer
++g_memdup2 (gconstpointer mem,
++ gsize byte_size)
++{
++ gpointer new_mem;
++
++ if (mem && byte_size != 0)
++ {
++ new_mem = g_malloc (byte_size);
++ memcpy (new_mem, mem, byte_size);
++ }
++ else
++ new_mem = NULL;
++
++ return new_mem;
++}
+--- a/glib/meson.build
++++ b/glib/meson.build
+@@ -268,6 +268,7 @@ glib_sources = files(
+ 'gslist.c',
+ 'gstdio.c',
+ 'gstrfuncs.c',
++ 'gstrfuncsprivate.h',
+ 'gstring.c',
+ 'gstringchunk.c',
+ 'gtestutils.c',
+--- a/glib/tests/strfuncs.c
++++ b/glib/tests/strfuncs.c
+@@ -32,6 +32,8 @@
+ #include <string.h>
+ #include "glib.h"
+
++#include "gstrfuncsprivate.h"
++
+ #if defined (_MSC_VER) && (_MSC_VER <= 1800)
+ #define isnan(x) _isnan(x)
+
+@@ -219,6 +221,26 @@ test_memdup (void)
+ g_free (str_dup);
+ }
+
++/* Testing g_memdup2() function with various positive and negative cases */
++static void
++test_memdup2 (void)
++{
++ gchar *str_dup = NULL;
++ const gchar *str = "The quick brown fox jumps over the lazy dog";
++
++ /* Testing negative cases */
++ g_assert_null (g_memdup2 (NULL, 1024));
++ g_assert_null (g_memdup2 (str, 0));
++ g_assert_null (g_memdup2 (NULL, 0));
++
++ /* Testing normal usage cases */
++ str_dup = g_memdup2 (str, strlen (str) + 1);
++ g_assert_nonnull (str_dup);
++ g_assert_cmpstr (str, ==, str_dup);
++
++ g_free (str_dup);
++}
++
+ /* Testing g_strpcpy() function with various positive and negative cases */
+ static void
+ test_stpcpy (void)
+@@ -2523,6 +2545,7 @@ main (int argc,
+ g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
+ g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
+ g_test_add_func ("/strfuncs/memdup", test_memdup);
++ g_test_add_func ("/strfuncs/memdup2", test_memdup2);
+ g_test_add_func ("/strfuncs/stpcpy", test_stpcpy);
+ g_test_add_func ("/strfuncs/str_match_string", test_str_match_string);
+ g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch
new file mode 100644
index 0000000000..20137ea5f3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch
@@ -0,0 +1,249 @@
+From be8834340a2d928ece82025463ae23dee2c333d0 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:37:56 +0000
+Subject: [PATCH 02/11] gio: Use g_memdup2() instead of g_memdup() in obvious
+ places
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Convert all the call sites which use `g_memdup()`’s length argument
+trivially (for example, by passing a `sizeof()`), so that they use
+`g_memdup2()` instead.
+
+In almost all of these cases the use of `g_memdup()` would not have
+caused problems, but it will soon be deprecated, so best port away from
+it.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gdbusconnection.c | 5 +++--
+ gio/gdbusinterfaceskeleton.c | 3 ++-
+ gio/gfile.c | 7 ++++---
+ gio/gsettingsschema.c | 5 +++--
+ gio/gwin32registrykey.c | 8 +++++---
+ gio/tests/async-close-output-stream.c | 6 ++++--
+ gio/tests/gdbus-export.c | 5 +++--
+ gio/win32/gwinhttpfile.c | 9 +++++----
+ 8 files changed, 29 insertions(+), 19 deletions(-)
+
+--- a/gio/gdbusconnection.c
++++ b/gio/gdbusconnection.c
+@@ -110,6 +110,7 @@
+ #include "gasyncinitable.h"
+ #include "giostream.h"
+ #include "gasyncresult.h"
++#include "gstrfuncsprivate.h"
+ #include "gtask.h"
+ #include "gmarshal-internal.h"
+
+@@ -4007,7 +4008,7 @@ _g_dbus_interface_vtable_copy (const GDB
+ /* Don't waste memory by copying padding - remember to update this
+ * when changing struct _GDBusInterfaceVTable in gdbusconnection.h
+ */
+- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
++ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
+ }
+
+ static void
+@@ -4024,7 +4025,7 @@ _g_dbus_subtree_vtable_copy (const GDBus
+ /* Don't waste memory by copying padding - remember to update this
+ * when changing struct _GDBusSubtreeVTable in gdbusconnection.h
+ */
+- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
++ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
+ }
+
+ static void
+--- a/gio/gdbusinterfaceskeleton.c
++++ b/gio/gdbusinterfaceskeleton.c
+@@ -28,6 +28,7 @@
+ #include "gdbusmethodinvocation.h"
+ #include "gdbusconnection.h"
+ #include "gmarshal-internal.h"
++#include "gstrfuncsprivate.h"
+ #include "gtask.h"
+ #include "gioerror.h"
+
+@@ -701,7 +702,7 @@ add_connection_locked (GDBusInterfaceSke
+ * properly before building the hooked_vtable, so we create it
+ * once at the last minute.
+ */
+- interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
++ interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
+ interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call;
+ }
+
+--- a/gio/gfile.c
++++ b/gio/gfile.c
+@@ -60,6 +60,7 @@
+ #include "gasyncresult.h"
+ #include "gioerror.h"
+ #include "glibintl.h"
++#include "gstrfuncsprivate.h"
+
+
+ /**
+@@ -7854,7 +7855,7 @@ measure_disk_usage_progress (gboolean re
+ g_main_context_invoke_full (g_task_get_context (task),
+ g_task_get_priority (task),
+ measure_disk_usage_invoke_progress,
+- g_memdup (&progress, sizeof progress),
++ g_memdup2 (&progress, sizeof progress),
+ g_free);
+ }
+
+@@ -7872,7 +7873,7 @@ measure_disk_usage_thread (GTask
+ data->progress_callback ? measure_disk_usage_progress : NULL, task,
+ &result.disk_usage, &result.num_dirs, &result.num_files,
+ &error))
+- g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free);
++ g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free);
+ else
+ g_task_return_error (task, error);
+ }
+@@ -7896,7 +7897,7 @@ g_file_real_measure_disk_usage_async (GF
+
+ task = g_task_new (file, cancellable, callback, user_data);
+ g_task_set_source_tag (task, g_file_real_measure_disk_usage_async);
+- g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free);
++ g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free);
+ g_task_set_priority (task, io_priority);
+
+ g_task_run_in_thread (task, measure_disk_usage_thread);
+--- a/gio/gsettingsschema.c
++++ b/gio/gsettingsschema.c
+@@ -20,6 +20,7 @@
+
+ #include "gsettingsschema-internal.h"
+ #include "gsettings.h"
++#include "gstrfuncsprivate.h"
+
+ #include "gvdb/gvdb-reader.h"
+ #include "strinfo.c"
+@@ -1067,9 +1068,9 @@ g_settings_schema_list_children (GSettin
+
+ if (g_str_has_suffix (key, "/"))
+ {
+- gint length = strlen (key);
++ gsize length = strlen (key);
+
+- strv[j] = g_memdup (key, length);
++ strv[j] = g_memdup2 (key, length);
+ strv[j][length - 1] = '\0';
+ j++;
+ }
+--- a/gio/gwin32registrykey.c
++++ b/gio/gwin32registrykey.c
+@@ -28,6 +28,8 @@
+ #include <ntstatus.h>
+ #include <winternl.h>
+
++#include "gstrfuncsprivate.h"
++
+ #ifndef _WDMDDK_
+ typedef enum _KEY_INFORMATION_CLASS {
+ KeyBasicInformation,
+@@ -247,7 +249,7 @@ g_win32_registry_value_iter_copy (const
+ new_iter->value_name_size = iter->value_name_size;
+
+ if (iter->value_data != NULL)
+- new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size);
++ new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size);
+
+ new_iter->value_data_size = iter->value_data_size;
+
+@@ -268,8 +270,8 @@ g_win32_registry_value_iter_copy (const
+ new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
+
+ if (iter->value_data_expanded_u8 != NULL)
+- new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8,
+- iter->value_data_expanded_charsize);
++ new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8,
++ iter->value_data_expanded_charsize);
+
+ new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
+
+--- a/gio/tests/async-close-output-stream.c
++++ b/gio/tests/async-close-output-stream.c
+@@ -24,6 +24,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+
++#include "gstrfuncsprivate.h"
++
+ #define DATA_TO_WRITE "Hello world\n"
+
+ typedef struct
+@@ -147,9 +149,9 @@ prepare_data (SetupData *data,
+
+ data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream));
+
+- g_assert_cmpint (data->expected_size, >, 0);
++ g_assert_cmpuint (data->expected_size, >, 0);
+
+- data->expected_output = g_memdup (written, (guint)data->expected_size);
++ data->expected_output = g_memdup2 (written, data->expected_size);
+
+ /* then recreate the streams and prepare them for the asynchronous close */
+ destroy_streams (data);
+--- a/gio/tests/gdbus-export.c
++++ b/gio/tests/gdbus-export.c
+@@ -23,6 +23,7 @@
+ #include <string.h>
+
+ #include "gdbus-tests.h"
++#include "gstrfuncsprivate.h"
+
+ /* all tests rely on a shared mainloop */
+ static GMainLoop *loop = NULL;
+@@ -671,7 +672,7 @@ subtree_introspect (GDBusConnection
+ g_assert_not_reached ();
+ }
+
+- return g_memdup (interfaces, 2 * sizeof (void *));
++ return g_memdup2 (interfaces, 2 * sizeof (void *));
+ }
+
+ static const GDBusInterfaceVTable *
+@@ -727,7 +728,7 @@ dynamic_subtree_introspect (GDBusConnect
+ {
+ const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL };
+
+- return g_memdup (interfaces, 2 * sizeof (void *));
++ return g_memdup2 (interfaces, 2 * sizeof (void *));
+ }
+
+ static const GDBusInterfaceVTable *
+--- a/gio/win32/gwinhttpfile.c
++++ b/gio/win32/gwinhttpfile.c
+@@ -29,6 +29,7 @@
+ #include "gio/gfile.h"
+ #include "gio/gfileattribute.h"
+ #include "gio/gfileinfo.h"
++#include "gstrfuncsprivate.h"
+ #include "gwinhttpfile.h"
+ #include "gwinhttpfileinputstream.h"
+ #include "gwinhttpfileoutputstream.h"
+@@ -393,10 +394,10 @@
+ child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
+ child->vfs = winhttp_file->vfs;
+ child->url = winhttp_file->url;
+- child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
+- child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
+- child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
+- child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
++ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
++ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
++ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
++ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
+ child->url.lpszUrlPath = wnew_path;
+ child->url.dwUrlPathLength = wcslen (wnew_path);
+ child->url.lpszExtraInfo = NULL;
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch
new file mode 100644
index 0000000000..eceff161a6
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch
@@ -0,0 +1,131 @@
+From 6110caea45b235420b98cd41d845cc92238f6781 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:39:25 +0000
+Subject: [PATCH 03/11] gobject: Use g_memdup2() instead of g_memdup() in
+ obvious places
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Convert all the call sites which use `g_memdup()`’s length argument
+trivially (for example, by passing a `sizeof()`), so that they use
+`g_memdup2()` instead.
+
+In almost all of these cases the use of `g_memdup()` would not have
+caused problems, but it will soon be deprecated, so best port away from
+it.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gobject/gsignal.c | 3 ++-
+ gobject/gtype.c | 9 +++++----
+ gobject/gtypemodule.c | 3 ++-
+ gobject/tests/param.c | 4 +++-
+ 4 files changed, 12 insertions(+), 7 deletions(-)
+
+--- a/gobject/gsignal.c
++++ b/gobject/gsignal.c
+@@ -28,6 +28,7 @@
+ #include <signal.h>
+
+ #include "gsignal.h"
++#include "gstrfuncsprivate.h"
+ #include "gtype-private.h"
+ #include "gbsearcharray.h"
+ #include "gvaluecollector.h"
+@@ -1809,7 +1810,7 @@ g_signal_newv (const gchar *signal
+ node->single_va_closure_is_valid = FALSE;
+ node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
+ node->n_params = n_params;
+- node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
++ node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
+ node->return_type = return_type;
+ node->class_closure_bsa = NULL;
+ if (accumulator)
+--- a/gobject/gtype.c
++++ b/gobject/gtype.c
+@@ -33,6 +33,7 @@
+
+ #include "glib-private.h"
+ #include "gconstructor.h"
++#include "gstrfuncsprivate.h"
+
+ #ifdef G_OS_WIN32
+ #include <windows.h>
+@@ -1470,7 +1471,7 @@ type_add_interface_Wm (TypeNode
+ iholder->next = iface_node_get_holders_L (iface);
+ iface_node_set_holders_W (iface, iholder);
+ iholder->instance_type = NODE_TYPE (node);
+- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
++ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
+ iholder->plugin = plugin;
+
+ /* create an iface entry for this type */
+@@ -1731,7 +1732,7 @@ type_iface_retrieve_holder_info_Wm (Type
+ INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
+
+ check_interface_info_I (iface, instance_type, &tmp_info);
+- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
++ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
+ }
+
+ return iholder; /* we don't modify write lock upon returning NULL */
+@@ -2016,10 +2017,10 @@ type_iface_vtable_base_init_Wm (TypeNode
+ IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
+
+ if (pentry)
+- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
++ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
+ }
+ if (!vtable)
+- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
++ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
+ entry->vtable = vtable;
+ vtable->g_type = NODE_TYPE (iface);
+ vtable->g_instance_type = NODE_TYPE (node);
+--- a/gobject/gtypemodule.c
++++ b/gobject/gtypemodule.c
+@@ -19,6 +19,7 @@
+
+ #include <stdlib.h>
+
++#include "gstrfuncsprivate.h"
+ #include "gtypeplugin.h"
+ #include "gtypemodule.h"
+
+@@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule
+ module_type_info->loaded = TRUE;
+ module_type_info->info = *type_info;
+ if (type_info->value_table)
+- module_type_info->info.value_table = g_memdup (type_info->value_table,
++ module_type_info->info.value_table = g_memdup2 (type_info->value_table,
+ sizeof (GTypeValueTable));
+
+ return module_type_info->type;
+--- a/gobject/tests/param.c
++++ b/gobject/tests/param.c
+@@ -2,6 +2,8 @@
+ #include <glib-object.h>
+ #include <stdlib.h>
+
++#include "gstrfuncsprivate.h"
++
+ static void
+ test_param_value (void)
+ {
+@@ -874,7 +876,7 @@ main (int argc, char *argv[])
+ test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
+ data.change_this_flag, data.change_this_type,
+ data.use_this_flag, data.use_this_type);
+- test_data = g_memdup (&data, sizeof (TestParamImplementData));
++ test_data = g_memdup2 (&data, sizeof (TestParamImplementData));
+ g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
+ g_free (test_path);
+ }
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch
new file mode 100644
index 0000000000..6a3ac6b552
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch
@@ -0,0 +1,298 @@
+Backport of:
+
+From 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:41:21 +0000
+Subject: [PATCH 04/11] glib: Use g_memdup2() instead of g_memdup() in obvious
+ places
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Convert all the call sites which use `g_memdup()`’s length argument
+trivially (for example, by passing a `sizeof()` or an existing `gsize`
+variable), so that they use `g_memdup2()` instead.
+
+In almost all of these cases the use of `g_memdup()` would not have
+caused problems, but it will soon be deprecated, so best port away from
+it
+
+In particular, this fixes an overflow within `g_bytes_new()`, identified
+as GHSL-2021-045 by GHSL team member Kevin Backhouse.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Fixes: GHSL-2021-045
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ glib/gbytes.c | 6 ++++--
+ glib/gdir.c | 3 ++-
+ glib/ghash.c | 7 ++++---
+ glib/giochannel.c | 5 +++--
+ glib/gslice.c | 3 ++-
+ glib/gtestutils.c | 3 ++-
+ glib/gvariant.c | 7 ++++---
+ glib/gvarianttype.c | 3 ++-
+ glib/tests/array-test.c | 4 +++-
+ glib/tests/option-context.c | 6 ++++--
+ glib/tests/uri.c | 8 +++++---
+ 11 files changed, 35 insertions(+), 20 deletions(-)
+
+--- a/glib/gbytes.c
++++ b/glib/gbytes.c
+@@ -34,6 +34,8 @@
+
+ #include <string.h>
+
++#include "gstrfuncsprivate.h"
++
+ /**
+ * GBytes:
+ *
+@@ -95,7 +97,7 @@ g_bytes_new (gconstpointer data,
+ {
+ g_return_val_if_fail (data != NULL || size == 0, NULL);
+
+- return g_bytes_new_take (g_memdup (data, size), size);
++ return g_bytes_new_take (g_memdup2 (data, size), size);
+ }
+
+ /**
+@@ -499,7 +501,7 @@ g_bytes_unref_to_data (GBytes *bytes,
+ * Copy: Non g_malloc (or compatible) allocator, or static memory,
+ * so we have to copy, and then unref.
+ */
+- result = g_memdup (bytes->data, bytes->size);
++ result = g_memdup2 (bytes->data, bytes->size);
+ *size = bytes->size;
+ g_bytes_unref (bytes);
+ }
+--- a/glib/gdir.c
++++ b/glib/gdir.c
+@@ -37,6 +37,7 @@
+ #include "gconvert.h"
+ #include "gfileutils.h"
+ #include "gstrfuncs.h"
++#include "gstrfuncsprivate.h"
+ #include "gtestutils.h"
+ #include "glibintl.h"
+
+@@ -112,7 +113,7 @@ g_dir_open_with_errno (const gchar *path
+ return NULL;
+ #endif
+
+- return g_memdup (&dir, sizeof dir);
++ return g_memdup2 (&dir, sizeof dir);
+ }
+
+ /**
+--- a/glib/ghash.c
++++ b/glib/ghash.c
+@@ -34,6 +34,7 @@
+ #include "gmacros.h"
+ #include "glib-private.h"
+ #include "gstrfuncs.h"
++#include "gstrfuncsprivate.h"
+ #include "gatomic.h"
+ #include "gtestutils.h"
+ #include "gslice.h"
+@@ -962,7 +963,7 @@ g_hash_table_ensure_keyval_fits (GHashTa
+ if (hash_table->have_big_keys)
+ {
+ if (key != value)
+- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
++ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
+ /* Keys and values are both big now, so no need for further checks */
+ return;
+ }
+@@ -970,7 +971,7 @@ g_hash_table_ensure_keyval_fits (GHashTa
+ {
+ if (key != value)
+ {
+- hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size);
++ hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size);
+ is_a_set = FALSE;
+ }
+ }
+@@ -998,7 +999,7 @@ g_hash_table_ensure_keyval_fits (GHashTa
+
+ /* Just split if necessary */
+ if (is_a_set && key != value)
+- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
++ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
+
+ #endif
+ }
+--- a/glib/giochannel.c
++++ b/glib/giochannel.c
+@@ -35,7 +35,7 @@
+ #include <errno.h>
+
+ #include "giochannel.h"
+-
++#include "gstrfuncsprivate.h"
+ #include "gstrfuncs.h"
+ #include "gtestutils.h"
+ #include "glibintl.h"
+
+@@ -1673,10 +1674,10 @@ g_io_channel_read_line (GIOChannel *cha
+
+ /* Copy the read bytes (including any embedded nuls) and nul-terminate.
+ * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a
+- * #GString, so it’s safe to call g_memdup() with +1 length to allocate
++ * #GString, so it’s safe to call g_memdup2() with +1 length to allocate
+ * a nul-terminator. */
+ g_assert (USE_BUF (channel));
+- line = g_memdup (USE_BUF (channel)->str, got_length + 1);
++ line = g_memdup2 (USE_BUF (channel)->str, got_length + 1);
+ line[got_length] = '\0';
+ *str_return = g_steal_pointer (&line);
+ g_string_erase (USE_BUF (channel), 0, got_length);
+--- a/glib/gslice.c
++++ b/glib/gslice.c
+@@ -41,6 +41,7 @@
+ #include "gmain.h"
+ #include "gmem.h" /* gslice.h */
+ #include "gstrfuncs.h"
++#include "gstrfuncsprivate.h"
+ #include "gutils.h"
+ #include "gtrashstack.h"
+ #include "gtestutils.h"
+@@ -350,7 +351,7 @@ g_slice_get_config_state (GSliceConfig c
+ array[i++] = allocator->contention_counters[address];
+ array[i++] = allocator_get_magazine_threshold (allocator, address);
+ *n_values = i;
+- return g_memdup (array, sizeof (array[0]) * *n_values);
++ return g_memdup2 (array, sizeof (array[0]) * *n_values);
+ default:
+ return NULL;
+ }
+--- a/glib/gtestutils.c
++++ b/glib/gtestutils.c
+@@ -49,6 +49,7 @@
+ #include "gpattern.h"
+ #include "grand.h"
+ #include "gstrfuncs.h"
++#include "gstrfuncsprivate.h"
+ #include "gtimer.h"
+ #include "gslice.h"
+ #include "gspawn.h"
+@@ -3803,7 +3804,7 @@ g_test_log_extract (GTestLogBuffer *tbuf
+ if (p <= tbuffer->data->str + mlength)
+ {
+ g_string_erase (tbuffer->data, 0, mlength);
+- tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg)));
++ tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg)));
+ return TRUE;
+ }
+
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -33,6 +33,7 @@
+
+ #include <string.h>
+
++#include "gstrfuncsprivate.h"
+
+ /**
+ * SECTION:gvariant
+@@ -725,7 +726,7 @@ g_variant_new_variant (GVariant *value)
+ g_variant_ref_sink (value);
+
+ return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
+- g_memdup (&value, sizeof value),
++ g_memdup2 (&value, sizeof value),
+ 1, g_variant_is_trusted (value));
+ }
+
+@@ -1229,7 +1230,7 @@ g_variant_new_fixed_array (const GVarian
+ return NULL;
+ }
+
+- data = g_memdup (elements, n_elements * element_size);
++ data = g_memdup2 (elements, n_elements * element_size);
+ value = g_variant_new_from_data (array_type, data,
+ n_elements * element_size,
+ FALSE, g_free, data);
+@@ -1908,7 +1909,7 @@ g_variant_dup_bytestring (GVariant *valu
+ if (length)
+ *length = size;
+
+- return g_memdup (original, size + 1);
++ return g_memdup2 (original, size + 1);
+ }
+
+ /**
+--- a/glib/gvarianttype.c
++++ b/glib/gvarianttype.c
+@@ -28,6 +28,7 @@
+
+ #include <string.h>
+
++#include "gstrfuncsprivate.h"
+
+ /**
+ * SECTION:gvarianttype
+@@ -1181,7 +1182,7 @@ g_variant_type_new_tuple (const GVariant
+ g_assert (offset < sizeof buffer);
+ buffer[offset++] = ')';
+
+- return (GVariantType *) g_memdup (buffer, offset);
++ return (GVariantType *) g_memdup2 (buffer, offset);
+ }
+
+ /**
+--- a/glib/tests/array-test.c
++++ b/glib/tests/array-test.c
+@@ -29,6 +29,8 @@
+ #include <string.h>
+ #include "glib.h"
+
++#include "gstrfuncsprivate.h"
++
+ /* Test data to be passed to any function which calls g_array_new(), providing
+ * the parameters for that call. Most #GArray tests should be repeated for all
+ * possible values of #ArrayTestData. */
+@@ -1917,7 +1919,7 @@ byte_array_new_take (void)
+ GByteArray *gbarray;
+ guint8 *data;
+
+- data = g_memdup ("woooweeewow", 11);
++ data = g_memdup2 ("woooweeewow", 11);
+ gbarray = g_byte_array_new_take (data, 11);
+ g_assert (gbarray->data == data);
+ g_assert_cmpuint (gbarray->len, ==, 11);
+--- a/glib/tests/option-context.c
++++ b/glib/tests/option-context.c
+@@ -27,6 +27,8 @@
+ #include <string.h>
+ #include <locale.h>
+
++#include "gstrfuncsprivate.h"
++
+ static GOptionEntry main_entries[] = {
+ { "main-switch", 0, 0,
+ G_OPTION_ARG_NONE, NULL,
+@@ -256,7 +258,7 @@ join_stringv (int argc, char **argv)
+ static char **
+ copy_stringv (char **argv, int argc)
+ {
+- return g_memdup (argv, sizeof (char *) * (argc + 1));
++ return g_memdup2 (argv, sizeof (char *) * (argc + 1));
+ }
+
+ static void
+@@ -2323,7 +2325,7 @@ test_group_parse (void)
+ g_option_context_add_group (context, group);
+
+ argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc);
+- orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *));
++ orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *));
+
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch
new file mode 100644
index 0000000000..4f86522d00
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch
@@ -0,0 +1,54 @@
+From 0cbad673215ec8a049b7fe2ff44b0beed31b376e Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 16:12:24 +0000
+Subject: [PATCH 05/11] gwinhttpfile: Avoid arithmetic overflow when
+ calculating a size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The members of `URL_COMPONENTS` (`winhttp_file->url`) are `DWORD`s, i.e.
+32-bit unsigned integers. Adding to and multiplying them may cause them
+to overflow the unsigned integer bounds, even if the result is passed to
+`g_memdup2()` which accepts a `gsize`.
+
+Cast the `URL_COMPONENTS` members to `gsize` first to ensure that the
+arithmetic is done in terms of `gsize`s rather than unsigned integers.
+
+Spotted by Sebastian Dröge.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/win32/gwinhttpfile.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c
+index 3f8fbd838..e0340e247 100644
+--- a/gio/win32/gwinhttpfile.c
++++ b/gio/win32/gwinhttpfile.c
+@@ -410,10 +410,10 @@ g_winhttp_file_resolve_relative_path (GFile *file,
+ child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
+ child->vfs = winhttp_file->vfs;
+ child->url = winhttp_file->url;
+- child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
+- child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
+- child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
+- child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
++ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2);
++ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2);
++ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2);
++ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2);
+ child->url.lpszUrlPath = wnew_path;
+ child->url.dwUrlPathLength = wcslen (wnew_path);
+ child->url.lpszExtraInfo = NULL;
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch
new file mode 100644
index 0000000000..d8043f5e29
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch
@@ -0,0 +1,101 @@
+From f9ee2275cbc312c0b4cdbc338a4fbb76eb36fb9a Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:49:00 +0000
+Subject: [PATCH 06/11] gdatainputstream: Handle stop_chars_len internally as
+ gsize
+
+Previously it was handled as a `gssize`, which meant that if the
+`stop_chars` string was longer than `G_MAXSSIZE` there would be an
+overflow.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gdatainputstream.c | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c
+index 2e7750cb5..2cdcbda19 100644
+--- a/gio/gdatainputstream.c
++++ b/gio/gdatainputstream.c
+@@ -27,6 +27,7 @@
+ #include "gioenumtypes.h"
+ #include "gioerror.h"
+ #include "glibintl.h"
++#include "gstrfuncsprivate.h"
+
+ #include <string.h>
+
+@@ -856,7 +857,7 @@ static gssize
+ scan_for_chars (GDataInputStream *stream,
+ gsize *checked_out,
+ const char *stop_chars,
+- gssize stop_chars_len)
++ gsize stop_chars_len)
+ {
+ GBufferedInputStream *bstream;
+ const char *buffer;
+@@ -952,7 +953,7 @@ typedef struct
+ gsize checked;
+
+ gchar *stop_chars;
+- gssize stop_chars_len;
++ gsize stop_chars_len;
+ gsize length;
+ } GDataInputStreamReadData;
+
+@@ -1078,12 +1079,17 @@ g_data_input_stream_read_async (GDataInputStream *stream,
+ {
+ GDataInputStreamReadData *data;
+ GTask *task;
++ gsize stop_chars_len_unsigned;
+
+ data = g_slice_new0 (GDataInputStreamReadData);
+- if (stop_chars_len == -1)
+- stop_chars_len = strlen (stop_chars);
+- data->stop_chars = g_memdup (stop_chars, stop_chars_len);
+- data->stop_chars_len = stop_chars_len;
++
++ if (stop_chars_len < 0)
++ stop_chars_len_unsigned = strlen (stop_chars);
++ else
++ stop_chars_len_unsigned = (gsize) stop_chars_len;
++
++ data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned);
++ data->stop_chars_len = stop_chars_len_unsigned;
+ data->last_saw_cr = FALSE;
+
+ task = g_task_new (stream, cancellable, callback, user_data);
+@@ -1338,17 +1344,20 @@ g_data_input_stream_read_upto (GDataInputStream *stream,
+ gssize found_pos;
+ gssize res;
+ char *data_until;
++ gsize stop_chars_len_unsigned;
+
+ g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
+
+ if (stop_chars_len < 0)
+- stop_chars_len = strlen (stop_chars);
++ stop_chars_len_unsigned = strlen (stop_chars);
++ else
++ stop_chars_len_unsigned = (gsize) stop_chars_len;
+
+ bstream = G_BUFFERED_INPUT_STREAM (stream);
+
+ checked = 0;
+
+- while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1)
++ while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1)
+ {
+ if (g_buffered_input_stream_get_available (bstream) ==
+ g_buffered_input_stream_get_buffer_size (bstream))
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch
new file mode 100644
index 0000000000..f183939c45
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch
@@ -0,0 +1,76 @@
+From 2aaf593a9eb96d84fe3be740aca2810a97d95592 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:50:37 +0000
+Subject: [PATCH 07/11] gwin32: Use gsize internally in g_wcsdup()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This allows it to handle strings up to length `G_MAXSIZE` — previously
+it would overflow with such strings.
+
+Update the several copies of it identically.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gwin32registrykey.c | 34 ++++++++++++++++++++++++++--------
+ 2 files changed, 38 insertions(+), 16 deletions(-)
+
+diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c
+index 548a94188..2eb67daf8 100644
+--- a/gio/gwin32registrykey.c
++++ b/gio/gwin32registrykey.c
+@@ -127,16 +127,34 @@ typedef enum
+ G_WIN32_REGISTRY_UPDATED_PATH = 1,
+ } GWin32RegistryKeyUpdateFlag;
+
++static gsize
++g_utf16_len (const gunichar2 *str)
++{
++ gsize result;
++
++ for (result = 0; str[0] != 0; str++, result++)
++ ;
++
++ return result;
++}
++
+ static gunichar2 *
+-g_wcsdup (const gunichar2 *str,
+- gssize str_size)
++g_wcsdup (const gunichar2 *str, gssize str_len)
+ {
+- if (str_size == -1)
+- {
+- str_size = wcslen (str) + 1;
+- str_size *= sizeof (gunichar2);
+- }
+- return g_memdup (str, str_size);
++ gsize str_len_unsigned;
++ gsize str_size;
++
++ g_return_val_if_fail (str != NULL, NULL);
++
++ if (str_len < 0)
++ str_len_unsigned = g_utf16_len (str);
++ else
++ str_len_unsigned = (gsize) str_len;
++
++ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
++ str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
++
++ return g_memdup2 (str, str_size);
+ }
+
+ /**
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch
new file mode 100644
index 0000000000..ffafc35c07
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch
@@ -0,0 +1,101 @@
+From ba8ca443051f93a74c0d03d62e70402036f967a5 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 13:58:32 +0000
+Subject: [PATCH 08/11] gkeyfilesettingsbackend: Handle long keys when
+ converting paths
+
+Previously, the code in `convert_path()` could not handle keys longer
+than `G_MAXINT`, and would overflow if that was exceeded.
+
+Convert the code to use `gsize` and `g_memdup2()` throughout, and
+change from identifying the position of the final slash in the string
+using a signed offset `i`, to using a pointer to the character (and
+`strrchr()`). This allows the slash to be at any position in a
+`G_MAXSIZE`-long string, without sacrificing a bit of the offset for
+indicating whether a slash was found.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gkeyfilesettingsbackend.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
+index cd5765afd..25b057672 100644
+--- a/gio/gkeyfilesettingsbackend.c
++++ b/gio/gkeyfilesettingsbackend.c
+@@ -33,6 +33,7 @@
+ #include "gfilemonitor.h"
+ #include "gsimplepermission.h"
+ #include "gsettingsbackendinternal.h"
++#include "gstrfuncsprivate.h"
+ #include "giomodule-priv.h"
+ #include "gportalsupport.h"
+
+@@ -145,8 +146,8 @@ convert_path (GKeyfileSettingsBackend *kfsb,
+ gchar **group,
+ gchar **basename)
+ {
+- gint key_len = strlen (key);
+- gint i;
++ gsize key_len = strlen (key);
++ const gchar *last_slash;
+
+ if (key_len < kfsb->prefix_len ||
+ memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0)
+@@ -155,38 +156,36 @@ convert_path (GKeyfileSettingsBackend *kfsb,
+ key_len -= kfsb->prefix_len;
+ key += kfsb->prefix_len;
+
+- for (i = key_len; i >= 0; i--)
+- if (key[i] == '/')
+- break;
++ last_slash = strrchr (key, '/');
+
+ if (kfsb->root_group)
+ {
+ /* if a root_group was specified, make sure the user hasn't given
+ * a path that ghosts that group name
+ */
+- if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0)
++ if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0)
+ return FALSE;
+ }
+ else
+ {
+ /* if no root_group was given, ensure that the user gave a path */
+- if (i == -1)
++ if (last_slash == NULL)
+ return FALSE;
+ }
+
+ if (group)
+ {
+- if (i >= 0)
++ if (last_slash != NULL)
+ {
+- *group = g_memdup (key, i + 1);
+- (*group)[i] = '\0';
++ *group = g_memdup2 (key, (last_slash - key) + 1);
++ (*group)[(last_slash - key)] = '\0';
+ }
+ else
+ *group = g_strdup (kfsb->root_group);
+ }
+
+ if (basename)
+- *basename = g_memdup (key + i + 1, key_len - i);
++ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
+
+ return TRUE;
+ }
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch
new file mode 100644
index 0000000000..8efb7c720f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch
@@ -0,0 +1,100 @@
+From 65ec7f4d6e8832c481f6e00e2eb007b9a60024ce Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 14:00:53 +0000
+Subject: [PATCH 09/11] =?UTF-8?q?gsocket:=20Use=20gsize=20to=20track=20nat?=
+ =?UTF-8?q?ive=20sockaddr=E2=80=99s=20size?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Don’t use an `int`, that’s potentially too small. In practical terms,
+this is not a problem, since no socket address is going to be that big.
+
+By making these changes we can use `g_memdup2()` without warnings,
+though. Fewer warnings is good.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gsocket.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/gio/gsocket.c
++++ b/gio/gsocket.c
+@@ -75,6 +75,7 @@
+ #include "gcredentialsprivate.h"
+ #include "glibintl.h"
+ #include "gioprivate.h"
++#include "gstrfuncsprivate.h"
+
+ #ifdef G_OS_WIN32
+ /* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */
+@@ -174,7 +175,7 @@ static gboolean g_socket_datagram_ba
+ GError **error);
+
+ static GSocketAddress *
+-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len);
++cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len);
+
+ static gssize
+ g_socket_receive_message_with_timeout (GSocket *socket,
+@@ -260,7 +261,7 @@ struct _GSocketPrivate
+ struct {
+ GSocketAddress *addr;
+ struct sockaddr *native;
+- gint native_len;
++ gsize native_len;
+ guint64 last_used;
+ } recv_addr_cache[RECV_ADDR_CACHE_SIZE];
+ };
+@@ -5259,14 +5260,14 @@ g_socket_send_messages_with_timeout (GSo
+ }
+
+ static GSocketAddress *
+-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len)
++cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len)
+ {
+ GSocketAddress *saddr;
+ gint i;
+ guint64 oldest_time = G_MAXUINT64;
+ gint oldest_index = 0;
+
+- if (native_len <= 0)
++ if (native_len == 0)
+ return NULL;
+
+ saddr = NULL;
+@@ -5274,7 +5275,7 @@ cache_recv_address (GSocket *socket, str
+ {
+ GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr;
+ gpointer tmp_native = socket->priv->recv_addr_cache[i].native;
+- gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
++ gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
+
+ if (!tmp)
+ continue;
+@@ -5304,7 +5305,7 @@ cache_recv_address (GSocket *socket, str
+ g_free (socket->priv->recv_addr_cache[oldest_index].native);
+ }
+
+- socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len);
++ socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len);
+ socket->priv->recv_addr_cache[oldest_index].native_len = native_len;
+ socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr);
+ socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time ();
+@@ -5452,6 +5453,9 @@ g_socket_receive_message_with_timeout (G
+ /* do it */
+ while (1)
+ {
++ /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */
++ G_STATIC_ASSERT (sizeof addr <= G_MAXINT);
++
+ addrlen = sizeof addr;
+ if (address)
+ result = WSARecvFrom (socket->priv->fd,
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch
new file mode 100644
index 0000000000..63fda0b600
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch
@@ -0,0 +1,59 @@
+From 777b95a88f006d39d9fe6d3321db17e7b0d4b9a4 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 14:07:39 +0000
+Subject: [PATCH 10/11] gtlspassword: Forbid very long TLS passwords
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The public API `g_tls_password_set_value_full()` (and the vfunc it
+invokes) can only accept a `gssize` length. Ensure that nul-terminated
+strings passed to `g_tls_password_set_value()` can’t exceed that length.
+Use `g_memdup2()` to avoid an overflow if they’re longer than
+`G_MAXUINT` similarly.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gtlspassword.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c
+index 1e437a7b6..dbcec41a8 100644
+--- a/gio/gtlspassword.c
++++ b/gio/gtlspassword.c
+@@ -23,6 +23,7 @@
+ #include "glibintl.h"
+
+ #include "gioenumtypes.h"
++#include "gstrfuncsprivate.h"
+ #include "gtlspassword.h"
+
+ #include <string.h>
+@@ -287,9 +288,14 @@ g_tls_password_set_value (GTlsPassword *password,
+ g_return_if_fail (G_IS_TLS_PASSWORD (password));
+
+ if (length < 0)
+- length = strlen ((gchar *)value);
++ {
++ /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
++ gsize length_unsigned = strlen ((gchar *) value);
++ g_return_if_fail (length_unsigned > G_MAXSSIZE);
++ length = (gssize) length_unsigned;
++ }
+
+- g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free);
++ g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
+ }
+
+ /**
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch
new file mode 100644
index 0000000000..a620a49269
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch
@@ -0,0 +1,63 @@
+From ecdf91400e9a538695a0895b95ad7e8abcdf1749 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 4 Feb 2021 14:09:40 +0000
+Subject: [PATCH 11/11] giochannel: Forbid very long line terminator strings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The public API `GIOChannel.line_term_len` is only a `guint`. Ensure that
+nul-terminated strings passed to `g_io_channel_set_line_term()` can’t
+exceed that length. Use `g_memdup2()` to avoid a warning (`g_memdup()`
+is due to be deprecated), but not to avoid a bug, since it’s also
+limited to `G_MAXUINT`.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+Helps: #2319
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ glib/giochannel.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/glib/giochannel.c b/glib/giochannel.c
+index c6a89d6e0..4dec20f77 100644
+--- a/glib/giochannel.c
++++ b/glib/giochannel.c
+@@ -887,16 +887,25 @@ g_io_channel_set_line_term (GIOChannel *channel,
+ const gchar *line_term,
+ gint length)
+ {
++ guint length_unsigned;
++
+ g_return_if_fail (channel != NULL);
+ g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
+
+ if (line_term == NULL)
+- length = 0;
+- else if (length < 0)
+- length = strlen (line_term);
++ length_unsigned = 0;
++ else if (length >= 0)
++ length_unsigned = (guint) length;
++ else
++ {
++ /* FIXME: We’re constrained by line_term_len being a guint here */
++ gsize length_size = strlen (line_term);
++ g_return_if_fail (length_size > G_MAXUINT);
++ length_unsigned = (guint) length_size;
++ }
+
+ g_free (channel->line_term);
+- channel->line_term = line_term ? g_memdup (line_term, length) : NULL;
++ channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
+ channel->line_term_len = length;
+ }
+
+--
+GitLab
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch
new file mode 100644
index 0000000000..3047062f54
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch
@@ -0,0 +1,36 @@
+From f8273b9aded135fe07094faebd527e43851aaf6e Mon Sep 17 00:00:00 2001
+From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
+Date: Sun, 7 Feb 2021 23:32:40 +0100
+Subject: [PATCH 1/5] giochannel: Fix length_size bounds check
+
+The inverted condition is an obvious error introduced by ecdf91400e9a.
+
+Fixes https://gitlab.gnome.org/GNOME/glib/-/issues/2323
+
+(cherry picked from commit a149bf2f9030168051942124536e303af8ba6176)
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ glib/giochannel.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/glib/giochannel.c b/glib/giochannel.c
+index 4dec20f77..c3f3102ff 100644
+--- a/glib/giochannel.c
++++ b/glib/giochannel.c
+@@ -896,7 +896,7 @@ g_io_channel_set_line_term (GIOChannel *channel,
+ {
+ /* FIXME: We’re constrained by line_term_len being a guint here */
+ gsize length_size = strlen (line_term);
+- g_return_if_fail (length_size > G_MAXUINT);
++ g_return_if_fail (length_size <= G_MAXUINT);
+ length_unsigned = (guint) length_size;
+ }
+
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch
new file mode 100644
index 0000000000..2ba26075df
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch
@@ -0,0 +1,38 @@
+From e069c50467712e6d607822afd6b6c15c2c343dff Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@collabora.com>
+Date: Mon, 8 Feb 2021 10:34:50 +0000
+Subject: [PATCH 2/5] giochannel: Don't store negative line_term_len in
+ GIOChannel struct
+
+Adding test coverage indicated that this was another bug in 0cc11f74.
+
+Fixes: 0cc11f74 "giochannel: Forbid very long line terminator strings"
+Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2323
+Signed-off-by: Simon McVittie <smcv@collabora.com>
+(cherry picked from commit 5dc8b0014c03e7491d93b90275ab442e888a9628)
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ glib/giochannel.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/glib/giochannel.c b/glib/giochannel.c
+index c3f3102ff..19bb06ba6 100644
+--- a/glib/giochannel.c
++++ b/glib/giochannel.c
+@@ -902,7 +902,7 @@ g_io_channel_set_line_term (GIOChannel *channel,
+
+ g_free (channel->line_term);
+ channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
+- channel->line_term_len = length;
++ channel->line_term_len = length_unsigned;
+ }
+
+ /**
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch
new file mode 100644
index 0000000000..2c388b4bbb
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch
@@ -0,0 +1,38 @@
+From 4506d1859a863087598c8d122740bae25b65b099 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@collabora.com>
+Date: Mon, 8 Feb 2021 10:04:48 +0000
+Subject: [PATCH 4/5] gtlspassword: Fix inverted assertion
+
+The intention here was to assert that the length of the password fits
+in a gssize. Passwords more than half the size of virtual memory are
+probably excessive.
+
+Fixes: a8b204ff "gtlspassword: Forbid very long TLS passwords"
+Signed-off-by: Simon McVittie <smcv@collabora.com>
+(cherry picked from commit 61bb52ec42de1082bfb06ce1c737fc295bfe60b8)
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gtlspassword.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c
+index dbcec41a8..bd86a6dfe 100644
+--- a/gio/gtlspassword.c
++++ b/gio/gtlspassword.c
+@@ -291,7 +291,7 @@ g_tls_password_set_value (GTlsPassword *password,
+ {
+ /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
+ gsize length_unsigned = strlen ((gchar *) value);
+- g_return_if_fail (length_unsigned > G_MAXSSIZE);
++ g_return_if_fail (length_unsigned <= G_MAXSSIZE);
+ length = (gssize) length_unsigned;
+ }
+
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch
new file mode 100644
index 0000000000..356e986fe0
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch
@@ -0,0 +1,100 @@
+From 3d1550354c3c6a8491c39881752d51cb7515f2c2 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@collabora.com>
+Date: Mon, 8 Feb 2021 10:22:39 +0000
+Subject: [PATCH 5/5] tls-interaction: Add test coverage for various ways to
+ set the password
+
+Signed-off-by: Simon McVittie <smcv@collabora.com>
+(cherry picked from commit df4501316ca3903072400504a5ea76498db19538)
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/tests/tls-interaction.c | 55 +++++++++++++++++++++++++++++++++++++
+ 1 file changed, 55 insertions(+)
+
+diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c
+index 4f0737d7e..5661e8e0d 100644
+--- a/gio/tests/tls-interaction.c
++++ b/gio/tests/tls-interaction.c
+@@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction,
+ }
+
+
++/* Return a copy of @str that is allocated in a silly way, to exercise
++ * custom free-functions. The returned pointer points to a copy of @str
++ * in a buffer of the form "BEFORE \0 str \0 AFTER". */
++static guchar *
++special_dup (const char *str)
++{
++ GString *buf = g_string_new ("BEFORE");
++ guchar *ret;
++
++ g_string_append_c (buf, '\0');
++ g_string_append (buf, str);
++ g_string_append_c (buf, '\0');
++ g_string_append (buf, "AFTER");
++ ret = (guchar *) g_string_free (buf, FALSE);
++ return ret + strlen ("BEFORE") + 1;
++}
++
++
++/* Free a copy of @str that was made with special_dup(), after asserting
++ * that it has not been corrupted. */
++static void
++special_free (gpointer p)
++{
++ gchar *s = p;
++ gchar *buf = s - strlen ("BEFORE") - 1;
++
++ g_assert_cmpstr (buf, ==, "BEFORE");
++ g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER");
++ g_free (buf);
++}
++
++
+ static GTlsInteractionResult
+ test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
+ GTlsPassword *password,
+@@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
+ GError **error)
+ {
+ TestInteraction *self;
++ const guchar *value;
++ gsize len;
+
+ g_assert (TEST_IS_INTERACTION (interaction));
+ self = TEST_INTERACTION (interaction);
+@@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
+ g_assert (error != NULL);
+ g_assert (*error == NULL);
+
++ /* Exercise different ways to set the value */
++ g_tls_password_set_value (password, (const guchar *) "foo", 4);
++ len = 0;
++ value = g_tls_password_get_value (password, &len);
++ g_assert_cmpmem (value, len, "foo", 4);
++
++ g_tls_password_set_value (password, (const guchar *) "bar", -1);
++ len = 0;
++ value = g_tls_password_get_value (password, &len);
++ g_assert_cmpmem (value, len, "bar", 3);
++
++ g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free);
++ len = 0;
++ value = g_tls_password_get_value (password, &len);
++ g_assert_cmpmem (value, len, "baa", 4);
++
++ g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free);
++ len = 0;
++ value = g_tls_password_get_value (password, &len);
++ g_assert_cmpmem (value, len, "baz", 3);
++
+ /* Don't do this in real life. Include a null terminator for testing */
+ g_tls_password_set_value (password, (const guchar *)"the password", 13);
+ return G_TLS_INTERACTION_HANDLED;
+--
+GitLab
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch
new file mode 100644
index 0000000000..dd43689aae
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch
@@ -0,0 +1,49 @@
+From cb9ee701ef46c1819eed4e2a4dc181682bdfc176 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 10 Feb 2021 21:16:39 +0000
+Subject: [PATCH 1/3] gkeyfilesettingsbackend: Fix basename handling when group
+ is unset
+
+Fix an effective regression in commit
+7781a9cbd2fd0aa84bee0f4eee88470640ff6706, which happens when
+`convert_path()` is called with a `key` which contains no slashes. In
+that case, the `key` is entirely the `basename`.
+
+Prior to commit 7781a9cb, the code worked through a fluke of `i == -1`
+cancelling out with the various additions in the `g_memdup()` call, and
+effectively resulting in `g_strdup (key)`.
+
+Spotted by Guido Berhoerster.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gkeyfilesettingsbackend.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
+index 25b057672..861c3a661 100644
+--- a/gio/gkeyfilesettingsbackend.c
++++ b/gio/gkeyfilesettingsbackend.c
+@@ -185,7 +185,12 @@ convert_path (GKeyfileSettingsBackend *kfsb,
+ }
+
+ if (basename)
+- *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
++ {
++ if (last_slash != NULL)
++ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
++ else
++ *basename = g_strdup (key);
++ }
+
+ return TRUE;
+ }
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch
new file mode 100644
index 0000000000..04503641c3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch
@@ -0,0 +1,43 @@
+From 31e0d403ba635dbbacbfbff74295e5db02558d76 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 10 Feb 2021 21:19:30 +0000
+Subject: [PATCH 2/3] gkeyfilesettingsbackend: Disallow empty key or group
+ names
+
+These should never have been allowed; they will result in precondition
+failures from the `GKeyFile` later on in the code.
+
+A test will be added for this shortly.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/gkeyfilesettingsbackend.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
+index 861c3a661..de216e615 100644
+--- a/gio/gkeyfilesettingsbackend.c
++++ b/gio/gkeyfilesettingsbackend.c
+@@ -158,6 +158,13 @@ convert_path (GKeyfileSettingsBackend *kfsb,
+
+ last_slash = strrchr (key, '/');
+
++ /* Disallow empty group names or key names */
++ if (key_len == 0 ||
++ (last_slash != NULL &&
++ (*(last_slash + 1) == '\0' ||
++ last_slash == key)))
++ return FALSE;
++
+ if (kfsb->root_group)
+ {
+ /* if a root_group was specified, make sure the user hasn't given
+--
+GitLab
+
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch
new file mode 100644
index 0000000000..65f59287a8
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch
@@ -0,0 +1,232 @@
+Backport of:
+
+From 221c26685354dea2b2732df94404e8e5e77a1591 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 10 Feb 2021 21:21:36 +0000
+Subject: [PATCH 3/3] tests: Add tests for key name handling in the keyfile
+ backend
+
+This tests the two recent commits.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-27219
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/tests/gsettings.c | 170 +++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 169 insertions(+), 1 deletion(-)
+
+--- a/gio/tests/gsettings.c
++++ b/gio/tests/gsettings.c
+@@ -1,3 +1,4 @@
++#include <errno.h>
+ #include <stdlib.h>
+ #include <locale.h>
+ #include <libintl.h>
+@@ -1740,6 +1741,14 @@ key_changed_cb (GSettings *settings, con
+ (*b) = TRUE;
+ }
+
++typedef struct
++{
++ const gchar *path;
++ const gchar *root_group;
++ const gchar *keyfile_group;
++ const gchar *root_path;
++} KeyfileTestData;
++
+ /*
+ * Test that using a keyfile works
+ */
+@@ -1834,7 +1843,11 @@ test_keyfile (Fixture *fixture,
+ g_free (str);
+
+ g_settings_set (settings, "farewell", "s", "cheerio");
+-
++
++ /* Check that empty keys/groups are not allowed. */
++ g_assert_false (g_settings_is_writable (settings, ""));
++ g_assert_false (g_settings_is_writable (settings, "/"));
++
+ /* When executing as root, changing the mode of the keyfile will have
+ * no effect on the writability of the settings.
+ */
+@@ -1866,6 +1879,149 @@ test_keyfile (Fixture *fixture,
+ g_free (keyfile_path);
+ }
+
++/*
++ * Test that using a keyfile works with a schema with no path set.
++ */
++static void
++test_keyfile_no_path (Fixture *fixture,
++ gconstpointer user_data)
++{
++ const KeyfileTestData *test_data = user_data;
++ GSettingsBackend *kf_backend;
++ GSettings *settings;
++ GKeyFile *keyfile;
++ gboolean writable;
++ gchar *key = NULL;
++ GError *error = NULL;
++ gchar *keyfile_path = NULL, *store_path = NULL;
++
++ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
++ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
++ kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group);
++ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path);
++ g_object_unref (kf_backend);
++
++ g_settings_reset (settings, "test-boolean");
++ g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
++
++ writable = g_settings_is_writable (settings, "test-boolean");
++ g_assert_true (writable);
++ g_settings_set (settings, "test-boolean", "b", FALSE);
++
++ g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
++
++ g_settings_delay (settings);
++ g_settings_set (settings, "test-boolean", "b", TRUE);
++ g_settings_apply (settings);
++
++ keyfile = g_key_file_new ();
++ g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
++
++ g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL));
++
++ g_key_file_free (keyfile);
++
++ g_settings_reset (settings, "test-boolean");
++ g_settings_apply (settings);
++ keyfile = g_key_file_new ();
++ g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
++
++ g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error));
++ g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
++ g_clear_error (&error);
++
++ /* Check that empty keys/groups are not allowed. */
++ g_assert_false (g_settings_is_writable (settings, ""));
++ g_assert_false (g_settings_is_writable (settings, "/"));
++
++ /* Keys which ghost the root group name are not allowed. This can only be
++ * tested when the path is `/` as otherwise it acts as a prefix and prevents
++ * any ghosting. */
++ if (g_str_equal (test_data->path, "/"))
++ {
++ key = g_strdup_printf ("%s/%s", test_data->root_group, "");
++ g_assert_false (g_settings_is_writable (settings, key));
++ g_free (key);
++
++ key = g_strdup_printf ("%s/%s", test_data->root_group, "/");
++ g_assert_false (g_settings_is_writable (settings, key));
++ g_free (key);
++
++ key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean");
++ g_assert_false (g_settings_is_writable (settings, key));
++ g_free (key);
++ }
++
++ g_key_file_free (keyfile);
++ g_object_unref (settings);
++
++ /* Clean up the temporary directory. */
++ g_assert_cmpint (g_chmod (keyfile_path, 0777) == 0 ? 0 : errno, ==, 0);
++ g_assert_cmpint (g_remove (store_path) == 0 ? 0 : errno, ==, 0);
++ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0);
++ g_free (store_path);
++ g_free (keyfile_path);
++}
++
++/*
++ * Test that a keyfile rejects writes to keys outside its root path.
++ */
++static void
++test_keyfile_outside_root_path (Fixture *fixture,
++ gconstpointer user_data)
++{
++ GSettingsBackend *kf_backend;
++ GSettings *settings;
++ gchar *keyfile_path = NULL, *store_path = NULL;
++
++ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
++ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
++ kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root");
++ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/");
++ g_object_unref (kf_backend);
++
++ g_assert_false (g_settings_is_writable (settings, "test-boolean"));
++
++ g_object_unref (settings);
++
++ /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
++ * don’t error on failure. */
++ g_remove (store_path);
++ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0);
++ g_free (store_path);
++ g_free (keyfile_path);
++}
++
++/*
++ * Test that a keyfile rejects writes to keys in the root if no root group is set.
++ */
++static void
++test_keyfile_no_root_group (Fixture *fixture,
++ gconstpointer user_data)
++{
++ GSettingsBackend *kf_backend;
++ GSettings *settings;
++ gchar *keyfile_path = NULL, *store_path = NULL;
++
++ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
++ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
++ kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL);
++ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/");
++ g_object_unref (kf_backend);
++
++ g_assert_false (g_settings_is_writable (settings, "test-boolean"));
++ g_assert_true (g_settings_is_writable (settings, "child/test-boolean"));
++
++ g_object_unref (settings);
++
++ /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
++ * don’t error on failure. */
++ g_remove (store_path);
++ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0);
++ g_free (store_path);
++ g_free (keyfile_path);
++}
++
+ /* Test that getting child schemas works
+ */
+ static void
+@@ -2844,6 +3000,14 @@ main (int argc, char *argv[])
+ gchar *override_text;
+ gchar *enums;
+ gint result;
++ const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" };
++ const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" };
++ const KeyfileTestData keyfile_test_data_long_path = {
++ "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/",
++ "root",
++ "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch",
++ "/"
++ };
+
+ /* Meson build sets this */
+ #ifdef TEST_LOCALE_PATH
+@@ -2967,6 +3131,11 @@ main (int argc, char *argv[])
+ }
+
+ g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown);
++ g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown);
++ g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown);
++ g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown);
++ g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown);
++ g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown);
+ g_test_add_func ("/gsettings/child-schema", test_child_schema);
+ g_test_add_func ("/gsettings/strinfo", test_strinfo);
+ g_test_add_func ("/gsettings/enums", test_enums);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch
new file mode 100644
index 0000000000..c89ca20726
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch
@@ -0,0 +1,27 @@
+From 78420a75aeb70569a8cd79fa0fea7b786b6f785f Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 24 Feb 2021 17:33:38 +0000
+Subject: [PATCH 1/5] glocalfileoutputstream: Fix a typo in a comment
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-28153
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/glocalfileoutputstream.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/gio/glocalfileoutputstream.c
++++ b/gio/glocalfileoutputstream.c
+@@ -851,7 +851,7 @@ handle_overwrite_open (const char *fi
+ mode = mode_from_flags_or_info (flags, reference_info);
+
+ /* We only need read access to the original file if we are creating a backup.
+- * We also add O_CREATE to avoid a race if the file was just removed */
++ * We also add O_CREAT to avoid a race if the file was just removed */
+ if (create_backup || readable)
+ open_flags = O_RDWR | O_CREAT | O_BINARY;
+ else
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch
new file mode 100644
index 0000000000..8a35bab4de
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch
@@ -0,0 +1,42 @@
+From 32d3d02a50e7dcec5f4cf7908e7ac88d575d8fc5 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 24 Feb 2021 17:34:32 +0000
+Subject: [PATCH 2/5] tests: Stop using g_test_bug_base() in file tests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Since a following commit is going to add a new test which references
+Gitlab, so it’s best to move the URI bases inside the test cases.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-28153
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/tests/file.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/gio/tests/file.c
++++ b/gio/tests/file.c
+@@ -685,7 +685,7 @@ test_replace_cancel (void)
+ guint count;
+ GError *error = NULL;
+
+- g_test_bug ("629301");
++ g_test_bug ("https://bugzilla.gnome.org/629301");
+
+ path = g_dir_make_tmp ("g_file_replace_cancel_XXXXXX", &error);
+ g_assert_no_error (error);
+@@ -1784,8 +1784,6 @@ main (int argc, char *argv[])
+ {
+ g_test_init (&argc, &argv, NULL);
+
+- g_test_bug_base ("http://bugzilla.gnome.org/");
+-
+ g_test_add_func ("/file/basic", test_basic);
+ g_test_add_func ("/file/build-filename", test_build_filename);
+ g_test_add_func ("/file/parent", test_parent);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch
new file mode 100644
index 0000000000..a82febd26e
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch
@@ -0,0 +1,57 @@
+Backport of:
+
+From ce0eb088a68171eed3ac217cb92a72e36eb57d1b Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 10 Mar 2021 16:05:55 +0000
+Subject: [PATCH 3/5] glocalfileoutputstream: Factor out a flag check
+
+This clarifies the code a little. It introduces no functional changes.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-28153
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/glocalfileoutputstream.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/gio/glocalfileoutputstream.c
++++ b/gio/glocalfileoutputstream.c
+@@ -847,6 +847,7 @@ handle_overwrite_open (const char *fi
+ int res;
+ int mode;
+ int errsv;
++ gboolean replace_destination_set = (flags & G_FILE_CREATE_REPLACE_DESTINATION);
+
+ mode = mode_from_flags_or_info (flags, reference_info);
+
+@@ -954,7 +955,7 @@ handle_overwrite_open (const char *fi
+ * to a backup file and rewrite the contents of the file.
+ */
+
+- if ((flags & G_FILE_CREATE_REPLACE_DESTINATION) ||
++ if (replace_destination_set ||
+ (!(original_stat.st_nlink > 1) && !is_symlink))
+ {
+ char *dirname, *tmp_filename;
+@@ -973,7 +974,7 @@ handle_overwrite_open (const char *fi
+
+ /* try to keep permissions (unless replacing) */
+
+- if ( ! (flags & G_FILE_CREATE_REPLACE_DESTINATION) &&
++ if (!replace_destination_set &&
+ (
+ #ifdef HAVE_FCHOWN
+ fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 ||
+@@ -1112,7 +1113,7 @@ handle_overwrite_open (const char *fi
+ }
+ }
+
+- if (flags & G_FILE_CREATE_REPLACE_DESTINATION)
++ if (replace_destination_set)
+ {
+ g_close (fd, NULL);
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch
new file mode 100644
index 0000000000..5b106e8474
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch
@@ -0,0 +1,265 @@
+Backport of:
+
+From 317b3b587058a05dca95d56dac26568c5b098d33 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 24 Feb 2021 17:36:07 +0000
+Subject: [PATCH 4/5] glocalfileoutputstream: Fix CREATE_REPLACE_DESTINATION
+ with symlinks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The `G_FILE_CREATE_REPLACE_DESTINATION` flag is equivalent to unlinking
+the destination file and re-creating it from scratch. That did
+previously work, but in the process the code would call `open(O_CREAT)`
+on the file. If the file was a dangling symlink, this would create the
+destination file (empty). That’s not an intended side-effect, and has
+security implications if the symlink is controlled by a lower-privileged
+process.
+
+Fix that by not opening the destination file if it’s a symlink, and
+adjusting the rest of the code to cope with
+ - the fact that `fd == -1` is not an error iff `is_symlink` is true,
+ - and that `original_stat` will contain the `lstat()` results for the
+ symlink now, rather than the `stat()` results for its target (again,
+ iff `is_symlink` is true).
+
+This means that the target of the dangling symlink is no longer created,
+which was the bug. The symlink itself continues to be replaced (as
+before) with the new file — this is the intended behaviour of
+`g_file_replace()`.
+
+The behaviour for non-symlink cases, or cases where the symlink was not
+dangling, should be unchanged.
+
+Includes a unit test.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Fixes: #2325
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-28153
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/glocalfileoutputstream.c | 77 ++++++++++++++++++-------
+ gio/tests/file.c | 108 +++++++++++++++++++++++++++++++++++
+ 2 files changed, 163 insertions(+), 22 deletions(-)
+
+--- a/gio/glocalfileoutputstream.c
++++ b/gio/glocalfileoutputstream.c
+@@ -875,16 +875,22 @@ handle_overwrite_open (const char *fi
+ /* Could be a symlink, or it could be a regular ELOOP error,
+ * but then the next open will fail too. */
+ is_symlink = TRUE;
+- fd = g_open (filename, open_flags, mode);
++ if (!replace_destination_set)
++ fd = g_open (filename, open_flags, mode);
+ }
+-#else
+- fd = g_open (filename, open_flags, mode);
+- errsv = errno;
++#else /* if !O_NOFOLLOW */
+ /* This is racy, but we do it as soon as possible to minimize the race */
+ is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK);
++
++ if (!is_symlink || !replace_destination_set)
++ {
++ fd = g_open (filename, open_flags, mode);
++ errsv = errno;
++ }
+ #endif
+
+- if (fd == -1)
++ if (fd == -1 &&
++ (!is_symlink || !replace_destination_set))
+ {
+ char *display_name = g_filename_display_name (filename);
+ g_set_error (error, G_IO_ERROR,
+@@ -898,7 +904,14 @@ handle_overwrite_open (const char *fi
+ #ifdef G_OS_WIN32
+ res = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &original_stat);
+ #else
+- res = fstat (fd, &original_stat);
++ if (!is_symlink)
++ {
++ res = fstat (fd, &original_stat);
++ }
++ else
++ {
++ res = lstat (filename, &original_stat);
++ }
+ #endif
+ errsv = errno;
+
+@@ -917,16 +930,27 @@ handle_overwrite_open (const char *fi
+ if (!S_ISREG (original_stat.st_mode))
+ {
+ if (S_ISDIR (original_stat.st_mode))
+- g_set_error_literal (error,
+- G_IO_ERROR,
+- G_IO_ERROR_IS_DIRECTORY,
+- _("Target file is a directory"));
+- else
+- g_set_error_literal (error,
++ {
++ g_set_error_literal (error,
++ G_IO_ERROR,
++ G_IO_ERROR_IS_DIRECTORY,
++ _("Target file is a directory"));
++ goto err_out;
++ }
++ else if (!is_symlink ||
++#ifdef S_ISLNK
++ !S_ISLNK (original_stat.st_mode)
++#else
++ FALSE
++#endif
++ )
++ {
++ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_REGULAR_FILE,
+ _("Target file is not a regular file"));
+- goto err_out;
++ goto err_out;
++ }
+ }
+
+ if (etag != NULL)
+@@ -1007,7 +1031,8 @@ handle_overwrite_open (const char *fi
+ }
+ }
+
+- g_close (fd, NULL);
++ if (fd >= 0)
++ g_close (fd, NULL);
+ *temp_filename = tmp_filename;
+ return tmpfd;
+ }
+--- a/gio/tests/file.c
++++ b/gio/tests/file.c
+@@ -804,6 +804,113 @@ test_replace_cancel (void)
+ g_object_unref (tmpdir);
+ }
+
++static void
++test_replace_symlink (void)
++{
++#ifdef G_OS_UNIX
++ gchar *tmpdir_path = NULL;
++ GFile *tmpdir = NULL, *source_file = NULL, *target_file = NULL;
++ GFileOutputStream *stream = NULL;
++ const gchar *new_contents = "this is a test message which should be written to source and not target";
++ gsize n_written;
++ GFileEnumerator *enumerator = NULL;
++ GFileInfo *info = NULL;
++ gchar *contents = NULL;
++ gsize length = 0;
++ GError *local_error = NULL;
++
++ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2325");
++ g_test_summary ("Test that G_FILE_CREATE_REPLACE_DESTINATION doesn’t follow symlinks");
++
++ /* Create a fresh, empty working directory. */
++ tmpdir_path = g_dir_make_tmp ("g_file_replace_symlink_XXXXXX", &local_error);
++ g_assert_no_error (local_error);
++ tmpdir = g_file_new_for_path (tmpdir_path);
++
++ g_test_message ("Using temporary directory %s", tmpdir_path);
++ g_free (tmpdir_path);
++
++ /* Create symlink `source` which points to `target`. */
++ source_file = g_file_get_child (tmpdir, "source");
++ target_file = g_file_get_child (tmpdir, "target");
++ g_file_make_symbolic_link (source_file, "target", NULL, &local_error);
++ g_assert_no_error (local_error);
++
++ /* Ensure that `target` doesn’t exist */
++ g_assert_false (g_file_query_exists (target_file, NULL));
++
++ /* Replace the `source` symlink with a regular file using
++ * %G_FILE_CREATE_REPLACE_DESTINATION, which should replace it *without*
++ * following the symlink */
++ stream = g_file_replace (source_file, NULL, FALSE /* no backup */,
++ G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error);
++ g_assert_no_error (local_error);
++
++ g_output_stream_write_all (G_OUTPUT_STREAM (stream), new_contents, strlen (new_contents),
++ &n_written, NULL, &local_error);
++ g_assert_no_error (local_error);
++ g_assert_cmpint (n_written, ==, strlen (new_contents));
++
++ g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, &local_error);
++ g_assert_no_error (local_error);
++
++ g_clear_object (&stream);
++
++ /* At this point, there should still only be one file: `source`. It should
++ * now be a regular file. `target` should not exist. */
++ enumerator = g_file_enumerate_children (tmpdir,
++ G_FILE_ATTRIBUTE_STANDARD_NAME ","
++ G_FILE_ATTRIBUTE_STANDARD_TYPE,
++ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
++ g_assert_no_error (local_error);
++
++ info = g_file_enumerator_next_file (enumerator, NULL, &local_error);
++ g_assert_no_error (local_error);
++ g_assert_nonnull (info);
++
++ g_assert_cmpstr (g_file_info_get_name (info), ==, "source");
++ g_assert_cmpint (g_file_info_get_file_type (info), ==, G_FILE_TYPE_REGULAR);
++
++ g_clear_object (&info);
++
++ info = g_file_enumerator_next_file (enumerator, NULL, &local_error);
++ g_assert_no_error (local_error);
++ g_assert_null (info);
++
++ g_file_enumerator_close (enumerator, NULL, &local_error);
++ g_assert_no_error (local_error);
++ g_clear_object (&enumerator);
++
++ /* Double-check that `target` doesn’t exist */
++ g_assert_false (g_file_query_exists (target_file, NULL));
++
++ /* Check the content of `source`. */
++ g_file_load_contents (source_file,
++ NULL,
++ &contents,
++ &length,
++ NULL,
++ &local_error);
++ g_assert_no_error (local_error);
++ g_assert_cmpstr (contents, ==, new_contents);
++ g_assert_cmpuint (length, ==, strlen (new_contents));
++ g_free (contents);
++
++ /* Tidy up. */
++ g_file_delete (source_file, NULL, &local_error);
++ g_assert_no_error (local_error);
++
++ g_file_delete (tmpdir, NULL, &local_error);
++ g_assert_no_error (local_error);
++
++ g_clear_object (&target_file);
++ g_clear_object (&source_file);
++ g_clear_object (&tmpdir);
++#else /* if !G_OS_UNIX */
++ g_test_skip ("Symlink replacement tests can only be run on Unix")
++#endif
++}
++
+ static void
+ on_file_deleted (GObject *object,
+ GAsyncResult *result,
+@@ -1752,6 +1859,7 @@ main (int argc, char *argv[])
+ g_test_add_data_func ("/file/async-create-delete/4096", GINT_TO_POINTER (4096), test_create_delete);
+ g_test_add_func ("/file/replace-load", test_replace_load);
+ g_test_add_func ("/file/replace-cancel", test_replace_cancel);
++ g_test_add_func ("/file/replace-symlink", test_replace_symlink);
+ g_test_add_func ("/file/async-delete", test_async_delete);
+ #ifdef G_OS_UNIX
+ g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch
new file mode 100644
index 0000000000..2334147f7d
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch
@@ -0,0 +1,55 @@
+From 6c6439261bc7a8a0627519848a7222b3e1bd4ffe Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 24 Feb 2021 17:42:24 +0000
+Subject: [PATCH 5/5] glocalfileoutputstream: Add a missing O_CLOEXEC flag to
+ replace()
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
+CVE: CVE-2021-28153
+Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ gio/glocalfileoutputstream.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/gio/glocalfileoutputstream.c
++++ b/gio/glocalfileoutputstream.c
+@@ -58,6 +58,12 @@
+ #define O_BINARY 0
+ #endif
+
++#ifndef O_CLOEXEC
++#define O_CLOEXEC 0
++#else
++#define HAVE_O_CLOEXEC 1
++#endif
++
+ struct _GLocalFileOutputStreamPrivate {
+ char *tmp_filename;
+ char *original_filename;
+@@ -1223,7 +1229,7 @@ _g_local_file_output_stream_replace (con
+ sync_on_close = FALSE;
+
+ /* If the file doesn't exist, create it */
+- open_flags = O_CREAT | O_EXCL | O_BINARY;
++ open_flags = O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC;
+ if (readable)
+ open_flags |= O_RDWR;
+ else
+@@ -1253,8 +1259,11 @@ _g_local_file_output_stream_replace (con
+ set_error_from_open_errno (filename, error);
+ return NULL;
+ }
+-
+-
++#if !defined(HAVE_O_CLOEXEC) && defined(F_SETFD)
++ else
++ fcntl (fd, F_SETFD, FD_CLOEXEC);
++#endif
++
+ stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
+ stream->priv->fd = fd;
+ stream->priv->sync_on_close = sync_on_close;
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch
new file mode 100644
index 0000000000..ce90586290
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch
@@ -0,0 +1,290 @@
+From 5f4485c4ff57fdefb1661531788def7ca5a47328 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 17 Aug 2023 04:19:44 +0000
+Subject: [PATCH] gvariant-serialiser: Check offset table entry size is minimal
+
+The entries in an offset table (which is used for variable sized arrays
+and tuples containing variable sized members) are sized so that they can
+address every byte in the overall variant.
+
+The specification requires that for a variant to be in normal form, its
+offset table entries must be the minimum width such that they can
+address every byte in the variant.
+
+That minimality requirement was not checked in
+`g_variant_is_normal_form()`, leading to two different byte arrays being
+interpreted as the normal form of a given variant tree. That kind of
+confusion could potentially be exploited, and is certainly a bug.
+
+Fix it by adding the necessary checks on offset table entry width, and
+unit tests.
+
+Spotted by William Manley.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Fixes: #2794
+
+CVE: CVE-2023-29499
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/5f4485c4ff57fdefb1661531788def7ca5a47328]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-serialiser.c | 19 +++-
+ glib/tests/gvariant.c | 176 +++++++++++++++++++++++++++++++++++++
+ 2 files changed, 194 insertions(+), 1 deletion(-)
+
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index 0bf7243..5aa2cbc 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -694,6 +694,10 @@ gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
+ out.data_size = last_end;
+ out.array = value.data + last_end;
+ out.length = offsets_array_size / out.offset_size;
++
++ if (out.length > 0 && gvs_calculate_total_size (last_end, out.length) != value.size)
++ return out; /* offset size not minimal */
++
+ out.is_normal = TRUE;
+
+ return out;
+@@ -1201,6 +1205,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
+ gsize length;
+ gsize offset;
+ gsize i;
++ gsize offset_table_size;
+
+ /* as per the comment in gvs_tuple_get_child() */
+ if G_UNLIKELY (value.data == NULL && value.size != 0)
+@@ -1305,7 +1310,19 @@ gvs_tuple_is_normal (GVariantSerialised value)
+ }
+ }
+
+- return offset_ptr == offset;
++ /* @offset_ptr has been counting backwards from the end of the variant, to
++ * find the beginning of the offset table. @offset has been counting forwards
++ * from the beginning of the variant to find the end of the data. They should
++ * have met in the middle. */
++ if (offset_ptr != offset)
++ return FALSE;
++
++ offset_table_size = value.size - offset_ptr;
++ if (value.size > 0 &&
++ gvs_calculate_total_size (offset, offset_table_size / offset_size) != value.size)
++ return FALSE; /* offset size not minimal */
++
++ return TRUE;
+ }
+
+ /* Variants {{{2
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index d640c81..4ce0e4f 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -5092,6 +5092,86 @@ test_normal_checking_array_offsets2 (void)
+ g_variant_unref (variant);
+ }
+
++/* Test that an otherwise-valid serialised GVariant is considered non-normal if
++ * its offset table entries are too wide.
++ *
++ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
++static void
++test_normal_checking_array_offsets_minimal_sized (void)
++{
++ GVariantBuilder builder;
++ gsize i;
++ GVariant *aay_constructed = NULL;
++ const guint8 *data = NULL;
++ guint8 *data_owned = NULL;
++ GVariant *aay_deserialised = NULL;
++ GVariant *aay_normalised = NULL;
++
++ /* Construct an array of type aay, consisting of 128 elements which are each
++ * an empty array, i.e. `[[] * 128]`. This is chosen because the inner
++ * elements are variable sized (making the outer array variable sized, so it
++ * must have an offset table), but they are also zero-sized when serialised.
++ * So the serialised representation of @aay_constructed consists entirely of
++ * its offset table, which is entirely zeroes.
++ *
++ * The array is chosen to be 128 elements long because that means offset
++ * table entries which are 1 byte long. If the elements in the array were
++ * non-zero-sized (to the extent that the overall array is ≥256 bytes long),
++ * the offset table entries would end up being 2 bytes long. */
++ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
++
++ for (i = 0; i < 128; i++)
++ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
++
++ aay_constructed = g_variant_builder_end (&builder);
++
++ /* Verify that the constructed array is in normal form, and its serialised
++ * form is `b'\0' * 128`. */
++ g_assert_true (g_variant_is_normal_form (aay_constructed));
++ g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128);
++ g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128);
++
++ data = g_variant_get_data (aay_constructed);
++ for (i = 0; i < g_variant_get_size (aay_constructed); i++)
++ g_assert_cmpuint (data[i], ==, 0);
++
++ /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to
++ * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table
++ * entries, because each offset table entry has to be able to reference all of
++ * the byte boundaries in the container. All the entries in the offset table
++ * are zero, so all the elements of the array are zero-sized. */
++ data = data_owned = g_malloc0 (256);
++ aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"),
++ data,
++ 256,
++ FALSE,
++ g_free,
++ g_steal_pointer (&data_owned));
++
++ g_assert_false (g_variant_is_normal_form (aay_deserialised));
++ g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128);
++ g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256);
++
++ data = g_variant_get_data (aay_deserialised);
++ for (i = 0; i < g_variant_get_size (aay_deserialised); i++)
++ g_assert_cmpuint (data[i], ==, 0);
++
++ /* Get its normal form. That should change the serialised size. */
++ aay_normalised = g_variant_get_normal_form (aay_deserialised);
++
++ g_assert_true (g_variant_is_normal_form (aay_normalised));
++ g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128);
++ g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128);
++
++ data = g_variant_get_data (aay_normalised);
++ for (i = 0; i < g_variant_get_size (aay_normalised); i++)
++ g_assert_cmpuint (data[i], ==, 0);
++
++ g_variant_unref (aay_normalised);
++ g_variant_unref (aay_deserialised);
++ g_variant_unref (aay_constructed);
++}
++
+ /* Test that a tuple with invalidly large values in its offset table is
+ * normalised successfully without looping infinitely. */
+ static void
+@@ -5286,6 +5366,98 @@ test_normal_checking_tuple_offsets4 (void)
+ g_variant_unref (variant);
+ }
+
++/* Test that an otherwise-valid serialised GVariant is considered non-normal if
++ * its offset table entries are too wide.
++ *
++ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
++static void
++test_normal_checking_tuple_offsets_minimal_sized (void)
++{
++ GString *type_string = NULL;
++ GVariantBuilder builder;
++ gsize i;
++ GVariant *ray_constructed = NULL;
++ const guint8 *data = NULL;
++ guint8 *data_owned = NULL;
++ GVariant *ray_deserialised = NULL;
++ GVariant *ray_normalised = NULL;
++
++ /* Construct a tuple of type (ay…ay), consisting of 129 members which are each
++ * an empty array, i.e. `([] * 129)`. This is chosen because the inner
++ * members are variable sized, so the outer tuple must have an offset table,
++ * but they are also zero-sized when serialised. So the serialised
++ * representation of @ray_constructed consists entirely of its offset table,
++ * which is entirely zeroes.
++ *
++ * The tuple is chosen to be 129 members long because that means it has 128
++ * offset table entries which are 1 byte long each. If the members in the
++ * tuple were non-zero-sized (to the extent that the overall tuple is ≥256
++ * bytes long), the offset table entries would end up being 2 bytes long.
++ *
++ * 129 members are used unlike 128 array elements in
++ * test_normal_checking_array_offsets_minimal_sized(), because the last member
++ * in a tuple never needs an offset table entry. */
++ type_string = g_string_new ("");
++ g_string_append_c (type_string, '(');
++ for (i = 0; i < 129; i++)
++ g_string_append (type_string, "ay");
++ g_string_append_c (type_string, ')');
++
++ g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str));
++
++ for (i = 0; i < 129; i++)
++ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
++
++ ray_constructed = g_variant_builder_end (&builder);
++
++ /* Verify that the constructed tuple is in normal form, and its serialised
++ * form is `b'\0' * 128`. */
++ g_assert_true (g_variant_is_normal_form (ray_constructed));
++ g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129);
++ g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128);
++
++ data = g_variant_get_data (ray_constructed);
++ for (i = 0; i < g_variant_get_size (ray_constructed); i++)
++ g_assert_cmpuint (data[i], ==, 0);
++
++ /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has
++ * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table
++ * entries, because each offset table entry has to be able to reference all of
++ * the byte boundaries in the container. All the entries in the offset table
++ * are zero, so all the members of the tuple are zero-sized. */
++ data = data_owned = g_malloc0 (256);
++ ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str),
++ data,
++ 256,
++ FALSE,
++ g_free,
++ g_steal_pointer (&data_owned));
++
++ g_assert_false (g_variant_is_normal_form (ray_deserialised));
++ g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129);
++ g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256);
++
++ data = g_variant_get_data (ray_deserialised);
++ for (i = 0; i < g_variant_get_size (ray_deserialised); i++)
++ g_assert_cmpuint (data[i], ==, 0);
++
++ /* Get its normal form. That should change the serialised size. */
++ ray_normalised = g_variant_get_normal_form (ray_deserialised);
++
++ g_assert_true (g_variant_is_normal_form (ray_normalised));
++ g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129);
++ g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128);
++
++ data = g_variant_get_data (ray_normalised);
++ for (i = 0; i < g_variant_get_size (ray_normalised); i++)
++ g_assert_cmpuint (data[i], ==, 0);
++
++ g_variant_unref (ray_normalised);
++ g_variant_unref (ray_deserialised);
++ g_variant_unref (ray_constructed);
++ g_string_free (type_string, TRUE);
++}
++
+ /* Test that an empty object path is normalised successfully to the base object
+ * path, ‘/’. */
+ static void
+@@ -5431,6 +5603,8 @@ main (int argc, char **argv)
+ test_normal_checking_array_offsets);
+ g_test_add_func ("/gvariant/normal-checking/array-offsets2",
+ test_normal_checking_array_offsets2);
++ g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized",
++ test_normal_checking_array_offsets_minimal_sized);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
+ test_normal_checking_tuple_offsets);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
+@@ -5439,6 +5613,8 @@ main (int argc, char **argv)
+ test_normal_checking_tuple_offsets3);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
+ test_normal_checking_tuple_offsets4);
++ g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
++ test_normal_checking_tuple_offsets_minimal_sized);
+ g_test_add_func ("/gvariant/normal-checking/empty-object-path",
+ test_normal_checking_empty_object_path);
+
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch
new file mode 100644
index 0000000000..b2187f2af9
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch
@@ -0,0 +1,89 @@
+From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
+From: William Manley <will@stb-tester.com>
+Date: Wed, 9 Aug 2023 10:04:49 +0000
+Subject: [PATCH] gvariant-core: Consolidate construction of
+ `GVariantSerialised`
+
+So I only need to change it in one place.
+
+This introduces no functional changes.
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant.c | 8 +++++---
+ glib/tests/gvariant.c | 24 ++++++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/glib/gvariant.c b/glib/gvariant.c
+index 8ba701e..4dbd9e8 100644
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -5952,14 +5952,16 @@ g_variant_byteswap (GVariant *value)
+ g_variant_serialised_byteswap (serialised);
+
+ bytes = g_bytes_new_take (serialised.data, serialised.size);
+- new = g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE);
++ new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
+ g_bytes_unref (bytes);
+ }
+ else
+ /* contains no multi-byte data */
+- new = value;
++ new = g_variant_get_normal_form (value);
+
+- return g_variant_ref_sink (new);
++ g_assert (g_variant_is_trusted (new));
++
++ return g_steal_pointer (&new);
+ }
+
+ /**
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index 4ce0e4f..3dda08e 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -3834,6 +3834,29 @@ test_gv_byteswap (void)
+ g_free (string);
+ }
+
++static void
++test_gv_byteswap_non_normal_non_aligned (void)
++{
++ const guint8 data[] = { 0x02 };
++ GVariant *v = NULL;
++ GVariant *v_byteswapped = NULL;
++
++ g_test_summary ("Test that calling g_variant_byteswap() on a variant which "
++ "is in non-normal form and doesn’t need byteswapping returns "
++ "the same variant in normal form.");
++
++ v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL);
++ g_assert_false (g_variant_is_normal_form (v));
++
++ v_byteswapped = g_variant_byteswap (v);
++ g_assert_true (g_variant_is_normal_form (v_byteswapped));
++
++ g_assert_cmpvariant (v, v_byteswapped);
++
++ g_variant_unref (v);
++ g_variant_unref (v_byteswapped);
++}
++
+ static void
+ test_parser (void)
+ {
+@@ -5570,6 +5593,7 @@ main (int argc, char **argv)
+ g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
+ g_test_add_func ("/gvariant/hashing", test_hashing);
+ g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
++ g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned);
+ g_test_add_func ("/gvariant/parser", test_parses);
+ g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
+ g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch
new file mode 100644
index 0000000000..9167ea624f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch
@@ -0,0 +1,255 @@
+From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
+From: William Manley <will@stb-tester.com>
+Date: Wed, 9 Aug 2023 10:39:34 +0000
+Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
+ framing offsets
+
+This introduces no functional changes.
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant.c | 81 +++++++++++++++++++++++++++++++++----------
+ glib/tests/gvariant.c | 57 ++++++++++++++++++++++++++----
+ 2 files changed, 112 insertions(+), 26 deletions(-)
+
+diff --git a/glib/gvariant.c b/glib/gvariant.c
+index 4dbd9e8..a80c2c9 100644
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -5788,7 +5788,8 @@ g_variant_iter_loop (GVariantIter *iter,
+
+ /* Serialised data {{{1 */
+ static GVariant *
+-g_variant_deep_copy (GVariant *value)
++g_variant_deep_copy (GVariant *value,
++ gboolean byteswap)
+ {
+ switch (g_variant_classify (value))
+ {
+@@ -5806,7 +5807,7 @@ g_variant_deep_copy (GVariant *value)
+ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
+ {
+ GVariant *child = g_variant_get_child_value (value, i);
+- g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
++ g_variant_builder_add_value (&builder, g_variant_deep_copy (child, byteswap));
+ g_variant_unref (child);
+ }
+
+@@ -5820,28 +5821,63 @@ g_variant_deep_copy (GVariant *value)
+ return g_variant_new_byte (g_variant_get_byte (value));
+
+ case G_VARIANT_CLASS_INT16:
+- return g_variant_new_int16 (g_variant_get_int16 (value));
++ if (byteswap)
++ return g_variant_new_int16 (GUINT16_SWAP_LE_BE (g_variant_get_int16 (value)));
++ else
++ return g_variant_new_int16 (g_variant_get_int16 (value));
+
+ case G_VARIANT_CLASS_UINT16:
+- return g_variant_new_uint16 (g_variant_get_uint16 (value));
++ if (byteswap)
++ return g_variant_new_uint16 (GUINT16_SWAP_LE_BE (g_variant_get_uint16 (value)));
++ else
++ return g_variant_new_uint16 (g_variant_get_uint16 (value));
+
+ case G_VARIANT_CLASS_INT32:
+- return g_variant_new_int32 (g_variant_get_int32 (value));
++ if (byteswap)
++ return g_variant_new_int32 (GUINT32_SWAP_LE_BE (g_variant_get_int32 (value)));
++ else
++ return g_variant_new_int32 (g_variant_get_int32 (value));
+
+ case G_VARIANT_CLASS_UINT32:
+- return g_variant_new_uint32 (g_variant_get_uint32 (value));
++ if (byteswap)
++ return g_variant_new_uint32 (GUINT32_SWAP_LE_BE (g_variant_get_uint32 (value)));
++ else
++ return g_variant_new_uint32 (g_variant_get_uint32 (value));
+
+ case G_VARIANT_CLASS_INT64:
+- return g_variant_new_int64 (g_variant_get_int64 (value));
++ if (byteswap)
++ return g_variant_new_int64 (GUINT64_SWAP_LE_BE (g_variant_get_int64 (value)));
++ else
++ return g_variant_new_int64 (g_variant_get_int64 (value));
+
+ case G_VARIANT_CLASS_UINT64:
+- return g_variant_new_uint64 (g_variant_get_uint64 (value));
++ if (byteswap)
++ return g_variant_new_uint64 (GUINT64_SWAP_LE_BE (g_variant_get_uint64 (value)));
++ else
++ return g_variant_new_uint64 (g_variant_get_uint64 (value));
+
+ case G_VARIANT_CLASS_HANDLE:
+- return g_variant_new_handle (g_variant_get_handle (value));
++ if (byteswap)
++ return g_variant_new_handle (GUINT32_SWAP_LE_BE (g_variant_get_handle (value)));
++ else
++ return g_variant_new_handle (g_variant_get_handle (value));
+
+ case G_VARIANT_CLASS_DOUBLE:
+- return g_variant_new_double (g_variant_get_double (value));
++ if (byteswap)
++ {
++ /* We have to convert the double to a uint64 here using a union,
++ * because a cast will round it numerically. */
++ union
++ {
++ guint64 u64;
++ gdouble dbl;
++ } u1, u2;
++ u1.dbl = g_variant_get_double (value);
++ u2.u64 = GUINT64_SWAP_LE_BE (u1.u64);
++ return g_variant_new_double (u2.dbl);
++ }
++ else
++ return g_variant_new_double (g_variant_get_double (value));
+
+ case G_VARIANT_CLASS_STRING:
+ return g_variant_new_string (g_variant_get_string (value, NULL));
+@@ -5896,7 +5932,7 @@ g_variant_get_normal_form (GVariant *value)
+ if (g_variant_is_normal_form (value))
+ return g_variant_ref (value);
+
+- trusted = g_variant_deep_copy (value);
++ trusted = g_variant_deep_copy (value, FALSE);
+ g_assert (g_variant_is_trusted (trusted));
+
+ return g_variant_ref_sink (trusted);
+@@ -5916,6 +5952,11 @@ g_variant_get_normal_form (GVariant *value)
+ * contain multi-byte numeric data. That include strings, booleans,
+ * bytes and containers containing only these things (recursively).
+ *
++ * While this function can safely handle untrusted, non-normal data, it is
++ * recommended to check whether the input is in normal form beforehand, using
++ * g_variant_is_normal_form(), and to reject non-normal inputs if your
++ * application can be strict about what inputs it rejects.
++ *
+ * The returned value is always in normal form and is marked as trusted.
+ *
+ * Returns: (transfer full): the byteswapped form of @value
+@@ -5933,21 +5974,20 @@ g_variant_byteswap (GVariant *value)
+
+ g_variant_type_info_query (type_info, &alignment, NULL);
+
+- if (alignment)
+- /* (potentially) contains multi-byte numeric data */
++ if (alignment && g_variant_is_normal_form (value))
+ {
++ /* (potentially) contains multi-byte numeric data, but is also already in
++ * normal form so we can use a faster byteswapping codepath on the
++ * serialised data */
+ GVariantSerialised serialised = { 0, };
+- GVariant *trusted;
+ GBytes *bytes;
+
+- trusted = g_variant_get_normal_form (value);
+- serialised.type_info = g_variant_get_type_info (trusted);
+- serialised.size = g_variant_get_size (trusted);
++ serialised.type_info = g_variant_get_type_info (value);
++ serialised.size = g_variant_get_size (value);
+ serialised.data = g_malloc (serialised.size);
+ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
+ serialised.checked_offsets_up_to = G_MAXSIZE;
+- g_variant_store (trusted, serialised.data);
+- g_variant_unref (trusted);
++ g_variant_store (value, serialised.data);
+
+ g_variant_serialised_byteswap (serialised);
+
+@@ -5955,6 +5995,9 @@ g_variant_byteswap (GVariant *value)
+ new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
+ g_bytes_unref (bytes);
+ }
++ else if (alignment)
++ /* (potentially) contains multi-byte numeric data */
++ new = g_variant_ref_sink (g_variant_deep_copy (value, TRUE));
+ else
+ /* contains no multi-byte data */
+ new = g_variant_get_normal_form (value);
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index 3dda08e..679dd40 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -2284,24 +2284,67 @@ serialise_tree (TreeInstance *tree,
+ static void
+ test_byteswap (void)
+ {
+- GVariantSerialised one = { 0, }, two = { 0, };
++ GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, };
+ TreeInstance *tree;
+-
++ GVariant *one_variant = NULL;
++ GVariant *two_variant = NULL;
++ GVariant *two_byteswapped = NULL;
++ GVariant *three_variant = NULL;
++ GVariant *three_byteswapped = NULL;
++ guint8 *three_data_copy = NULL;
++ gsize three_size_copy = 0;
++
++ /* Write a tree out twice, once normally and once byteswapped. */
+ tree = tree_instance_new (NULL, 3);
+ serialise_tree (tree, &one);
+
++ one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)),
++ one.data, one.size, FALSE, NULL, NULL);
++
+ i_am_writing_byteswapped = TRUE;
+ serialise_tree (tree, &two);
++ serialise_tree (tree, &three);
+ i_am_writing_byteswapped = FALSE;
+
+- g_variant_serialised_byteswap (two);
+-
+- g_assert_cmpmem (one.data, one.size, two.data, two.size);
+- g_assert_cmpuint (one.depth, ==, two.depth);
+-
++ /* Swap the first byteswapped one back using the function we want to test. */
++ two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)),
++ two.data, two.size, FALSE, NULL, NULL);
++ two_byteswapped = g_variant_byteswap (two_variant);
++
++ /* Make the second byteswapped one non-normal (hopefully), and then byteswap
++ * it back using the function we want to test in its non-normal mode.
++ * This might not work because it’s not necessarily possible to make an
++ * arbitrary random variant non-normal. Adding a single zero byte to the end
++ * often makes something non-normal but still readable. */
++ three_size_copy = three.size + 1;
++ three_data_copy = g_malloc (three_size_copy);
++ memcpy (three_data_copy, three.data, three.size);
++ three_data_copy[three.size] = '\0';
++
++ three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)),
++ three_data_copy, three_size_copy, FALSE, NULL, NULL);
++ three_byteswapped = g_variant_byteswap (three_variant);
++
++ /* Check they’re the same. We can always compare @one_variant and
++ * @two_byteswapped. We can only compare @two_byteswapped and
++ * @three_byteswapped if @two_variant and @three_variant are equal: in that
++ * case, the corruption to @three_variant was enough to make it non-normal but
++ * not enough to change its value. */
++ g_assert_cmpvariant (one_variant, two_byteswapped);
++
++ if (g_variant_equal (two_variant, three_variant))
++ g_assert_cmpvariant (two_byteswapped, three_byteswapped);
++
++ g_variant_unref (three_byteswapped);
++ g_variant_unref (three_variant);
++ g_variant_unref (two_byteswapped);
++ g_variant_unref (two_variant);
++ g_variant_unref (one_variant);
+ tree_instance_free (tree);
+ g_free (one.data);
+ g_free (two.data);
++ g_free (three.data);
++ g_free (three_data_copy);
+ }
+
+ static void
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch
new file mode 100644
index 0000000000..533142b22a
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch
@@ -0,0 +1,49 @@
+From 21a204147b16539b3eda3143b32844c49e29f4d4 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 17 Aug 2023 11:33:49 +0000
+Subject: [PATCH] gvariant: Propagate trust when getting a child of a
+ serialised variant
+
+If a variant is trusted, that means all its children are trusted, so
+ensure that their checked offsets are set as such.
+
+This allows a lot of the offset table checks to be avoided when getting
+children from trusted serialised tuples, which speeds things up.
+
+No unit test is included because this is just a performance fix. If
+there are other slownesses, or regressions, in serialised `GVariant`
+performance, the fuzzing setup will catch them like it did this one.
+
+This change does reduce the time to run the oss-fuzz reproducer from 80s
+to about 0.7s on my machine.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Fixes: #2841
+oss-fuzz#54314
+
+CVE: CVE-2023-32636
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/21a204147b16539b3eda3143b32844c49e29f4d4]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
+index 1b9d5cc..ed57c70 100644
+--- a/glib/gvariant-core.c
++++ b/glib/gvariant-core.c
+@@ -1173,8 +1173,8 @@ g_variant_get_child_value (GVariant *value,
+ child->contents.serialised.bytes =
+ g_bytes_ref (value->contents.serialised.bytes);
+ child->contents.serialised.data = s_child.data;
+- child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
+- child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
++ child->contents.serialised.ordered_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.ordered_offsets_up_to;
++ child->contents.serialised.checked_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.checked_offsets_up_to;
+
+ return child;
+ }
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch
new file mode 100644
index 0000000000..9c0867bf5f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch
@@ -0,0 +1,154 @@
+From 78da5faccb3e065116b75b3ff87ff55381da6c76 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 17 Aug 2023 11:24:43 +0000
+Subject: [PATCH] gvariant: Check offset table doesn't fall outside variant
+ bounds
+
+When dereferencing the first entry in the offset table for a tuple,
+check that it doesn’t fall outside the bounds of the variant first.
+
+This prevents an out-of-bounds read from some non-normal tuples.
+
+This bug was introduced in commit 73d0aa81c2575a5c9ae77d.
+
+Includes a unit test, although the test will likely only catch the
+original bug if run with asan enabled.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Fixes: #2840
+oss-fuzz#54302
+
+CVE: CVE-2023-32643
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/78da5faccb3e065116b75b3ff87ff55381da6c76]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-serialiser.c | 12 ++++++--
+ glib/tests/gvariant.c | 63 ++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 72 insertions(+), 3 deletions(-)
+
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index 5aa2cbc..4e50ed7 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -979,7 +979,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
+
+ member_info = g_variant_type_info_member_info (value.type_info, index_);
+
+- if (member_info->i + 1)
++ if (member_info->i + 1 &&
++ offset_size * (member_info->i + 1) <= value.size)
+ member_start = gvs_read_unaligned_le (value.data + value.size -
+ offset_size * (member_info->i + 1),
+ offset_size);
+@@ -990,7 +991,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
+ member_start &= member_info->b;
+ member_start |= member_info->c;
+
+- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
++ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST &&
++ offset_size * (member_info->i + 1) <= value.size)
+ member_end = value.size - offset_size * (member_info->i + 1);
+
+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
+@@ -1001,11 +1003,15 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
+ member_end = member_start + fixed_size;
+ }
+
+- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
++ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET &&
++ offset_size * (member_info->i + 2) <= value.size)
+ member_end = gvs_read_unaligned_le (value.data + value.size -
+ offset_size * (member_info->i + 2),
+ offset_size);
+
++ else /* invalid */
++ member_end = G_MAXSIZE;
++
+ if (out_member_start != NULL)
+ *out_member_start = member_start;
+ if (out_member_end != NULL)
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index 679dd40..2eca8be 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -5432,6 +5432,67 @@ test_normal_checking_tuple_offsets4 (void)
+ g_variant_unref (variant);
+ }
+
++/* This is a regression test that dereferencing the first element in the offset
++ * table doesn’t dereference memory before the start of the GVariant. The first
++ * element in the offset table gives the offset of the final member in the
++ * tuple (the offset table is stored in reverse), and the position of this final
++ * member is needed to check that none of the tuple members overlap with the
++ * offset table
++ *
++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */
++static void
++test_normal_checking_tuple_offsets5 (void)
++{
++ /* A tuple of type (sss) in normal form would have an offset table with two
++ * entries:
++ * - The first entry (lowest index in the table) gives the offset of the
++ * third `s` in the tuple, as the offset table is reversed compared to the
++ * tuple members.
++ * - The second entry (highest index in the table) gives the offset of the
++ * second `s` in the tuple.
++ * - The offset of the first `s` in the tuple is always 0.
++ *
++ * See §2.5.4 (Structures) of the GVariant specification for details, noting
++ * that the table is only layed out this way because all three members of the
++ * tuple have non-fixed sizes.
++ *
++ * It’s not clear whether the 0xaa data of this variant is part of the strings
++ * in the tuple, or part of the offset table. It doesn’t really matter. This
++ * is a regression test to check that the code to validate the offset table
++ * doesn’t unconditionally try to access the first entry in the offset table
++ * by subtracting the table size from the end of the GVariant data.
++ *
++ * In this non-normal case, that would result in an address off the start of
++ * the GVariant data, and an out-of-bounds read, because the GVariant is one
++ * byte long, but the offset table is calculated as two bytes long (with 1B
++ * sized entries) from the tuple’s type.
++ */
++ const GVariantType *data_type = G_VARIANT_TYPE ("(sss)");
++ const guint8 data[] = { 0xaa };
++ gsize size = sizeof (data);
++ GVariant *variant = NULL;
++ GVariant *normal_variant = NULL;
++ GVariant *expected = NULL;
++
++ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840");
++
++ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
++ g_assert_nonnull (variant);
++
++ g_assert_false (g_variant_is_normal_form (variant));
++
++ normal_variant = g_variant_get_normal_form (variant);
++ g_assert_nonnull (normal_variant);
++
++ expected = g_variant_new_parsed ("('', '', '')");
++ g_assert_cmpvariant (expected, variant);
++ g_assert_cmpvariant (expected, normal_variant);
++
++ g_variant_unref (expected);
++ g_variant_unref (normal_variant);
++ g_variant_unref (variant);
++}
++
+ /* Test that an otherwise-valid serialised GVariant is considered non-normal if
+ * its offset table entries are too wide.
+ *
+@@ -5680,6 +5741,8 @@ main (int argc, char **argv)
+ test_normal_checking_tuple_offsets3);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
+ test_normal_checking_tuple_offsets4);
++ g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
++ test_normal_checking_tuple_offsets5);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
+ test_normal_checking_tuple_offsets_minimal_sized);
+ g_test_add_func ("/gvariant/normal-checking/empty-object-path",
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
new file mode 100644
index 0000000000..9fc58341cb
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
@@ -0,0 +1,103 @@
+From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
+From: William Manley <will@stb-tester.com>
+Date: Wed, 9 Aug 2023 10:04:49 +0000
+Subject: [PATCH] gvariant-core: Consolidate construction of
+ `GVariantSerialised`
+
+So I only need to change it in one place.
+
+This introduces no functional changes.
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-core.c | 49 ++++++++++++++++++++++----------------------
+ 1 file changed, 25 insertions(+), 24 deletions(-)
+
+diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
+index 9397573..aa0e0a0 100644
+--- a/glib/gvariant-core.c
++++ b/glib/gvariant-core.c
+@@ -349,6 +349,27 @@ g_variant_ensure_size (GVariant *value)
+ }
+ }
+
++/* < private >
++ * g_variant_to_serialised:
++ * @value: a #GVariant
++ *
++ * Gets a GVariantSerialised for a GVariant in state STATE_SERIALISED.
++ */
++inline static GVariantSerialised
++g_variant_to_serialised (GVariant *value)
++{
++ g_assert (value->state & STATE_SERIALISED);
++ {
++ GVariantSerialised serialised = {
++ value->type_info,
++ (gpointer) value->contents.serialised.data,
++ value->size,
++ value->depth,
++ };
++ return serialised;
++ }
++}
++
+ /* < private >
+ * g_variant_serialise:
+ * @value: a #GVariant
+@@ -991,16 +1012,8 @@ g_variant_n_children (GVariant *value)
+ g_variant_lock (value);
+
+ if (value->state & STATE_SERIALISED)
+- {
+- GVariantSerialised serialised = {
+- value->type_info,
+- (gpointer) value->contents.serialised.data,
+- value->size,
+- value->depth,
+- };
+-
+- n_children = g_variant_serialised_n_children (serialised);
+- }
++ n_children = g_variant_serialised_n_children (
++ g_variant_to_serialised (value));
+ else
+ n_children = value->contents.tree.n_children;
+
+@@ -1061,12 +1074,7 @@ g_variant_get_child_value (GVariant *value,
+ }
+
+ {
+- GVariantSerialised serialised = {
+- value->type_info,
+- (gpointer) value->contents.serialised.data,
+- value->size,
+- value->depth,
+- };
++ GVariantSerialised serialised = g_variant_to_serialised (value);
+ GVariantSerialised s_child;
+ GVariant *child;
+
+@@ -1179,14 +1187,7 @@ g_variant_is_normal_form (GVariant *value)
+
+ if (value->state & STATE_SERIALISED)
+ {
+- GVariantSerialised serialised = {
+- value->type_info,
+- (gpointer) value->contents.serialised.data,
+- value->size,
+- value->depth
+- };
+-
+- if (g_variant_serialised_is_normal (serialised))
++ if (g_variant_serialised_is_normal (g_variant_to_serialised (value)))
+ value->state |= STATE_TRUSTED;
+ }
+ else
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
new file mode 100644
index 0000000000..0e96b8d457
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
@@ -0,0 +1,210 @@
+From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
+From: William Manley <will@stb-tester.com>
+Date: Wed, 9 Aug 2023 10:39:34 +0000
+Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
+ framing offsets
+
+This introduces no functional changes.
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-serialiser.c | 108 +++++++++++++++++++------------------
+ 1 file changed, 57 insertions(+), 51 deletions(-)
+
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index 83e9d85..c7c2114 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -633,30 +633,62 @@ gvs_calculate_total_size (gsize body_size,
+ return body_size + 8 * offsets;
+ }
+
++struct Offsets
++{
++ gsize data_size;
++
++ guchar *array;
++ gsize length;
++ guint offset_size;
++
++ gboolean is_normal;
++};
++
+ static gsize
+-gvs_variable_sized_array_n_children (GVariantSerialised value)
++gvs_offsets_get_offset_n (struct Offsets *offsets,
++ gsize n)
++{
++ return gvs_read_unaligned_le (
++ offsets->array + (offsets->offset_size * n), offsets->offset_size);
++}
++
++static struct Offsets
++gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
+ {
++ struct Offsets out = { 0, };
+ gsize offsets_array_size;
+- gsize offset_size;
+ gsize last_end;
+
+ if (value.size == 0)
+- return 0;
+-
+- offset_size = gvs_get_offset_size (value.size);
++ {
++ out.is_normal = TRUE;
++ return out;
++ }
+
+- last_end = gvs_read_unaligned_le (value.data + value.size -
+- offset_size, offset_size);
++ out.offset_size = gvs_get_offset_size (value.size);
++ last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size,
++ out.offset_size);
+
+ if (last_end > value.size)
+- return 0;
++ return out; /* offsets not normal */
+
+ offsets_array_size = value.size - last_end;
+
+- if (offsets_array_size % offset_size)
+- return 0;
++ if (offsets_array_size % out.offset_size)
++ return out; /* offsets not normal */
++
++ out.data_size = last_end;
++ out.array = value.data + last_end;
++ out.length = offsets_array_size / out.offset_size;
++ out.is_normal = TRUE;
+
+- return offsets_array_size / offset_size;
++ return out;
++}
++
++static gsize
++gvs_variable_sized_array_n_children (GVariantSerialised value)
++{
++ return gvs_variable_sized_array_get_frame_offsets (value).length;
+ }
+
+ static GVariantSerialised
+@@ -664,8 +696,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
+ gsize index_)
+ {
+ GVariantSerialised child = { 0, };
+- gsize offset_size;
+- gsize last_end;
++
++ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
++
+ gsize start;
+ gsize end;
+
+@@ -673,18 +706,11 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
+ g_variant_type_info_ref (child.type_info);
+ child.depth = value.depth + 1;
+
+- offset_size = gvs_get_offset_size (value.size);
+-
+- last_end = gvs_read_unaligned_le (value.data + value.size -
+- offset_size, offset_size);
+-
+ if (index_ > 0)
+ {
+ guint alignment;
+
+- start = gvs_read_unaligned_le (value.data + last_end +
+- (offset_size * (index_ - 1)),
+- offset_size);
++ start = gvs_offsets_get_offset_n (&offsets, index_ - 1);
+
+ g_variant_type_info_query (child.type_info, &alignment, NULL);
+ start += (-start) & alignment;
+@@ -692,11 +718,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
+ else
+ start = 0;
+
+- end = gvs_read_unaligned_le (value.data + last_end +
+- (offset_size * index_),
+- offset_size);
++ end = gvs_offsets_get_offset_n (&offsets, index_);
+
+- if (start < end && end <= value.size && end <= last_end)
++ if (start < end && end <= value.size && end <= offsets.data_size)
+ {
+ child.data = value.data + start;
+ child.size = end - start;
+@@ -768,34 +792,16 @@ static gboolean
+ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+ {
+ GVariantSerialised child = { 0, };
+- gsize offsets_array_size;
+- guchar *offsets_array;
+- guint offset_size;
+ guint alignment;
+- gsize last_end;
+- gsize length;
+ gsize offset;
+ gsize i;
+
+- if (value.size == 0)
+- return TRUE;
+-
+- offset_size = gvs_get_offset_size (value.size);
+- last_end = gvs_read_unaligned_le (value.data + value.size -
+- offset_size, offset_size);
++ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
+
+- if (last_end > value.size)
++ if (!offsets.is_normal)
+ return FALSE;
+
+- offsets_array_size = value.size - last_end;
+-
+- if (offsets_array_size % offset_size)
+- return FALSE;
+-
+- offsets_array = value.data + value.size - offsets_array_size;
+- length = offsets_array_size / offset_size;
+-
+- if (length == 0)
++ if (value.size != 0 && offsets.length == 0)
+ return FALSE;
+
+ child.type_info = g_variant_type_info_element (value.type_info);
+@@ -803,14 +809,14 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+ child.depth = value.depth + 1;
+ offset = 0;
+
+- for (i = 0; i < length; i++)
++ for (i = 0; i < offsets.length; i++)
+ {
+ gsize this_end;
+
+- this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
+- offset_size);
++ this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i,
++ offsets.offset_size);
+
+- if (this_end < offset || this_end > last_end)
++ if (this_end < offset || this_end > offsets.data_size)
+ return FALSE;
+
+ while (offset & alignment)
+@@ -832,7 +838,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+ offset = this_end;
+ }
+
+- g_assert (offset == last_end);
++ g_assert (offset == offsets.data_size);
+
+ return TRUE;
+ }
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
new file mode 100644
index 0000000000..e361cc7aad
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
@@ -0,0 +1,417 @@
+From ade71fb544391b2e33e1859645726bfee0d5eaaf Mon Sep 17 00:00:00 2001
+From: William Manley <will@stb-tester.com>
+Date: Wed, 16 Aug 2023 03:12:21 +0000
+Subject: [PATCH] gvariant: Don't allow child elements to overlap with each
+ other
+
+If different elements of a variable sized array can overlap with each
+other then we can cause a `GVariant` to normalise to a much larger type.
+
+This commit changes the behaviour of `GVariant` with non-normal form data. If
+an invalid frame offset is found all subsequent elements are given their
+default value.
+
+When retrieving an element at index `n` we scan the frame offsets up to index
+`n` and if they are not in order we return an element with the default value
+for that type. This guarantees that elements don't overlap with each
+other. We remember the offset we've scanned up to so we don't need to
+repeat this work on subsequent accesses. We skip these checks for trusted
+data.
+
+Unfortunately this makes random access of untrusted data O(n) — at least
+on first access. It doesn't affect the algorithmic complexity of accessing
+elements in order, such as when using the `GVariantIter` interface. Also:
+the cost of validation will be amortised as the `GVariant` instance is
+continued to be used.
+
+I've implemented this with 4 different functions, 1 for each element size,
+rather than looping calling `gvs_read_unaligned_le` in the hope that the
+compiler will find it easy to optimise and should produce fairly tight
+code.
+
+Fixes: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/ade71fb544391b2e33e1859645726bfee0d5eaaf]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-core.c | 35 ++++++++++++++++
+ glib/gvariant-serialiser.c | 86 ++++++++++++++++++++++++++++++++++++--
+ glib/gvariant-serialiser.h | 8 ++++
+ glib/tests/gvariant.c | 45 ++++++++++++++++++++
+ 4 files changed, 171 insertions(+), 3 deletions(-)
+
+diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
+index aa0e0a0..9b51e15 100644
+--- a/glib/gvariant-core.c
++++ b/glib/gvariant-core.c
+@@ -65,6 +65,7 @@ struct _GVariant
+ {
+ GBytes *bytes;
+ gconstpointer data;
++ gsize ordered_offsets_up_to;
+ } serialised;
+
+ struct
+@@ -162,6 +163,24 @@ struct _GVariant
+ * if .data pointed to the appropriate number of nul
+ * bytes.
+ *
++ * .ordered_offsets_up_to: If ordered_offsets_up_to == n this means that all
++ * the frame offsets up to and including the frame
++ * offset determining the end of element n are in
++ * order. This guarantees that the bytes of element
++ * n don't overlap with any previous element.
++ *
++ * For trusted data this is set to G_MAXSIZE and we
++ * don't check that the frame offsets are in order.
++ *
++ * Note: This doesn't imply the offsets are good in
++ * any way apart from their ordering. In particular
++ * offsets may be out of bounds for this value or
++ * may imply that the data overlaps the frame
++ * offsets themselves.
++ *
++ * This field is only relevant for arrays of non
++ * fixed width types.
++ *
+ * .tree: Only valid when the instance is in tree form.
+ *
+ * Note that accesses from other threads could result in
+@@ -365,6 +384,7 @@ g_variant_to_serialised (GVariant *value)
+ (gpointer) value->contents.serialised.data,
+ value->size,
+ value->depth,
++ value->contents.serialised.ordered_offsets_up_to,
+ };
+ return serialised;
+ }
+@@ -396,6 +416,7 @@ g_variant_serialise (GVariant *value,
+ serialised.size = value->size;
+ serialised.data = data;
+ serialised.depth = value->depth;
++ serialised.ordered_offsets_up_to = 0;
+
+ children = (gpointer *) value->contents.tree.children;
+ n_children = value->contents.tree.n_children;
+@@ -439,6 +460,15 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
+ g_assert (serialised->size == value->size);
+ serialised->depth = value->depth;
+
++ if (value->state & STATE_SERIALISED)
++ {
++ serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
++ }
++ else
++ {
++ serialised->ordered_offsets_up_to = 0;
++ }
++
+ if (serialised->data)
+ /* g_variant_store() is a public API, so it
+ * it will reacquire the lock if it needs to.
+@@ -481,6 +511,7 @@ g_variant_ensure_serialised (GVariant *value)
+ bytes = g_bytes_new_take (data, value->size);
+ value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
+ value->contents.serialised.bytes = bytes;
++ value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
+ value->state |= STATE_SERIALISED;
+ }
+ }
+@@ -561,6 +592,7 @@ g_variant_new_from_bytes (const GVariantType *type,
+ serialised.type_info = value->type_info;
+ serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
+ serialised.depth = 0;
++ serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
+
+ if (!g_variant_serialised_check (serialised))
+ {
+@@ -610,6 +642,8 @@ g_variant_new_from_bytes (const GVariantType *type,
+ value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
+ }
+
++ value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
++
+ g_clear_pointer (&owned_bytes, g_bytes_unref);
+
+ return value;
+@@ -1108,6 +1142,7 @@ g_variant_get_child_value (GVariant *value,
+ child->contents.serialised.bytes =
+ g_bytes_ref (value->contents.serialised.bytes);
+ child->contents.serialised.data = s_child.data;
++ child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
+
+ return child;
+ }
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index c7c2114..fe0b1a4 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -1,6 +1,7 @@
+ /*
+ * Copyright © 2007, 2008 Ryan Lortie
+ * Copyright © 2010 Codethink Limited
++ * Copyright © 2020 William Manley
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -264,6 +265,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
+ value.type_info = g_variant_type_info_element (value.type_info);
+ g_variant_type_info_ref (value.type_info);
+ value.depth++;
++ value.ordered_offsets_up_to = 0;
+
+ return value;
+ }
+@@ -295,7 +297,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
+ {
+ if (n_children)
+ {
+- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1 };
++ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
+
+ gvs_filler (&child, children[0]);
+ }
+@@ -317,6 +319,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
+ /* proper element size: "Just". recurse to the child. */
+ value.type_info = g_variant_type_info_element (value.type_info);
+ value.depth++;
++ value.ordered_offsets_up_to = 0;
+
+ return g_variant_serialised_is_normal (value);
+ }
+@@ -358,6 +361,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
+ value.data = NULL;
+
+ value.depth++;
++ value.ordered_offsets_up_to = 0;
+
+ return value;
+ }
+@@ -388,7 +392,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
+ {
+ if (n_children)
+ {
+- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1 };
++ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
+
+ /* write the data for the child. */
+ gvs_filler (&child, children[0]);
+@@ -408,6 +412,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
+ value.type_info = g_variant_type_info_element (value.type_info);
+ value.size--;
+ value.depth++;
++ value.ordered_offsets_up_to = 0;
+
+ return g_variant_serialised_is_normal (value);
+ }
+@@ -691,6 +696,32 @@ gvs_variable_sized_array_n_children (GVariantSerialised value)
+ return gvs_variable_sized_array_get_frame_offsets (value).length;
+ }
+
++/* Find the index of the first out-of-order element in @data, assuming that
++ * @data is an array of elements of given @type, starting at index @start and
++ * containing a further @len-@start elements. */
++#define DEFINE_FIND_UNORDERED(type) \
++ static gsize \
++ find_unordered_##type (const guint8 *data, gsize start, gsize len) \
++ { \
++ gsize off; \
++ type current, previous; \
++ \
++ memcpy (&previous, data + start * sizeof (current), sizeof (current)); \
++ for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \
++ { \
++ memcpy (&current, data + off, sizeof (current)); \
++ if (current < previous) \
++ break; \
++ previous = current; \
++ } \
++ return off / sizeof (current) - 1; \
++ }
++
++DEFINE_FIND_UNORDERED (guint8);
++DEFINE_FIND_UNORDERED (guint16);
++DEFINE_FIND_UNORDERED (guint32);
++DEFINE_FIND_UNORDERED (guint64);
++
+ static GVariantSerialised
+ gvs_variable_sized_array_get_child (GVariantSerialised value,
+ gsize index_)
+@@ -706,6 +737,49 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
+ g_variant_type_info_ref (child.type_info);
+ child.depth = value.depth + 1;
+
++ /* If the requested @index_ is beyond the set of indices whose framing offsets
++ * have been checked, check the remaining offsets to see whether they’re
++ * normal (in order, no overlapping array elements). */
++ if (index_ > value.ordered_offsets_up_to)
++ {
++ switch (offsets.offset_size)
++ {
++ case 1:
++ {
++ value.ordered_offsets_up_to = find_unordered_guint8 (
++ offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ break;
++ }
++ case 2:
++ {
++ value.ordered_offsets_up_to = find_unordered_guint16 (
++ offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ break;
++ }
++ case 4:
++ {
++ value.ordered_offsets_up_to = find_unordered_guint32 (
++ offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ break;
++ }
++ case 8:
++ {
++ value.ordered_offsets_up_to = find_unordered_guint64 (
++ offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ break;
++ }
++ default:
++ /* gvs_get_offset_size() only returns maximum 8 */
++ g_assert_not_reached ();
++ }
++ }
++
++ if (index_ > value.ordered_offsets_up_to)
++ {
++ /* Offsets are invalid somewhere, so return an empty child. */
++ return child;
++ }
++
+ if (index_ > 0)
+ {
+ guint alignment;
+@@ -840,6 +914,9 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+
+ g_assert (offset == offsets.data_size);
+
++ /* All offsets have now been checked. */
++ value.ordered_offsets_up_to = G_MAXSIZE;
++
+ return TRUE;
+ }
+
+@@ -1072,7 +1149,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
+ for (i = 0; i < length; i++)
+ {
+ const GVariantMemberInfo *member_info;
+- GVariantSerialised child;
++ GVariantSerialised child = { 0, };
+ gsize fixed_size;
+ guint alignment;
+ gsize end;
+@@ -1132,6 +1209,9 @@ gvs_tuple_is_normal (GVariantSerialised value)
+ offset = end;
+ }
+
++ /* All element bounds have been checked above. */
++ value.ordered_offsets_up_to = G_MAXSIZE;
++
+ {
+ gsize fixed_size;
+ guint alignment;
+diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
+index 81343e9..99d18ef 100644
+--- a/glib/gvariant-serialiser.h
++++ b/glib/gvariant-serialiser.h
+@@ -29,6 +29,14 @@ typedef struct
+ guchar *data;
+ gsize size;
+ gsize depth; /* same semantics as GVariant.depth */
++ /* If ordered_offsets_up_to == n this means that all the frame offsets up to and
++ * including the frame offset determining the end of element n are in order.
++ * This guarantees that the bytes of element n don't overlap with any previous
++ * element.
++ *
++ * This is both read and set by g_variant_serialised_get_child for arrays of
++ * non-fixed-width types */
++ gsize ordered_offsets_up_to;
+ } GVariantSerialised;
+
+ /* deserialisation */
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index 0e5ec8e..967e9a1 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -1,5 +1,6 @@
+ /*
+ * Copyright © 2010 Codethink Limited
++ * Copyright © 2020 William Manley
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -1283,6 +1284,7 @@ random_instance_filler (GVariantSerialised *serialised,
+ serialised->size = instance->size;
+
+ serialised->depth = 0;
++ serialised->ordered_offsets_up_to = 0;
+
+ g_assert_true (serialised->type_info == instance->type_info);
+ g_assert_cmpuint (serialised->size, ==, instance->size);
+@@ -5039,6 +5041,47 @@ test_normal_checking_array_offsets (void)
+ g_variant_unref (variant);
+ }
+
++/* This is a regression test that we can't have non-normal values that take up
++ * significantly more space than the normal equivalent, by specifying the
++ * offset table entries so that array elements overlap.
++ *
++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
++static void
++test_normal_checking_array_offsets2 (void)
++{
++ const guint8 data[] = {
++ 'h', 'i', '\0',
++ 0x03, 0x00, 0x03,
++ 0x06, 0x00, 0x06,
++ 0x09, 0x00, 0x09,
++ 0x0c, 0x00, 0x0c,
++ 0x0f, 0x00, 0x0f,
++ 0x12, 0x00, 0x12,
++ 0x15, 0x00, 0x15,
++ };
++ gsize size = sizeof (data);
++ const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
++ GVariant *variant = NULL;
++ GVariant *normal_variant = NULL;
++ GVariant *expected = NULL;
++
++ variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
++ g_assert_nonnull (variant);
++
++ normal_variant = g_variant_get_normal_form (variant);
++ g_assert_nonnull (normal_variant);
++ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
++
++ expected = g_variant_new_parsed (
++ "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
++ g_assert_cmpvariant (expected, variant);
++ g_assert_cmpvariant (expected, normal_variant);
++
++ g_variant_unref (expected);
++ g_variant_unref (normal_variant);
++ g_variant_unref (variant);
++}
++
+ /* Test that a tuple with invalidly large values in its offset table is
+ * normalised successfully without looping infinitely. */
+ static void
+@@ -5206,6 +5249,8 @@ main (int argc, char **argv)
+ test_normal_checking_tuples);
+ g_test_add_func ("/gvariant/normal-checking/array-offsets",
+ test_normal_checking_array_offsets);
++ g_test_add_func ("/gvariant/normal-checking/array-offsets2",
++ test_normal_checking_array_offsets2);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
+ test_normal_checking_tuple_offsets);
+ g_test_add_func ("/gvariant/normal-checking/empty-object-path",
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
new file mode 100644
index 0000000000..c057729aae
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
@@ -0,0 +1,113 @@
+From 345cae9c1aa7bf6752039225ef4c8d8d69fa8d76 Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Fri, 11 Aug 2023 04:09:12 +0000
+Subject: [PATCH] gvariant-serialiser: Factor out code to get bounds of a tuple
+ member
+
+This introduces no functional changes.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/345cae9c1aa7bf6752039225ef4c8d8d69fa8d76]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-serialiser.c | 73 ++++++++++++++++++++++++--------------
+ 1 file changed, 46 insertions(+), 27 deletions(-)
+
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index fe0b1a4..6f9b366 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -942,6 +942,51 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+ * for the tuple. See the notes in gvarianttypeinfo.h.
+ */
+
++static void
++gvs_tuple_get_member_bounds (GVariantSerialised value,
++ gsize index_,
++ gsize offset_size,
++ gsize *out_member_start,
++ gsize *out_member_end)
++{
++ const GVariantMemberInfo *member_info;
++ gsize member_start, member_end;
++
++ member_info = g_variant_type_info_member_info (value.type_info, index_);
++
++ if (member_info->i + 1)
++ member_start = gvs_read_unaligned_le (value.data + value.size -
++ offset_size * (member_info->i + 1),
++ offset_size);
++ else
++ member_start = 0;
++
++ member_start += member_info->a;
++ member_start &= member_info->b;
++ member_start |= member_info->c;
++
++ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
++ member_end = value.size - offset_size * (member_info->i + 1);
++
++ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
++ {
++ gsize fixed_size;
++
++ g_variant_type_info_query (member_info->type_info, NULL, &fixed_size);
++ member_end = member_start + fixed_size;
++ }
++
++ else /* G_VARIANT_MEMBER_ENDING_OFFSET */
++ member_end = gvs_read_unaligned_le (value.data + value.size -
++ offset_size * (member_info->i + 2),
++ offset_size);
++
++ if (out_member_start != NULL)
++ *out_member_start = member_start;
++ if (out_member_end != NULL)
++ *out_member_end = member_end;
++}
++
+ static gsize
+ gvs_tuple_n_children (GVariantSerialised value)
+ {
+@@ -997,33 +1042,7 @@ gvs_tuple_get_child (GVariantSerialised value,
+ }
+ }
+
+- if (member_info->i + 1)
+- start = gvs_read_unaligned_le (value.data + value.size -
+- offset_size * (member_info->i + 1),
+- offset_size);
+- else
+- start = 0;
+-
+- start += member_info->a;
+- start &= member_info->b;
+- start |= member_info->c;
+-
+- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
+- end = value.size - offset_size * (member_info->i + 1);
+-
+- else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
+- {
+- gsize fixed_size;
+-
+- g_variant_type_info_query (child.type_info, NULL, &fixed_size);
+- end = start + fixed_size;
+- child.size = fixed_size;
+- }
+-
+- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
+- end = gvs_read_unaligned_le (value.data + value.size -
+- offset_size * (member_info->i + 2),
+- offset_size);
++ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
+
+ /* The child should not extend into the offset table. */
+ if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch
new file mode 100644
index 0000000000..7e516b07ab
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch
@@ -0,0 +1,80 @@
+From 73d0aa81c2575a5c9ae77dcb94da919579014fc0 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Fri, 11 Aug 2023 04:13:02 +0000
+Subject: [PATCH] gvariant-serialiser: Rework child size calculation
+
+This reduces a few duplicate calls to `g_variant_type_info_query()` and
+explains why they’re needed.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/73d0aa81c2575a5c9ae77dcb94da919579014fc0]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-serialiser.c | 31 +++++++++----------------------
+ 1 file changed, 9 insertions(+), 22 deletions(-)
+
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index 6f9b366..fb75923 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -1007,14 +1007,18 @@ gvs_tuple_get_child (GVariantSerialised value,
+ child.depth = value.depth + 1;
+ offset_size = gvs_get_offset_size (value.size);
+
++ /* Ensure the size is set for fixed-sized children, or
++ * g_variant_serialised_check() will fail, even if we return
++ * (child.data == NULL) to indicate an error. */
++ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
++ g_variant_type_info_query (child.type_info, NULL, &child.size);
++
+ /* tuples are the only (potentially) fixed-sized containers, so the
+ * only ones that have to deal with the possibility of having %NULL
+ * data with a non-zero %size if errors occurred elsewhere.
+ */
+ if G_UNLIKELY (value.data == NULL && value.size != 0)
+ {
+- g_variant_type_info_query (child.type_info, NULL, &child.size);
+-
+ /* this can only happen in fixed-sized tuples,
+ * so the child must also be fixed sized.
+ */
+@@ -1032,29 +1036,12 @@ gvs_tuple_get_child (GVariantSerialised value,
+ else
+ {
+ if (offset_size * (member_info->i + 1) > value.size)
+- {
+- /* if the child is fixed size, return its size.
+- * if child is not fixed-sized, return size = 0.
+- */
+- g_variant_type_info_query (child.type_info, NULL, &child.size);
+-
+- return child;
+- }
++ return child;
+ }
+
+- gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
+-
+ /* The child should not extend into the offset table. */
+- if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
+- {
+- GVariantSerialised last_child;
+- last_child = gvs_tuple_get_child (value,
+- g_variant_type_info_n_members (value.type_info) - 1);
+- last_end = last_child.data + last_child.size - value.data;
+- g_variant_type_info_unref (last_child.type_info);
+- }
+- else
+- last_end = end;
++ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
++ gvs_tuple_get_member_bounds (value, g_variant_type_info_n_members (value.type_info) - 1, offset_size, NULL, &last_end);
+
+ if (start < end && end <= value.size && end <= last_end)
+ {
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
new file mode 100644
index 0000000000..8558a7911f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
@@ -0,0 +1,396 @@
+From 7cf6f5b69146d20948d42f0c476688fe17fef787 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 16 Aug 2023 12:09:06 +0000
+Subject: [PATCH] gvariant: Don't allow child elements of a tuple to overlap
+ each other
+
+This is similar to the earlier commit which prevents child elements of a
+variable-sized array from overlapping each other, but this time for
+tuples. It is based heavily on ideas by William Manley.
+
+Tuples are slightly different from variable-sized arrays in that they
+contain a mixture of fixed and variable sized elements. All but one of
+the variable sized elements have an entry in the frame offsets table.
+This means that if we were to just check the ordering of the frame
+offsets table, the variable sized elements could still overlap
+interleaving fixed sized elements, which would be bad.
+
+Therefore we have to check the elements rather than the frame offsets.
+
+The logic of checking the elements up to the index currently being
+requested, and caching the result in `ordered_offsets_up_to`, means that
+the algorithmic cost implications are the same for this commit as for
+variable-sized arrays: an O(N) cost for these checks is amortised out
+over N accesses to O(1) per access.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Fixes: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/7cf6f5b69146d20948d42f0c476688fe17fef787]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-core.c | 6 +-
+ glib/gvariant-serialiser.c | 40 ++++++++
+ glib/gvariant-serialiser.h | 7 +-
+ glib/gvariant.c | 1 +
+ glib/tests/gvariant.c | 181 +++++++++++++++++++++++++++++++++++++
+ 5 files changed, 232 insertions(+), 3 deletions(-)
+
+diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
+index 9b51e15..b951cd9 100644
+--- a/glib/gvariant-core.c
++++ b/glib/gvariant-core.c
+@@ -1,6 +1,7 @@
+ /*
+ * Copyright © 2007, 2008 Ryan Lortie
+ * Copyright © 2010 Codethink Limited
++ * Copyright © 2022 Endless OS Foundation, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -179,7 +180,7 @@ struct _GVariant
+ * offsets themselves.
+ *
+ * This field is only relevant for arrays of non
+- * fixed width types.
++ * fixed width types and for tuples.
+ *
+ * .tree: Only valid when the instance is in tree form.
+ *
+@@ -1117,6 +1118,9 @@ g_variant_get_child_value (GVariant *value,
+ */
+ s_child = g_variant_serialised_get_child (serialised, index_);
+
++ /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
++ value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
++
+ /* Check whether this would cause nesting too deep. If so, return a fake
+ * child. The only situation we expect this to happen in is with a variant,
+ * as all other deeply-nested types have a static type, and hence should
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index fb75923..cd4a3e6 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -942,6 +942,10 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+ * for the tuple. See the notes in gvarianttypeinfo.h.
+ */
+
++/* Note: This doesn’t guarantee that @out_member_end >= @out_member_start; that
++ * condition may not hold true for invalid serialised variants. The caller is
++ * responsible for checking the returned values and handling invalid ones
++ * appropriately. */
+ static void
+ gvs_tuple_get_member_bounds (GVariantSerialised value,
+ gsize index_,
+@@ -1028,6 +1032,42 @@ gvs_tuple_get_child (GVariantSerialised value,
+ return child;
+ }
+
++ /* If the requested @index_ is beyond the set of indices whose framing offsets
++ * have been checked, check the remaining offsets to see whether they’re
++ * normal (in order, no overlapping tuple elements).
++ *
++ * Unlike the checks in gvs_variable_sized_array_get_child(), we have to check
++ * all the tuple *elements* here, not just all the framing offsets, since
++ * tuples contain a mix of elements which use framing offsets and ones which
++ * don’t. None of them are allowed to overlap. */
++ if (index_ > value.ordered_offsets_up_to)
++ {
++ gsize i, prev_i_end = 0;
++
++ if (value.ordered_offsets_up_to > 0)
++ gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
++
++ for (i = value.ordered_offsets_up_to; i <= index_; i++)
++ {
++ gsize i_start, i_end;
++
++ gvs_tuple_get_member_bounds (value, i, offset_size, &i_start, &i_end);
++
++ if (i_start > i_end || i_start < prev_i_end || i_end > value.size)
++ break;
++
++ prev_i_end = i_end;
++ }
++
++ value.ordered_offsets_up_to = i - 1;
++ }
++
++ if (index_ > value.ordered_offsets_up_to)
++ {
++ /* Offsets are invalid somewhere, so return an empty child. */
++ return child;
++ }
++
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
+ {
+ if (offset_size * (member_info->i + 2) > value.size)
+diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
+index 99d18ef..144aec8 100644
+--- a/glib/gvariant-serialiser.h
++++ b/glib/gvariant-serialiser.h
+@@ -34,8 +34,11 @@ typedef struct
+ * This guarantees that the bytes of element n don't overlap with any previous
+ * element.
+ *
+- * This is both read and set by g_variant_serialised_get_child for arrays of
+- * non-fixed-width types */
++ * This is both read and set by g_variant_serialised_get_child() for arrays of
++ * non-fixed-width types, and for tuples.
++ *
++ * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
++ * rather than an index into the frame offsets. */
+ gsize ordered_offsets_up_to;
+ } GVariantSerialised;
+
+diff --git a/glib/gvariant.c b/glib/gvariant.c
+index d6f68a9..cdb428e 100644
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value)
+ serialised.type_info = g_variant_get_type_info (trusted);
+ serialised.size = g_variant_get_size (trusted);
+ serialised.data = g_malloc (serialised.size);
++ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
+ g_variant_store (trusted, serialised.data);
+ g_variant_unref (trusted);
+
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index 967e9a1..a84b02e 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -1,6 +1,7 @@
+ /*
+ * Copyright © 2010 Codethink Limited
+ * Copyright © 2020 William Manley
++ * Copyright © 2022 Endless OS Foundation, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+@@ -1451,6 +1452,7 @@ test_maybe (void)
+ serialised.data = flavoured_malloc (needed_size, flavour);
+ serialised.size = needed_size;
+ serialised.depth = 0;
++ serialised.ordered_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised,
+ random_instance_filler,
+@@ -1574,6 +1576,7 @@ test_array (void)
+ serialised.data = flavoured_malloc (needed_size, flavour);
+ serialised.size = needed_size;
+ serialised.depth = 0;
++ serialised.ordered_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised, random_instance_filler,
+ (gpointer *) instances, n_children);
+@@ -1738,6 +1741,7 @@ test_tuple (void)
+ serialised.data = flavoured_malloc (needed_size, flavour);
+ serialised.size = needed_size;
+ serialised.depth = 0;
++ serialised.ordered_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised, random_instance_filler,
+ (gpointer *) instances, n_children);
+@@ -1834,6 +1838,7 @@ test_variant (void)
+ serialised.data = flavoured_malloc (needed_size, flavour);
+ serialised.size = needed_size;
+ serialised.depth = 0;
++ serialised.ordered_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised, random_instance_filler,
+ (gpointer *) &instance, 1);
+@@ -5106,6 +5111,176 @@ test_normal_checking_tuple_offsets (void)
+ g_variant_unref (variant);
+ }
+
++/* This is a regression test that we can't have non-normal values that take up
++ * significantly more space than the normal equivalent, by specifying the
++ * offset table entries so that tuple elements overlap.
++ *
++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
++ * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
++static void
++test_normal_checking_tuple_offsets2 (void)
++{
++ const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
++ const guint8 data[] = {
++ 0x12, 0x34, 0x56, 0x78, 0x01,
++ /*
++ ^───────────────────┘
++
++ ^^^^^^^^^^ 1st yy
++ ^^^^^^^^^^ 2nd yy
++ ^^^^^^^^^^ 3rd yy
++ ^^^^ Framing offsets
++ */
++
++ /* If this variant was encoded normally, it would be something like this:
++ * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX
++ * ^─────────────────────────────────────────────────────┘
++ *
++ * ^^^^^^^^^^ 1st yy
++ * ^^^^^^^^^^ 2nd yy
++ * ^^^^^^^^^^ 3rd yy
++ * ^^^^ Framing offsets
++ */
++ };
++ gsize size = sizeof (data);
++ GVariant *variant = NULL;
++ GVariant *normal_variant = NULL;
++ GVariant *expected = NULL;
++
++ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
++ g_assert_nonnull (variant);
++
++ normal_variant = g_variant_get_normal_form (variant);
++ g_assert_nonnull (normal_variant);
++ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
++
++ expected = g_variant_new_parsed (
++ "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
++ g_assert_cmpvariant (expected, variant);
++ g_assert_cmpvariant (expected, normal_variant);
++
++ g_variant_unref (expected);
++ g_variant_unref (normal_variant);
++ g_variant_unref (variant);
++}
++
++/* This is a regression test that overlapping entries in the offset table are
++ * decoded consistently, even though they’re non-normal.
++ *
++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
++static void
++test_normal_checking_tuple_offsets3 (void)
++{
++ /* The expected decoding of this non-normal byte stream is complex. See
++ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
++ * specification.
++ *
++ * The rule “Child Values Overlapping Framing Offsets” from the specification
++ * says that the first `ay` must be decoded as `[0x01]` even though it
++ * overlaps the first byte of the offset table. However, since commit
++ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
++ * this as it’s exploitable. So the first `ay` must be given a default value.
++ *
++ * The second and third `ay`s must be given default values because of rule
++ * “End Boundary Precedes Start Boundary”.
++ *
++ * The `i` must be given a default value because of rule “Start or End
++ * Boundary of a Child Falls Outside the Container”.
++ */
++ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
++ const guint8 data[] = {
++ 0x01, 0x00, 0x02,
++ /*
++ ^──┘
++
++ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
++ 2nd ay, bytes 2-0
++ i, bytes 0-4
++ 3rd ay, bytes 4-1
++ ^^^^^^^^^^ Framing offsets
++ */
++ };
++ gsize size = sizeof (data);
++ GVariant *variant = NULL;
++ GVariant *normal_variant = NULL;
++ GVariant *expected = NULL;
++
++ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
++ g_assert_nonnull (variant);
++
++ g_assert_false (g_variant_is_normal_form (variant));
++
++ normal_variant = g_variant_get_normal_form (variant);
++ g_assert_nonnull (normal_variant);
++ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
++
++ expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
++ g_assert_cmpvariant (expected, variant);
++ g_assert_cmpvariant (expected, normal_variant);
++
++ g_variant_unref (expected);
++ g_variant_unref (normal_variant);
++ g_variant_unref (variant);
++}
++
++/* This is a regression test that overlapping entries in the offset table are
++ * decoded consistently, even though they’re non-normal.
++ *
++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
++static void
++test_normal_checking_tuple_offsets4 (void)
++{
++ /* The expected decoding of this non-normal byte stream is complex. See
++ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
++ * specification.
++ *
++ * The rule “Child Values Overlapping Framing Offsets” from the specification
++ * says that the first `ay` must be decoded as `[0x01]` even though it
++ * overlaps the first byte of the offset table. However, since commit
++ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
++ * this as it’s exploitable. So the first `ay` must be given a default value.
++ *
++ * The second `ay` must be given a default value because of rule “End Boundary
++ * Precedes Start Boundary”.
++ *
++ * The third `ay` must be given a default value because its framing offsets
++ * overlap that of the first `ay`.
++ */
++ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
++ const guint8 data[] = {
++ 0x01, 0x00, 0x02,
++ /*
++ ^──┘
++
++ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
++ 2nd ay, bytes 2-0
++ 3rd ay, bytes 0-1
++ ^^^^^^^^^^ Framing offsets
++ */
++ };
++ gsize size = sizeof (data);
++ GVariant *variant = NULL;
++ GVariant *normal_variant = NULL;
++ GVariant *expected = NULL;
++
++ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
++ g_assert_nonnull (variant);
++
++ g_assert_false (g_variant_is_normal_form (variant));
++
++ normal_variant = g_variant_get_normal_form (variant);
++ g_assert_nonnull (normal_variant);
++ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
++
++ expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
++ g_assert_cmpvariant (expected, variant);
++ g_assert_cmpvariant (expected, normal_variant);
++
++ g_variant_unref (expected);
++ g_variant_unref (normal_variant);
++ g_variant_unref (variant);
++}
++
+ /* Test that an empty object path is normalised successfully to the base object
+ * path, ‘/’. */
+ static void
+@@ -5253,6 +5428,12 @@ main (int argc, char **argv)
+ test_normal_checking_array_offsets2);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
+ test_normal_checking_tuple_offsets);
++ g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
++ test_normal_checking_tuple_offsets2);
++ g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
++ test_normal_checking_tuple_offsets3);
++ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
++ test_normal_checking_tuple_offsets4);
+ g_test_add_func ("/gvariant/normal-checking/empty-object-path",
+ test_normal_checking_empty_object_path);
+
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch
new file mode 100644
index 0000000000..83d0205160
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch
@@ -0,0 +1,49 @@
+From e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Wed, 16 Aug 2023 03:42:47 +0000
+Subject: [PATCH] gvariant: Port g_variant_deep_copy() to count its iterations
+ directly
+
+This is equivalent to what `GVariantIter` does, but it means that
+`g_variant_deep_copy()` is making its own `g_variant_get_child_value()`
+calls.
+
+This will be useful in an upcoming commit, where those child values will
+be inspected a little more deeply.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/glib/gvariant.c b/glib/gvariant.c
+index cdb428e..fdd36be 100644
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -5799,14 +5799,13 @@ g_variant_deep_copy (GVariant *value)
+ case G_VARIANT_CLASS_VARIANT:
+ {
+ GVariantBuilder builder;
+- GVariantIter iter;
+- GVariant *child;
++ gsize i, n_children;
+
+ g_variant_builder_init (&builder, g_variant_get_type (value));
+- g_variant_iter_init (&iter, value);
+
+- while ((child = g_variant_iter_next_value (&iter)))
++ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
+ {
++ GVariant *child = g_variant_get_child_value (value, i);
+ g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
+ g_variant_unref (child);
+ }
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
new file mode 100644
index 0000000000..f098548618
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
@@ -0,0 +1,394 @@
+From d1a293c4e29880b8d17bb826c9a426a440ca4a91 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 17 Aug 2023 01:30:38 +0000
+Subject: [PATCH] gvariant: Track checked and ordered offsets independently
+
+The past few commits introduced the concept of known-good offsets in the
+offset table (which is used for variable-width arrays and tuples).
+Good offsets are ones which are non-overlapping with all the previous
+offsets in the table.
+
+If a bad offset is encountered when indexing into the array or tuple,
+the cached known-good offset index will not be increased. In this way,
+all child variants at and beyond the first bad offset can be returned as
+default values rather than dereferencing potentially invalid data.
+
+In this case, there was no information about the fact that the indexes
+between the highest known-good index and the requested one had been
+checked already. That could lead to a pathological case where an offset
+table with an invalid first offset is repeatedly checked in full when
+trying to access higher-indexed children.
+
+Avoid that by storing the index of the highest checked offset in the
+table, as well as the index of the highest good/ordered offset.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/d1a293c4e29880b8d17bb826c9a426a440ca4a91]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant-core.c | 28 ++++++++++++++++++++++++
+ glib/gvariant-serialiser.c | 44 +++++++++++++++++++++++++++-----------
+ glib/gvariant-serialiser.h | 9 ++++++++
+ glib/gvariant.c | 1 +
+ glib/tests/gvariant.c | 5 +++++
+ 5 files changed, 75 insertions(+), 12 deletions(-)
+
+diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
+index b951cd9..1b9d5cc 100644
+--- a/glib/gvariant-core.c
++++ b/glib/gvariant-core.c
+@@ -67,6 +67,7 @@ struct _GVariant
+ GBytes *bytes;
+ gconstpointer data;
+ gsize ordered_offsets_up_to;
++ gsize checked_offsets_up_to;
+ } serialised;
+
+ struct
+@@ -182,6 +183,24 @@ struct _GVariant
+ * This field is only relevant for arrays of non
+ * fixed width types and for tuples.
+ *
++ * .checked_offsets_up_to: Similarly to .ordered_offsets_up_to, this stores
++ * the index of the highest element, n, whose frame
++ * offsets (and all the preceding frame offsets)
++ * have been checked for validity.
++ *
++ * It is always the case that
++ * .checked_offsets_up_to ≥ .ordered_offsets_up_to.
++ *
++ * If .checked_offsets_up_to == .ordered_offsets_up_to,
++ * then a bad offset has not been found so far.
++ *
++ * If .checked_offsets_up_to > .ordered_offsets_up_to,
++ * then a bad offset has been found at
++ * (.ordered_offsets_up_to + 1).
++ *
++ * This field is only relevant for arrays of non
++ * fixed width types and for tuples.
++ *
+ * .tree: Only valid when the instance is in tree form.
+ *
+ * Note that accesses from other threads could result in
+@@ -386,6 +405,7 @@ g_variant_to_serialised (GVariant *value)
+ value->size,
+ value->depth,
+ value->contents.serialised.ordered_offsets_up_to,
++ value->contents.serialised.checked_offsets_up_to,
+ };
+ return serialised;
+ }
+@@ -418,6 +438,7 @@ g_variant_serialise (GVariant *value,
+ serialised.data = data;
+ serialised.depth = value->depth;
+ serialised.ordered_offsets_up_to = 0;
++ serialised.checked_offsets_up_to = 0;
+
+ children = (gpointer *) value->contents.tree.children;
+ n_children = value->contents.tree.n_children;
+@@ -464,10 +485,12 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
+ if (value->state & STATE_SERIALISED)
+ {
+ serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
++ serialised->checked_offsets_up_to = value->contents.serialised.checked_offsets_up_to;
+ }
+ else
+ {
+ serialised->ordered_offsets_up_to = 0;
++ serialised->checked_offsets_up_to = 0;
+ }
+
+ if (serialised->data)
+@@ -513,6 +536,7 @@ g_variant_ensure_serialised (GVariant *value)
+ value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
+ value->contents.serialised.bytes = bytes;
+ value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
++ value->contents.serialised.checked_offsets_up_to = G_MAXSIZE;
+ value->state |= STATE_SERIALISED;
+ }
+ }
+@@ -594,6 +618,7 @@ g_variant_new_from_bytes (const GVariantType *type,
+ serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
+ serialised.depth = 0;
+ serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
++ serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
+
+ if (!g_variant_serialised_check (serialised))
+ {
+@@ -644,6 +669,7 @@ g_variant_new_from_bytes (const GVariantType *type,
+ }
+
+ value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
++ value->contents.serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
+
+ g_clear_pointer (&owned_bytes, g_bytes_unref);
+
+@@ -1120,6 +1146,7 @@ g_variant_get_child_value (GVariant *value,
+
+ /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
+ value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
++ value->contents.serialised.checked_offsets_up_to = MAX (value->contents.serialised.checked_offsets_up_to, serialised.checked_offsets_up_to);
+
+ /* Check whether this would cause nesting too deep. If so, return a fake
+ * child. The only situation we expect this to happen in is with a variant,
+@@ -1147,6 +1174,7 @@ g_variant_get_child_value (GVariant *value,
+ g_bytes_ref (value->contents.serialised.bytes);
+ child->contents.serialised.data = s_child.data;
+ child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
++ child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
+
+ return child;
+ }
+diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
+index cd4a3e6..0bf7243 100644
+--- a/glib/gvariant-serialiser.c
++++ b/glib/gvariant-serialiser.c
+@@ -120,6 +120,8 @@
+ *
+ * @depth has no restrictions; the depth of a top-level serialised #GVariant is
+ * zero, and it increases for each level of nested child.
++ *
++ * @checked_offsets_up_to is always ≥ @ordered_offsets_up_to
+ */
+
+ /* < private >
+@@ -147,6 +149,9 @@ g_variant_serialised_check (GVariantSerialised serialised)
+ !(serialised.size == 0 || serialised.data != NULL))
+ return FALSE;
+
++ if (serialised.ordered_offsets_up_to > serialised.checked_offsets_up_to)
++ return FALSE;
++
+ /* Depending on the native alignment requirements of the machine, the
+ * compiler will insert either 3 or 7 padding bytes after the char.
+ * This will result in the sizeof() the struct being 12 or 16.
+@@ -266,6 +271,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
+ g_variant_type_info_ref (value.type_info);
+ value.depth++;
+ value.ordered_offsets_up_to = 0;
++ value.checked_offsets_up_to = 0;
+
+ return value;
+ }
+@@ -297,7 +303,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
+ {
+ if (n_children)
+ {
+- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
++ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0, 0 };
+
+ gvs_filler (&child, children[0]);
+ }
+@@ -320,6 +326,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
+ value.type_info = g_variant_type_info_element (value.type_info);
+ value.depth++;
+ value.ordered_offsets_up_to = 0;
++ value.checked_offsets_up_to = 0;
+
+ return g_variant_serialised_is_normal (value);
+ }
+@@ -362,6 +369,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
+
+ value.depth++;
+ value.ordered_offsets_up_to = 0;
++ value.checked_offsets_up_to = 0;
+
+ return value;
+ }
+@@ -392,7 +400,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
+ {
+ if (n_children)
+ {
+- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
++ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0, 0 };
+
+ /* write the data for the child. */
+ gvs_filler (&child, children[0]);
+@@ -413,6 +421,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
+ value.size--;
+ value.depth++;
+ value.ordered_offsets_up_to = 0;
++ value.checked_offsets_up_to = 0;
+
+ return g_variant_serialised_is_normal (value);
+ }
+@@ -739,39 +748,46 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
+
+ /* If the requested @index_ is beyond the set of indices whose framing offsets
+ * have been checked, check the remaining offsets to see whether they’re
+- * normal (in order, no overlapping array elements). */
+- if (index_ > value.ordered_offsets_up_to)
++ * normal (in order, no overlapping array elements).
++ *
++ * Don’t bother checking if the highest known-good offset is lower than the
++ * highest checked offset, as that means there’s an invalid element at that
++ * index, so there’s no need to check further. */
++ if (index_ > value.checked_offsets_up_to &&
++ value.ordered_offsets_up_to == value.checked_offsets_up_to)
+ {
+ switch (offsets.offset_size)
+ {
+ case 1:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint8 (
+- offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ offsets.array, value.checked_offsets_up_to, index_ + 1);
+ break;
+ }
+ case 2:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint16 (
+- offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ offsets.array, value.checked_offsets_up_to, index_ + 1);
+ break;
+ }
+ case 4:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint32 (
+- offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ offsets.array, value.checked_offsets_up_to, index_ + 1);
+ break;
+ }
+ case 8:
+ {
+ value.ordered_offsets_up_to = find_unordered_guint64 (
+- offsets.array, value.ordered_offsets_up_to, index_ + 1);
++ offsets.array, value.checked_offsets_up_to, index_ + 1);
+ break;
+ }
+ default:
+ /* gvs_get_offset_size() only returns maximum 8 */
+ g_assert_not_reached ();
+ }
++
++ value.checked_offsets_up_to = index_;
+ }
+
+ if (index_ > value.ordered_offsets_up_to)
+@@ -916,6 +932,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
+
+ /* All offsets have now been checked. */
+ value.ordered_offsets_up_to = G_MAXSIZE;
++ value.checked_offsets_up_to = G_MAXSIZE;
+
+ return TRUE;
+ }
+@@ -1040,14 +1057,15 @@ gvs_tuple_get_child (GVariantSerialised value,
+ * all the tuple *elements* here, not just all the framing offsets, since
+ * tuples contain a mix of elements which use framing offsets and ones which
+ * don’t. None of them are allowed to overlap. */
+- if (index_ > value.ordered_offsets_up_to)
++ if (index_ > value.checked_offsets_up_to &&
++ value.ordered_offsets_up_to == value.checked_offsets_up_to)
+ {
+ gsize i, prev_i_end = 0;
+
+- if (value.ordered_offsets_up_to > 0)
+- gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
++ if (value.checked_offsets_up_to > 0)
++ gvs_tuple_get_member_bounds (value, value.checked_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
+
+- for (i = value.ordered_offsets_up_to; i <= index_; i++)
++ for (i = value.checked_offsets_up_to; i <= index_; i++)
+ {
+ gsize i_start, i_end;
+
+@@ -1060,6 +1078,7 @@ gvs_tuple_get_child (GVariantSerialised value,
+ }
+
+ value.ordered_offsets_up_to = i - 1;
++ value.checked_offsets_up_to = index_;
+ }
+
+ if (index_ > value.ordered_offsets_up_to)
+@@ -1257,6 +1276,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
+
+ /* All element bounds have been checked above. */
+ value.ordered_offsets_up_to = G_MAXSIZE;
++ value.checked_offsets_up_to = G_MAXSIZE;
+
+ {
+ gsize fixed_size;
+diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
+index 144aec8..e132451 100644
+--- a/glib/gvariant-serialiser.h
++++ b/glib/gvariant-serialiser.h
+@@ -40,6 +40,15 @@ typedef struct
+ * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
+ * rather than an index into the frame offsets. */
+ gsize ordered_offsets_up_to;
++
++ /* Similar to @ordered_offsets_up_to. This gives the index of the child element
++ * whose frame offset is the highest in the offset table which has been
++ * checked so far.
++ *
++ * This is always ≥ @ordered_offsets_up_to. It is always an element index.
++ *
++ * See documentation in gvariant-core.c for `struct GVariant` for details. */
++ gsize checked_offsets_up_to;
+ } GVariantSerialised;
+
+ /* deserialisation */
+diff --git a/glib/gvariant.c b/glib/gvariant.c
+index fdd36be..f910bd4 100644
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value)
+ serialised.size = g_variant_get_size (trusted);
+ serialised.data = g_malloc (serialised.size);
+ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
++ serialised.checked_offsets_up_to = G_MAXSIZE;
+ g_variant_store (trusted, serialised.data);
+ g_variant_unref (trusted);
+
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index a84b02e..640f3c0 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -1286,6 +1286,7 @@ random_instance_filler (GVariantSerialised *serialised,
+
+ serialised->depth = 0;
+ serialised->ordered_offsets_up_to = 0;
++ serialised->checked_offsets_up_to = 0;
+
+ g_assert_true (serialised->type_info == instance->type_info);
+ g_assert_cmpuint (serialised->size, ==, instance->size);
+@@ -1453,6 +1454,7 @@ test_maybe (void)
+ serialised.size = needed_size;
+ serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
++ serialised.checked_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised,
+ random_instance_filler,
+@@ -1577,6 +1579,7 @@ test_array (void)
+ serialised.size = needed_size;
+ serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
++ serialised.checked_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised, random_instance_filler,
+ (gpointer *) instances, n_children);
+@@ -1742,6 +1745,7 @@ test_tuple (void)
+ serialised.size = needed_size;
+ serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
++ serialised.checked_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised, random_instance_filler,
+ (gpointer *) instances, n_children);
+@@ -1839,6 +1843,7 @@ test_variant (void)
+ serialised.size = needed_size;
+ serialised.depth = 0;
+ serialised.ordered_offsets_up_to = 0;
++ serialised.checked_offsets_up_to = 0;
+
+ g_variant_serialiser_serialise (serialised, random_instance_filler,
+ (gpointer *) &instance, 1);
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch
new file mode 100644
index 0000000000..a523e60b91
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch
@@ -0,0 +1,97 @@
+From 298a537d5f6783e55d87e40011ee3fd3b22b72f9 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@endlessos.org>
+Date: Thu, 17 Aug 2023 01:39:01 +0000
+Subject: [PATCH] gvariant: Zero-initialise various GVariantSerialised objects
+
+The following few commits will add a couple of new fields to
+`GVariantSerialised`, and they should be zero-filled by default.
+
+Try and pre-empt that a bit by zero-filling `GVariantSerialised` by
+default in a few places.
+
+Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
+
+Helps: #2121
+
+CVE: CVE-2023-32665
+Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/298a537d5f6783e55d87e40011ee3fd3b22b72f9]
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ glib/gvariant.c | 2 +-
+ glib/tests/gvariant.c | 12 ++++++------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/glib/gvariant.c b/glib/gvariant.c
+index f910bd4..8ba701e 100644
+--- a/glib/gvariant.c
++++ b/glib/gvariant.c
+@@ -5936,7 +5936,7 @@ g_variant_byteswap (GVariant *value)
+ if (alignment)
+ /* (potentially) contains multi-byte numeric data */
+ {
+- GVariantSerialised serialised;
++ GVariantSerialised serialised = { 0, };
+ GVariant *trusted;
+ GBytes *bytes;
+
+diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
+index 640f3c0..d640c81 100644
+--- a/glib/tests/gvariant.c
++++ b/glib/tests/gvariant.c
+@@ -1446,7 +1446,7 @@ test_maybe (void)
+
+ for (flavour = 0; flavour < 8; flavour += alignment)
+ {
+- GVariantSerialised serialised;
++ GVariantSerialised serialised = { 0, };
+ GVariantSerialised child;
+
+ serialised.type_info = type_info;
+@@ -1572,7 +1572,7 @@ test_array (void)
+
+ for (flavour = 0; flavour < 8; flavour += alignment)
+ {
+- GVariantSerialised serialised;
++ GVariantSerialised serialised = { 0, };
+
+ serialised.type_info = array_info;
+ serialised.data = flavoured_malloc (needed_size, flavour);
+@@ -1738,7 +1738,7 @@ test_tuple (void)
+
+ for (flavour = 0; flavour < 8; flavour += alignment)
+ {
+- GVariantSerialised serialised;
++ GVariantSerialised serialised = { 0, };
+
+ serialised.type_info = type_info;
+ serialised.data = flavoured_malloc (needed_size, flavour);
+@@ -1835,7 +1835,7 @@ test_variant (void)
+
+ for (flavour = 0; flavour < 8; flavour += alignment)
+ {
+- GVariantSerialised serialised;
++ GVariantSerialised serialised = { 0, };
+ GVariantSerialised child;
+
+ serialised.type_info = type_info;
+@@ -2284,7 +2284,7 @@ serialise_tree (TreeInstance *tree,
+ static void
+ test_byteswap (void)
+ {
+- GVariantSerialised one, two;
++ GVariantSerialised one = { 0, }, two = { 0, };
+ TreeInstance *tree;
+
+ tree = tree_instance_new (NULL, 3);
+@@ -2358,7 +2358,7 @@ test_serialiser_children (void)
+ static void
+ test_fuzz (gdouble *fuzziness)
+ {
+- GVariantSerialised serialised;
++ GVariantSerialised serialised = { 0, };
+ TreeInstance *tree;
+
+ /* make an instance */
+--
+2.24.4
+
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb
index 1a006b9f38..60a6b843c1 100644
--- a/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb
+++ b/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb
@@ -18,6 +18,44 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \
file://tzdata-update.patch \
file://CVE-2020-35457.patch \
+ file://CVE-2021-27218.patch \
+ file://CVE-2021-27219-01.patch \
+ file://CVE-2021-27219-02.patch \
+ file://CVE-2021-27219-03.patch \
+ file://CVE-2021-27219-04.patch \
+ file://CVE-2021-27219-05.patch \
+ file://CVE-2021-27219-06.patch \
+ file://CVE-2021-27219-07.patch \
+ file://CVE-2021-27219-08.patch \
+ file://CVE-2021-27219-09.patch \
+ file://CVE-2021-27219-10.patch \
+ file://CVE-2021-27219-11.patch \
+ file://CVE-2021-27219-reg1-1.patch \
+ file://CVE-2021-27219-reg1-2.patch \
+ file://CVE-2021-27219-reg1-4.patch \
+ file://CVE-2021-27219-reg1-5.patch \
+ file://CVE-2021-27219-reg2-1.patch \
+ file://CVE-2021-27219-reg2-2.patch \
+ file://CVE-2021-27219-reg2-3.patch \
+ file://CVE-2021-28153-1.patch \
+ file://CVE-2021-28153-2.patch \
+ file://CVE-2021-28153-3.patch \
+ file://CVE-2021-28153-4.patch \
+ file://CVE-2021-28153-5.patch \
+ file://CVE-2023-32665-0001.patch \
+ file://CVE-2023-32665-0002.patch \
+ file://CVE-2023-32665-0003.patch \
+ file://CVE-2023-32665-0004.patch \
+ file://CVE-2023-32665-0005.patch \
+ file://CVE-2023-32665-0006.patch \
+ file://CVE-2023-32665-0007.patch \
+ file://CVE-2023-32665-0008.patch \
+ file://CVE-2023-32665-0009.patch \
+ file://CVE-2023-29499.patch \
+ file://CVE-2023-32611-0001.patch \
+ file://CVE-2023-32611-0002.patch \
+ file://CVE-2023-32643.patch \
+ file://CVE-2023-32636.patch \
"
SRC_URI_append_class-native = " file://relocate-modules.patch"
diff --git a/meta/recipes-core/glib-2.0/glib.inc b/meta/recipes-core/glib-2.0/glib.inc
index c3ddf18387..1849a6e05c 100644
--- a/meta/recipes-core/glib-2.0/glib.inc
+++ b/meta/recipes-core/glib-2.0/glib.inc
@@ -4,7 +4,7 @@ HOMEPAGE = "https://developer.gnome.org/glib/"
# pcre is under BSD;
# docs/reference/COPYING is with a 'public domain'-like license!
-LICENSE = "LGPLv2.1+ & BSD & PD"
+LICENSE = "LGPLv2.1+ & BSD-3-Clause & PD"
LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \
file://glib/glib.h;beginline=4;endline=17;md5=b88abb7f3ad09607e71cb9d530155906 \
file://gmodule/COPYING;md5=4fbd65380cdd255951079008b364516c \