summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch104
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch211
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch418
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch114
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch81
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch397
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch50
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch395
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch98
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb9
10 files changed, 1877 insertions, 0 deletions
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..2b7536c42d
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
@@ -0,0 +1,104 @@
1From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 9 Aug 2023 10:04:49 +0000
4Subject: [PATCH] gvariant-core: Consolidate construction of
5 `GVariantSerialised`
6
7So I only need to change it in one place.
8
9This introduces no functional changes.
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14
15Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
16
17Signed-off-by: Soumya <soumya.sambu@windriver.com>
18---
19 glib/gvariant-core.c | 49 ++++++++++++++++++++++----------------------
20 1 file changed, 25 insertions(+), 24 deletions(-)
21
22diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
23index a31d396..496f2e2 100644
24--- a/glib/gvariant-core.c
25+++ b/glib/gvariant-core.c
26@@ -349,6 +349,27 @@ g_variant_ensure_size (GVariant *value)
27 }
28 }
29
30+/* < private >
31+ * g_variant_to_serialised:
32+ * @value: a #GVariant
33+ *
34+ * Gets a GVariantSerialised for a GVariant in state STATE_SERIALISED.
35+ */
36+inline static GVariantSerialised
37+g_variant_to_serialised (GVariant *value)
38+{
39+ g_assert (value->state & STATE_SERIALISED);
40+ {
41+ GVariantSerialised serialised = {
42+ value->type_info,
43+ (gpointer) value->contents.serialised.data,
44+ value->size,
45+ value->depth,
46+ };
47+ return serialised;
48+ }
49+}
50+
51 /* < private >
52 * g_variant_serialise:
53 * @value: a #GVariant
54@@ -1007,16 +1028,8 @@ g_variant_n_children (GVariant *value)
55 g_variant_lock (value);
56
57 if (value->state & STATE_SERIALISED)
58- {
59- GVariantSerialised serialised = {
60- value->type_info,
61- (gpointer) value->contents.serialised.data,
62- value->size,
63- value->depth,
64- };
65-
66- n_children = g_variant_serialised_n_children (serialised);
67- }
68+ n_children = g_variant_serialised_n_children (
69+ g_variant_to_serialised (value));
70 else
71 n_children = value->contents.tree.n_children;
72
73@@ -1083,12 +1096,7 @@ g_variant_get_child_value (GVariant *value,
74 }
75
76 {
77- GVariantSerialised serialised = {
78- value->type_info,
79- (gpointer) value->contents.serialised.data,
80- value->size,
81- value->depth,
82- };
83+ GVariantSerialised serialised = g_variant_to_serialised (value);
84 GVariantSerialised s_child;
85 GVariant *child;
86
87@@ -1201,14 +1209,7 @@ g_variant_is_normal_form (GVariant *value)
88
89 if (value->state & STATE_SERIALISED)
90 {
91- GVariantSerialised serialised = {
92- value->type_info,
93- (gpointer) value->contents.serialised.data,
94- value->size,
95- value->depth
96- };
97-
98- if (g_variant_serialised_is_normal (serialised))
99+ if (g_variant_serialised_is_normal (g_variant_to_serialised (value)))
100 value->state |= STATE_TRUSTED;
101 }
102 else
103--
1042.40.0
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..4eff85a5f3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
@@ -0,0 +1,211 @@
1From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 9 Aug 2023 10:39:34 +0000
4Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
5 framing offsets
6
7This introduces no functional changes.
8
9Helps: #2121
10
11CVE: CVE-2023-32665
12
13Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
14
15Signed-off-by: Soumya <soumya.sambu@windriver.com>
16---
17 glib/gvariant-serialiser.c | 108 +++++++++++++++++++------------------
18 1 file changed, 57 insertions(+), 51 deletions(-)
19
20diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
21index 7b13381..e71248e 100644
22--- a/glib/gvariant-serialiser.c
23+++ b/glib/gvariant-serialiser.c
24@@ -633,30 +633,62 @@ gvs_calculate_total_size (gsize body_size,
25 return body_size + 8 * offsets;
26 }
27
28+struct Offsets
29+{
30+ gsize data_size;
31+
32+ guchar *array;
33+ gsize length;
34+ guint offset_size;
35+
36+ gboolean is_normal;
37+};
38+
39 static gsize
40-gvs_variable_sized_array_n_children (GVariantSerialised value)
41+gvs_offsets_get_offset_n (struct Offsets *offsets,
42+ gsize n)
43+{
44+ return gvs_read_unaligned_le (
45+ offsets->array + (offsets->offset_size * n), offsets->offset_size);
46+}
47+
48+static struct Offsets
49+gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
50 {
51+ struct Offsets out = { 0, };
52 gsize offsets_array_size;
53- gsize offset_size;
54 gsize last_end;
55
56 if (value.size == 0)
57- return 0;
58-
59- offset_size = gvs_get_offset_size (value.size);
60+ {
61+ out.is_normal = TRUE;
62+ return out;
63+ }
64
65- last_end = gvs_read_unaligned_le (value.data + value.size -
66- offset_size, offset_size);
67+ out.offset_size = gvs_get_offset_size (value.size);
68+ last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size,
69+ out.offset_size);
70
71 if (last_end > value.size)
72- return 0;
73+ return out; /* offsets not normal */
74
75 offsets_array_size = value.size - last_end;
76
77- if (offsets_array_size % offset_size)
78- return 0;
79+ if (offsets_array_size % out.offset_size)
80+ return out; /* offsets not normal */
81+
82+ out.data_size = last_end;
83+ out.array = value.data + last_end;
84+ out.length = offsets_array_size / out.offset_size;
85+ out.is_normal = TRUE;
86
87- return offsets_array_size / offset_size;
88+ return out;
89+}
90+
91+static gsize
92+gvs_variable_sized_array_n_children (GVariantSerialised value)
93+{
94+ return gvs_variable_sized_array_get_frame_offsets (value).length;
95 }
96
97 static GVariantSerialised
98@@ -664,8 +696,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
99 gsize index_)
100 {
101 GVariantSerialised child = { 0, };
102- gsize offset_size;
103- gsize last_end;
104+
105+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
106+
107 gsize start;
108 gsize end;
109
110@@ -673,18 +706,11 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
111 g_variant_type_info_ref (child.type_info);
112 child.depth = value.depth + 1;
113
114- offset_size = gvs_get_offset_size (value.size);
115-
116- last_end = gvs_read_unaligned_le (value.data + value.size -
117- offset_size, offset_size);
118-
119 if (index_ > 0)
120 {
121 guint alignment;
122
123- start = gvs_read_unaligned_le (value.data + last_end +
124- (offset_size * (index_ - 1)),
125- offset_size);
126+ start = gvs_offsets_get_offset_n (&offsets, index_ - 1);
127
128 g_variant_type_info_query (child.type_info, &alignment, NULL);
129 start += (-start) & alignment;
130@@ -692,11 +718,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
131 else
132 start = 0;
133
134- end = gvs_read_unaligned_le (value.data + last_end +
135- (offset_size * index_),
136- offset_size);
137+ end = gvs_offsets_get_offset_n (&offsets, index_);
138
139- if (start < end && end <= value.size && end <= last_end)
140+ if (start < end && end <= value.size && end <= offsets.data_size)
141 {
142 child.data = value.data + start;
143 child.size = end - start;
144@@ -768,34 +792,16 @@ static gboolean
145 gvs_variable_sized_array_is_normal (GVariantSerialised value)
146 {
147 GVariantSerialised child = { 0, };
148- gsize offsets_array_size;
149- guchar *offsets_array;
150- guint offset_size;
151 guint alignment;
152- gsize last_end;
153- gsize length;
154 gsize offset;
155 gsize i;
156
157- if (value.size == 0)
158- return TRUE;
159-
160- offset_size = gvs_get_offset_size (value.size);
161- last_end = gvs_read_unaligned_le (value.data + value.size -
162- offset_size, offset_size);
163+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
164
165- if (last_end > value.size)
166+ if (!offsets.is_normal)
167 return FALSE;
168
169- offsets_array_size = value.size - last_end;
170-
171- if (offsets_array_size % offset_size)
172- return FALSE;
173-
174- offsets_array = value.data + value.size - offsets_array_size;
175- length = offsets_array_size / offset_size;
176-
177- if (length == 0)
178+ if (value.size != 0 && offsets.length == 0)
179 return FALSE;
180
181 child.type_info = g_variant_type_info_element (value.type_info);
182@@ -803,14 +809,14 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
183 child.depth = value.depth + 1;
184 offset = 0;
185
186- for (i = 0; i < length; i++)
187+ for (i = 0; i < offsets.length; i++)
188 {
189 gsize this_end;
190
191- this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
192- offset_size);
193+ this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i,
194+ offsets.offset_size);
195
196- if (this_end < offset || this_end > last_end)
197+ if (this_end < offset || this_end > offsets.data_size)
198 return FALSE;
199
200 while (offset & alignment)
201@@ -832,7 +838,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
202 offset = this_end;
203 }
204
205- g_assert (offset == last_end);
206+ g_assert (offset == offsets.data_size);
207
208 return TRUE;
209 }
210--
2112.40.0
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..183c6b20e7
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
@@ -0,0 +1,418 @@
1From ade71fb544391b2e33e1859645726bfee0d5eaaf Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 16 Aug 2023 03:12:21 +0000
4Subject: [PATCH] gvariant: Don't allow child elements to overlap with each
5 other
6
7If different elements of a variable sized array can overlap with each
8other then we can cause a `GVariant` to normalise to a much larger type.
9
10This commit changes the behaviour of `GVariant` with non-normal form data. If
11an invalid frame offset is found all subsequent elements are given their
12default value.
13
14When retrieving an element at index `n` we scan the frame offsets up to index
15`n` and if they are not in order we return an element with the default value
16for that type. This guarantees that elements don't overlap with each
17other. We remember the offset we've scanned up to so we don't need to
18repeat this work on subsequent accesses. We skip these checks for trusted
19data.
20
21Unfortunately this makes random access of untrusted data O(n) — at least
22on first access. It doesn't affect the algorithmic complexity of accessing
23elements in order, such as when using the `GVariantIter` interface. Also:
24the cost of validation will be amortised as the `GVariant` instance is
25continued to be used.
26
27I've implemented this with 4 different functions, 1 for each element size,
28rather than looping calling `gvs_read_unaligned_le` in the hope that the
29compiler will find it easy to optimise and should produce fairly tight
30code.
31
32Fixes: #2121
33
34CVE: CVE-2023-32665
35
36Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/ade71fb544391b2e33e1859645726bfee0d5eaaf]
37
38Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
39---
40 glib/gvariant-core.c | 35 ++++++++++++++++
41 glib/gvariant-serialiser.c | 86 ++++++++++++++++++++++++++++++++++++--
42 glib/gvariant-serialiser.h | 8 ++++
43 glib/tests/gvariant.c | 45 ++++++++++++++++++++
44 4 files changed, 171 insertions(+), 3 deletions(-)
45
46diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
47index 496f2e2..4e0b2b5 100644
48--- a/glib/gvariant-core.c
49+++ b/glib/gvariant-core.c
50@@ -65,6 +65,7 @@ struct _GVariant
51 {
52 GBytes *bytes;
53 gconstpointer data;
54+ gsize ordered_offsets_up_to;
55 } serialised;
56
57 struct
58@@ -162,6 +163,24 @@ struct _GVariant
59 * if .data pointed to the appropriate number of nul
60 * bytes.
61 *
62+ * .ordered_offsets_up_to: If ordered_offsets_up_to == n this means that all
63+ * the frame offsets up to and including the frame
64+ * offset determining the end of element n are in
65+ * order. This guarantees that the bytes of element
66+ * n don't overlap with any previous element.
67+ *
68+ * For trusted data this is set to G_MAXSIZE and we
69+ * don't check that the frame offsets are in order.
70+ *
71+ * Note: This doesn't imply the offsets are good in
72+ * any way apart from their ordering. In particular
73+ * offsets may be out of bounds for this value or
74+ * may imply that the data overlaps the frame
75+ * offsets themselves.
76+ *
77+ * This field is only relevant for arrays of non
78+ * fixed width types.
79+ *
80 * .tree: Only valid when the instance is in tree form.
81 *
82 * Note that accesses from other threads could result in
83@@ -365,6 +384,7 @@ g_variant_to_serialised (GVariant *value)
84 (gpointer) value->contents.serialised.data,
85 value->size,
86 value->depth,
87+ value->contents.serialised.ordered_offsets_up_to,
88 };
89 return serialised;
90 }
91@@ -396,6 +416,7 @@ g_variant_serialise (GVariant *value,
92 serialised.size = value->size;
93 serialised.data = data;
94 serialised.depth = value->depth;
95+ serialised.ordered_offsets_up_to = 0;
96
97 children = (gpointer *) value->contents.tree.children;
98 n_children = value->contents.tree.n_children;
99@@ -439,6 +460,15 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
100 g_assert (serialised->size == value->size);
101 serialised->depth = value->depth;
102
103+ if (value->state & STATE_SERIALISED)
104+ {
105+ serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
106+ }
107+ else
108+ {
109+ serialised->ordered_offsets_up_to = 0;
110+ }
111+
112 if (serialised->data)
113 /* g_variant_store() is a public API, so it
114 * it will reacquire the lock if it needs to.
115@@ -481,6 +511,7 @@ g_variant_ensure_serialised (GVariant *value)
116 bytes = g_bytes_new_take (data, value->size);
117 value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
118 value->contents.serialised.bytes = bytes;
119+ value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
120 value->state |= STATE_SERIALISED;
121 }
122 }
123@@ -561,6 +592,7 @@ g_variant_new_from_bytes (const GVariantType *type,
124 serialised.type_info = value->type_info;
125 serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
126 serialised.depth = 0;
127+ serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
128
129 if (!g_variant_serialised_check (serialised))
130 {
131@@ -611,6 +643,8 @@ g_variant_new_from_bytes (const GVariantType *type,
132 value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
133 }
134
135+ value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
136+
137 g_clear_pointer (&owned_bytes, g_bytes_unref);
138
139 return value;
140@@ -1130,6 +1164,7 @@ g_variant_get_child_value (GVariant *value,
141 child->contents.serialised.bytes =
142 g_bytes_ref (value->contents.serialised.bytes);
143 child->contents.serialised.data = s_child.data;
144+ child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
145
146 return child;
147 }
148diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
149index e71248e..6fb3f2f 100644
150--- a/glib/gvariant-serialiser.c
151+++ b/glib/gvariant-serialiser.c
152@@ -1,6 +1,7 @@
153 /*
154 * Copyright © 2007, 2008 Ryan Lortie
155 * Copyright © 2010 Codethink Limited
156+ * Copyright © 2020 William Manley
157 *
158 * This library is free software; you can redistribute it and/or
159 * modify it under the terms of the GNU Lesser General Public
160@@ -264,6 +265,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
161 value.type_info = g_variant_type_info_element (value.type_info);
162 g_variant_type_info_ref (value.type_info);
163 value.depth++;
164+ value.ordered_offsets_up_to = 0;
165
166 return value;
167 }
168@@ -295,7 +297,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
169 {
170 if (n_children)
171 {
172- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1 };
173+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
174
175 gvs_filler (&child, children[0]);
176 }
177@@ -317,6 +319,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
178 /* proper element size: "Just". recurse to the child. */
179 value.type_info = g_variant_type_info_element (value.type_info);
180 value.depth++;
181+ value.ordered_offsets_up_to = 0;
182
183 return g_variant_serialised_is_normal (value);
184 }
185@@ -358,6 +361,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
186 value.data = NULL;
187
188 value.depth++;
189+ value.ordered_offsets_up_to = 0;
190
191 return value;
192 }
193@@ -388,7 +392,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
194 {
195 if (n_children)
196 {
197- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1 };
198+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
199
200 /* write the data for the child. */
201 gvs_filler (&child, children[0]);
202@@ -408,6 +412,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
203 value.type_info = g_variant_type_info_element (value.type_info);
204 value.size--;
205 value.depth++;
206+ value.ordered_offsets_up_to = 0;
207
208 return g_variant_serialised_is_normal (value);
209 }
210@@ -691,6 +696,32 @@ gvs_variable_sized_array_n_children (GVariantSerialised value)
211 return gvs_variable_sized_array_get_frame_offsets (value).length;
212 }
213
214+/* Find the index of the first out-of-order element in @data, assuming that
215+ * @data is an array of elements of given @type, starting at index @start and
216+ * containing a further @len-@start elements. */
217+#define DEFINE_FIND_UNORDERED(type) \
218+ static gsize \
219+ find_unordered_##type (const guint8 *data, gsize start, gsize len) \
220+ { \
221+ gsize off; \
222+ type current, previous; \
223+ \
224+ memcpy (&previous, data + start * sizeof (current), sizeof (current)); \
225+ for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \
226+ { \
227+ memcpy (&current, data + off, sizeof (current)); \
228+ if (current < previous) \
229+ break; \
230+ previous = current; \
231+ } \
232+ return off / sizeof (current) - 1; \
233+ }
234+
235+DEFINE_FIND_UNORDERED (guint8);
236+DEFINE_FIND_UNORDERED (guint16);
237+DEFINE_FIND_UNORDERED (guint32);
238+DEFINE_FIND_UNORDERED (guint64);
239+
240 static GVariantSerialised
241 gvs_variable_sized_array_get_child (GVariantSerialised value,
242 gsize index_)
243@@ -706,6 +737,49 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
244 g_variant_type_info_ref (child.type_info);
245 child.depth = value.depth + 1;
246
247+ /* If the requested @index_ is beyond the set of indices whose framing offsets
248+ * have been checked, check the remaining offsets to see whether they’re
249+ * normal (in order, no overlapping array elements). */
250+ if (index_ > value.ordered_offsets_up_to)
251+ {
252+ switch (offsets.offset_size)
253+ {
254+ case 1:
255+ {
256+ value.ordered_offsets_up_to = find_unordered_guint8 (
257+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
258+ break;
259+ }
260+ case 2:
261+ {
262+ value.ordered_offsets_up_to = find_unordered_guint16 (
263+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
264+ break;
265+ }
266+ case 4:
267+ {
268+ value.ordered_offsets_up_to = find_unordered_guint32 (
269+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
270+ break;
271+ }
272+ case 8:
273+ {
274+ value.ordered_offsets_up_to = find_unordered_guint64 (
275+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
276+ break;
277+ }
278+ default:
279+ /* gvs_get_offset_size() only returns maximum 8 */
280+ g_assert_not_reached ();
281+ }
282+ }
283+
284+ if (index_ > value.ordered_offsets_up_to)
285+ {
286+ /* Offsets are invalid somewhere, so return an empty child. */
287+ return child;
288+ }
289+
290 if (index_ > 0)
291 {
292 guint alignment;
293@@ -840,6 +914,9 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
294
295 g_assert (offset == offsets.data_size);
296
297+ /* All offsets have now been checked. */
298+ value.ordered_offsets_up_to = G_MAXSIZE;
299+
300 return TRUE;
301 }
302
303@@ -1072,7 +1149,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
304 for (i = 0; i < length; i++)
305 {
306 const GVariantMemberInfo *member_info;
307- GVariantSerialised child;
308+ GVariantSerialised child = { 0, };
309 gsize fixed_size;
310 guint alignment;
311 gsize end;
312@@ -1132,6 +1209,9 @@ gvs_tuple_is_normal (GVariantSerialised value)
313 offset = end;
314 }
315
316+ /* All element bounds have been checked above. */
317+ value.ordered_offsets_up_to = G_MAXSIZE;
318+
319 {
320 gsize fixed_size;
321 guint alignment;
322diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
323index 859cb7b..3ab83b3 100644
324--- a/glib/gvariant-serialiser.h
325+++ b/glib/gvariant-serialiser.h
326@@ -29,6 +29,14 @@ typedef struct
327 guchar *data;
328 gsize size;
329 gsize depth; /* same semantics as GVariant.depth */
330+ /* If ordered_offsets_up_to == n this means that all the frame offsets up to and
331+ * including the frame offset determining the end of element n are in order.
332+ * This guarantees that the bytes of element n don't overlap with any previous
333+ * element.
334+ *
335+ * This is both read and set by g_variant_serialised_get_child for arrays of
336+ * non-fixed-width types */
337+ gsize ordered_offsets_up_to;
338 } GVariantSerialised;
339
340 /* deserialization */
341diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
342index 0110f26..291f796 100644
343--- a/glib/tests/gvariant.c
344+++ b/glib/tests/gvariant.c
345@@ -1,5 +1,6 @@
346 /*
347 * Copyright © 2010 Codethink Limited
348+ * Copyright © 2020 William Manley
349 *
350 * This library is free software; you can redistribute it and/or
351 * modify it under the terms of the GNU Lesser General Public
352@@ -1279,6 +1280,7 @@ random_instance_filler (GVariantSerialised *serialised,
353 serialised->size = instance->size;
354
355 serialised->depth = 0;
356+ serialised->ordered_offsets_up_to = 0;
357
358 g_assert_true (serialised->type_info == instance->type_info);
359 g_assert_cmpuint (serialised->size, ==, instance->size);
360@@ -5023,6 +5025,47 @@ test_normal_checking_array_offsets (void)
361 g_variant_unref (variant);
362 }
363
364+/* This is a regression test that we can't have non-normal values that take up
365+ * significantly more space than the normal equivalent, by specifying the
366+ * offset table entries so that array elements overlap.
367+ *
368+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
369+static void
370+test_normal_checking_array_offsets2 (void)
371+{
372+ const guint8 data[] = {
373+ 'h', 'i', '\0',
374+ 0x03, 0x00, 0x03,
375+ 0x06, 0x00, 0x06,
376+ 0x09, 0x00, 0x09,
377+ 0x0c, 0x00, 0x0c,
378+ 0x0f, 0x00, 0x0f,
379+ 0x12, 0x00, 0x12,
380+ 0x15, 0x00, 0x15,
381+ };
382+ gsize size = sizeof (data);
383+ const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
384+ GVariant *variant = NULL;
385+ GVariant *normal_variant = NULL;
386+ GVariant *expected = NULL;
387+
388+ variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
389+ g_assert_nonnull (variant);
390+
391+ normal_variant = g_variant_get_normal_form (variant);
392+ g_assert_nonnull (normal_variant);
393+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
394+
395+ expected = g_variant_new_parsed (
396+ "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
397+ g_assert_cmpvariant (expected, variant);
398+ g_assert_cmpvariant (expected, normal_variant);
399+
400+ g_variant_unref (expected);
401+ g_variant_unref (normal_variant);
402+ g_variant_unref (variant);
403+}
404+
405 /* Test that a tuple with invalidly large values in its offset table is
406 * normalised successfully without looping infinitely. */
407 static void
408@@ -5189,6 +5232,8 @@ main (int argc, char **argv)
409 test_normal_checking_tuples);
410 g_test_add_func ("/gvariant/normal-checking/array-offsets",
411 test_normal_checking_array_offsets);
412+ g_test_add_func ("/gvariant/normal-checking/array-offsets2",
413+ test_normal_checking_array_offsets2);
414 g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
415 test_normal_checking_tuple_offsets);
416 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
417--
4182.40.0
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..791efdee87
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
@@ -0,0 +1,114 @@
1From 345cae9c1aa7bf6752039225ef4c8d8d69fa8d76 Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Fri, 11 Aug 2023 04:09:12 +0000
4Subject: [PATCH] gvariant-serialiser: Factor out code to get bounds of a tuple
5 member
6
7This introduces no functional changes.
8
9Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14
15Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/345cae9c1aa7bf6752039225ef4c8d8d69fa8d76]
16
17Signed-off-by: Soumya <soumya.sambu@windriver.com>
18---
19 glib/gvariant-serialiser.c | 73 ++++++++++++++++++++++++--------------
20 1 file changed, 46 insertions(+), 27 deletions(-)
21
22diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
23index 2932427..1c23eab 100644
24--- a/glib/gvariant-serialiser.c
25+++ b/glib/gvariant-serialiser.c
26@@ -946,6 +946,51 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
27 * for the tuple. See the notes in gvarianttypeinfo.h.
28 */
29
30+static void
31+gvs_tuple_get_member_bounds (GVariantSerialised value,
32+ gsize index_,
33+ gsize offset_size,
34+ gsize *out_member_start,
35+ gsize *out_member_end)
36+{
37+ const GVariantMemberInfo *member_info;
38+ gsize member_start, member_end;
39+
40+ member_info = g_variant_type_info_member_info (value.type_info, index_);
41+
42+ if (member_info->i + 1)
43+ member_start = gvs_read_unaligned_le (value.data + value.size -
44+ offset_size * (member_info->i + 1),
45+ offset_size);
46+ else
47+ member_start = 0;
48+
49+ member_start += member_info->a;
50+ member_start &= member_info->b;
51+ member_start |= member_info->c;
52+
53+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
54+ member_end = value.size - offset_size * (member_info->i + 1);
55+
56+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
57+ {
58+ gsize fixed_size;
59+
60+ g_variant_type_info_query (member_info->type_info, NULL, &fixed_size);
61+ member_end = member_start + fixed_size;
62+ }
63+
64+ else /* G_VARIANT_MEMBER_ENDING_OFFSET */
65+ member_end = gvs_read_unaligned_le (value.data + value.size -
66+ offset_size * (member_info->i + 2),
67+ offset_size);
68+
69+ if (out_member_start != NULL)
70+ *out_member_start = member_start;
71+ if (out_member_end != NULL)
72+ *out_member_end = member_end;
73+}
74+
75 static gsize
76 gvs_tuple_n_children (GVariantSerialised value)
77 {
78@@ -1001,33 +1046,7 @@ gvs_tuple_get_child (GVariantSerialised value,
79 }
80 }
81
82- if (member_info->i + 1)
83- start = gvs_read_unaligned_le (value.data + value.size -
84- offset_size * (member_info->i + 1),
85- offset_size);
86- else
87- start = 0;
88-
89- start += member_info->a;
90- start &= member_info->b;
91- start |= member_info->c;
92-
93- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
94- end = value.size - offset_size * (member_info->i + 1);
95-
96- else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
97- {
98- gsize fixed_size;
99-
100- g_variant_type_info_query (child.type_info, NULL, &fixed_size);
101- end = start + fixed_size;
102- child.size = fixed_size;
103- }
104-
105- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
106- end = gvs_read_unaligned_le (value.data + value.size -
107- offset_size * (member_info->i + 2),
108- offset_size);
109+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
110
111 /* The child should not extend into the offset table. */
112 if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
113--
1142.40.0
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..6c71c20819
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch
@@ -0,0 +1,81 @@
1From 73d0aa81c2575a5c9ae77dcb94da919579014fc0 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Fri, 11 Aug 2023 04:13:02 +0000
4Subject: [PATCH] gvariant-serialiser: Rework child size calculation
5
6This reduces a few duplicate calls to `g_variant_type_info_query()` and
7explains why they’re needed.
8
9Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14
15Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/73d0aa81c2575a5c9ae77dcb94da919579014fc0]
16
17Signed-off-by: Soumya <soumya.sambu@windriver.com>
18---
19 glib/gvariant-serialiser.c | 31 +++++++++----------------------
20 1 file changed, 9 insertions(+), 22 deletions(-)
21
22diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
23index 1c23eab..b63e99f 100644
24--- a/glib/gvariant-serialiser.c
25+++ b/glib/gvariant-serialiser.c
26@@ -1011,14 +1011,18 @@ gvs_tuple_get_child (GVariantSerialised value,
27 child.depth = value.depth + 1;
28 offset_size = gvs_get_offset_size (value.size);
29
30+ /* Ensure the size is set for fixed-sized children, or
31+ * g_variant_serialised_check() will fail, even if we return
32+ * (child.data == NULL) to indicate an error. */
33+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
34+ g_variant_type_info_query (child.type_info, NULL, &child.size);
35+
36 /* tuples are the only (potentially) fixed-sized containers, so the
37 * only ones that have to deal with the possibility of having %NULL
38 * data with a non-zero %size if errors occurred elsewhere.
39 */
40 if G_UNLIKELY (value.data == NULL && value.size != 0)
41 {
42- g_variant_type_info_query (child.type_info, NULL, &child.size);
43-
44 /* this can only happen in fixed-sized tuples,
45 * so the child must also be fixed sized.
46 */
47@@ -1036,29 +1040,12 @@ gvs_tuple_get_child (GVariantSerialised value,
48 else
49 {
50 if (offset_size * (member_info->i + 1) > value.size)
51- {
52- /* if the child is fixed size, return its size.
53- * if child is not fixed-sized, return size = 0.
54- */
55- g_variant_type_info_query (child.type_info, NULL, &child.size);
56-
57- return child;
58- }
59+ return child;
60 }
61
62- gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
63-
64 /* The child should not extend into the offset table. */
65- if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
66- {
67- GVariantSerialised last_child;
68- last_child = gvs_tuple_get_child (value,
69- g_variant_type_info_n_members (value.type_info) - 1);
70- last_end = last_child.data + last_child.size - value.data;
71- g_variant_type_info_unref (last_child.type_info);
72- }
73- else
74- last_end = end;
75+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
76+ gvs_tuple_get_member_bounds (value, g_variant_type_info_n_members (value.type_info) - 1, offset_size, NULL, &last_end);
77
78 if (start < end && end <= value.size && end <= last_end)
79 {
80--
812.40.0
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..194ce15287
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
@@ -0,0 +1,397 @@
1From 7cf6f5b69146d20948d42f0c476688fe17fef787 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 16 Aug 2023 12:09:06 +0000
4Subject: [PATCH] gvariant: Don't allow child elements of a tuple to overlap
5 each other
6
7This is similar to the earlier commit which prevents child elements of a
8variable-sized array from overlapping each other, but this time for
9tuples. It is based heavily on ideas by William Manley.
10
11Tuples are slightly different from variable-sized arrays in that they
12contain a mixture of fixed and variable sized elements. All but one of
13the variable sized elements have an entry in the frame offsets table.
14This means that if we were to just check the ordering of the frame
15offsets table, the variable sized elements could still overlap
16interleaving fixed sized elements, which would be bad.
17
18Therefore we have to check the elements rather than the frame offsets.
19
20The logic of checking the elements up to the index currently being
21requested, and caching the result in `ordered_offsets_up_to`, means that
22the algorithmic cost implications are the same for this commit as for
23variable-sized arrays: an O(N) cost for these checks is amortised out
24over N accesses to O(1) per access.
25
26Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
27
28Fixes: #2121
29
30CVE: CVE-2023-32665
31
32Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/7cf6f5b69146d20948d42f0c476688fe17fef787]
33
34Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
35---
36 glib/gvariant-core.c | 6 +-
37 glib/gvariant-serialiser.c | 40 ++++++++
38 glib/gvariant-serialiser.h | 7 +-
39 glib/gvariant.c | 1 +
40 glib/tests/gvariant.c | 181 +++++++++++++++++++++++++++++++++++++
41 5 files changed, 232 insertions(+), 3 deletions(-)
42
43diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
44index 4e0b2b5..c57ee77 100644
45--- a/glib/gvariant-core.c
46+++ b/glib/gvariant-core.c
47@@ -1,6 +1,7 @@
48 /*
49 * Copyright © 2007, 2008 Ryan Lortie
50 * Copyright © 2010 Codethink Limited
51+ * Copyright © 2022 Endless OS Foundation, LLC
52 *
53 * This library is free software; you can redistribute it and/or
54 * modify it under the terms of the GNU Lesser General Public
55@@ -179,7 +180,7 @@ struct _GVariant
56 * offsets themselves.
57 *
58 * This field is only relevant for arrays of non
59- * fixed width types.
60+ * fixed width types and for tuples.
61 *
62 * .tree: Only valid when the instance is in tree form.
63 *
64@@ -1139,6 +1140,9 @@ g_variant_get_child_value (GVariant *value,
65 */
66 s_child = g_variant_serialised_get_child (serialised, index_);
67
68+ /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
69+ value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
70+
71 /* Check whether this would cause nesting too deep. If so, return a fake
72 * child. The only situation we expect this to happen in is with a variant,
73 * as all other deeply-nested types have a static type, and hence should
74diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
75index 2493e76..d46d05c 100644
76--- a/glib/gvariant-serialiser.c
77+++ b/glib/gvariant-serialiser.c
78@@ -942,6 +942,10 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
79 * for the tuple. See the notes in gvarianttypeinfo.h.
80 */
81
82+/* Note: This doesn’t guarantee that @out_member_end >= @out_member_start; that
83+ * condition may not hold true for invalid serialised variants. The caller is
84+ * responsible for checking the returned values and handling invalid ones
85+ * appropriately. */
86 static void
87 gvs_tuple_get_member_bounds (GVariantSerialised value,
88 gsize index_,
89@@ -1028,6 +1032,42 @@ gvs_tuple_get_child (GVariantSerialised value,
90 return child;
91 }
92
93+ /* If the requested @index_ is beyond the set of indices whose framing offsets
94+ * have been checked, check the remaining offsets to see whether they’re
95+ * normal (in order, no overlapping tuple elements).
96+ *
97+ * Unlike the checks in gvs_variable_sized_array_get_child(), we have to check
98+ * all the tuple *elements* here, not just all the framing offsets, since
99+ * tuples contain a mix of elements which use framing offsets and ones which
100+ * don’t. None of them are allowed to overlap. */
101+ if (index_ > value.ordered_offsets_up_to)
102+ {
103+ gsize i, prev_i_end = 0;
104+
105+ if (value.ordered_offsets_up_to > 0)
106+ gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
107+
108+ for (i = value.ordered_offsets_up_to; i <= index_; i++)
109+ {
110+ gsize i_start, i_end;
111+
112+ gvs_tuple_get_member_bounds (value, i, offset_size, &i_start, &i_end);
113+
114+ if (i_start > i_end || i_start < prev_i_end || i_end > value.size)
115+ break;
116+
117+ prev_i_end = i_end;
118+ }
119+
120+ value.ordered_offsets_up_to = i - 1;
121+ }
122+
123+ if (index_ > value.ordered_offsets_up_to)
124+ {
125+ /* Offsets are invalid somewhere, so return an empty child. */
126+ return child;
127+ }
128+
129 if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
130 {
131 if (offset_size * (member_info->i + 2) > value.size)
132diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
133index 3ab83b3..03826f9 100644
134--- a/glib/gvariant-serialiser.h
135+++ b/glib/gvariant-serialiser.h
136@@ -34,8 +34,11 @@ typedef struct
137 * This guarantees that the bytes of element n don't overlap with any previous
138 * element.
139 *
140- * This is both read and set by g_variant_serialised_get_child for arrays of
141- * non-fixed-width types */
142+ * This is both read and set by g_variant_serialised_get_child() for arrays of
143+ * non-fixed-width types, and for tuples.
144+ *
145+ * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
146+ * rather than an index into the frame offsets. */
147 gsize ordered_offsets_up_to;
148 } GVariantSerialised;
149
150diff --git a/glib/gvariant.c b/glib/gvariant.c
151index 42ffc9a..f645e05 100644
152--- a/glib/gvariant.c
153+++ b/glib/gvariant.c
154@@ -5997,6 +5997,7 @@ g_variant_byteswap (GVariant *value)
155 serialised.size = g_variant_get_size (trusted);
156 serialised.data = g_malloc (serialised.size);
157 serialised.depth = g_variant_get_depth (trusted);
158+ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
159 g_variant_store (trusted, serialised.data);
160 g_variant_unref (trusted);
161
162diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
163index 291f796..3ddff96 100644
164--- a/glib/tests/gvariant.c
165+++ b/glib/tests/gvariant.c
166@@ -1,6 +1,7 @@
167 /*
168 * Copyright © 2010 Codethink Limited
169 * Copyright © 2020 William Manley
170+ * Copyright © 2022 Endless OS Foundation, LLC
171 *
172 * This library is free software; you can redistribute it and/or
173 * modify it under the terms of the GNU Lesser General Public
174@@ -1447,6 +1448,7 @@ test_maybe (void)
175 serialised.data = flavoured_malloc (needed_size, flavour);
176 serialised.size = needed_size;
177 serialised.depth = 0;
178+ serialised.ordered_offsets_up_to = 0;
179
180 g_variant_serialiser_serialise (serialised,
181 random_instance_filler,
182@@ -1570,6 +1572,7 @@ test_array (void)
183 serialised.data = flavoured_malloc (needed_size, flavour);
184 serialised.size = needed_size;
185 serialised.depth = 0;
186+ serialised.ordered_offsets_up_to = 0;
187
188 g_variant_serialiser_serialise (serialised, random_instance_filler,
189 (gpointer *) instances, n_children);
190@@ -1734,6 +1737,7 @@ test_tuple (void)
191 serialised.data = flavoured_malloc (needed_size, flavour);
192 serialised.size = needed_size;
193 serialised.depth = 0;
194+ serialised.ordered_offsets_up_to = 0;
195
196 g_variant_serialiser_serialise (serialised, random_instance_filler,
197 (gpointer *) instances, n_children);
198@@ -1830,6 +1834,7 @@ test_variant (void)
199 serialised.data = flavoured_malloc (needed_size, flavour);
200 serialised.size = needed_size;
201 serialised.depth = 0;
202+ serialised.ordered_offsets_up_to = 0;
203
204 g_variant_serialiser_serialise (serialised, random_instance_filler,
205 (gpointer *) &instance, 1);
206@@ -5090,6 +5095,176 @@ test_normal_checking_tuple_offsets (void)
207 g_variant_unref (variant);
208 }
209
210+/* This is a regression test that we can't have non-normal values that take up
211+ * significantly more space than the normal equivalent, by specifying the
212+ * offset table entries so that tuple elements overlap.
213+ *
214+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
215+ * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
216+static void
217+test_normal_checking_tuple_offsets2 (void)
218+{
219+ const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
220+ const guint8 data[] = {
221+ 0x12, 0x34, 0x56, 0x78, 0x01,
222+ /*
223+ ^───────────────────┘
224+
225+ ^^^^^^^^^^ 1st yy
226+ ^^^^^^^^^^ 2nd yy
227+ ^^^^^^^^^^ 3rd yy
228+ ^^^^ Framing offsets
229+ */
230+
231+ /* If this variant was encoded normally, it would be something like this:
232+ * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX
233+ * ^─────────────────────────────────────────────────────┘
234+ *
235+ * ^^^^^^^^^^ 1st yy
236+ * ^^^^^^^^^^ 2nd yy
237+ * ^^^^^^^^^^ 3rd yy
238+ * ^^^^ Framing offsets
239+ */
240+ };
241+ gsize size = sizeof (data);
242+ GVariant *variant = NULL;
243+ GVariant *normal_variant = NULL;
244+ GVariant *expected = NULL;
245+
246+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
247+ g_assert_nonnull (variant);
248+
249+ normal_variant = g_variant_get_normal_form (variant);
250+ g_assert_nonnull (normal_variant);
251+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
252+
253+ expected = g_variant_new_parsed (
254+ "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
255+ g_assert_cmpvariant (expected, variant);
256+ g_assert_cmpvariant (expected, normal_variant);
257+
258+ g_variant_unref (expected);
259+ g_variant_unref (normal_variant);
260+ g_variant_unref (variant);
261+}
262+
263+/* This is a regression test that overlapping entries in the offset table are
264+ * decoded consistently, even though they’re non-normal.
265+ *
266+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
267+static void
268+test_normal_checking_tuple_offsets3 (void)
269+{
270+ /* The expected decoding of this non-normal byte stream is complex. See
271+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
272+ * specification.
273+ *
274+ * The rule “Child Values Overlapping Framing Offsets” from the specification
275+ * says that the first `ay` must be decoded as `[0x01]` even though it
276+ * overlaps the first byte of the offset table. However, since commit
277+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
278+ * this as it’s exploitable. So the first `ay` must be given a default value.
279+ *
280+ * The second and third `ay`s must be given default values because of rule
281+ * “End Boundary Precedes Start Boundary”.
282+ *
283+ * The `i` must be given a default value because of rule “Start or End
284+ * Boundary of a Child Falls Outside the Container”.
285+ */
286+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
287+ const guint8 data[] = {
288+ 0x01, 0x00, 0x02,
289+ /*
290+ ^──┘
291+
292+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
293+ 2nd ay, bytes 2-0
294+ i, bytes 0-4
295+ 3rd ay, bytes 4-1
296+ ^^^^^^^^^^ Framing offsets
297+ */
298+ };
299+ gsize size = sizeof (data);
300+ GVariant *variant = NULL;
301+ GVariant *normal_variant = NULL;
302+ GVariant *expected = NULL;
303+
304+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
305+ g_assert_nonnull (variant);
306+
307+ g_assert_false (g_variant_is_normal_form (variant));
308+
309+ normal_variant = g_variant_get_normal_form (variant);
310+ g_assert_nonnull (normal_variant);
311+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
312+
313+ expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
314+ g_assert_cmpvariant (expected, variant);
315+ g_assert_cmpvariant (expected, normal_variant);
316+
317+ g_variant_unref (expected);
318+ g_variant_unref (normal_variant);
319+ g_variant_unref (variant);
320+}
321+
322+/* This is a regression test that overlapping entries in the offset table are
323+ * decoded consistently, even though they’re non-normal.
324+ *
325+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
326+static void
327+test_normal_checking_tuple_offsets4 (void)
328+{
329+ /* The expected decoding of this non-normal byte stream is complex. See
330+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
331+ * specification.
332+ *
333+ * The rule “Child Values Overlapping Framing Offsets” from the specification
334+ * says that the first `ay` must be decoded as `[0x01]` even though it
335+ * overlaps the first byte of the offset table. However, since commit
336+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
337+ * this as it’s exploitable. So the first `ay` must be given a default value.
338+ *
339+ * The second `ay` must be given a default value because of rule “End Boundary
340+ * Precedes Start Boundary”.
341+ *
342+ * The third `ay` must be given a default value because its framing offsets
343+ * overlap that of the first `ay`.
344+ */
345+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
346+ const guint8 data[] = {
347+ 0x01, 0x00, 0x02,
348+ /*
349+ ^──┘
350+
351+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
352+ 2nd ay, bytes 2-0
353+ 3rd ay, bytes 0-1
354+ ^^^^^^^^^^ Framing offsets
355+ */
356+ };
357+ gsize size = sizeof (data);
358+ GVariant *variant = NULL;
359+ GVariant *normal_variant = NULL;
360+ GVariant *expected = NULL;
361+
362+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
363+ g_assert_nonnull (variant);
364+
365+ g_assert_false (g_variant_is_normal_form (variant));
366+
367+ normal_variant = g_variant_get_normal_form (variant);
368+ g_assert_nonnull (normal_variant);
369+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
370+
371+ expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
372+ g_assert_cmpvariant (expected, variant);
373+ g_assert_cmpvariant (expected, normal_variant);
374+
375+ g_variant_unref (expected);
376+ g_variant_unref (normal_variant);
377+ g_variant_unref (variant);
378+}
379+
380 /* Test that an empty object path is normalised successfully to the base object
381 * path, ‘/’. */
382 static void
383@@ -5236,6 +5411,12 @@ main (int argc, char **argv)
384 test_normal_checking_array_offsets2);
385 g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
386 test_normal_checking_tuple_offsets);
387+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
388+ test_normal_checking_tuple_offsets2);
389+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
390+ test_normal_checking_tuple_offsets3);
391+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
392+ test_normal_checking_tuple_offsets4);
393 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
394 test_normal_checking_empty_object_path);
395
396--
3972.40.0
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..8a408ab030
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch
@@ -0,0 +1,50 @@
1From e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 16 Aug 2023 03:42:47 +0000
4Subject: [PATCH] gvariant: Port g_variant_deep_copy() to count its iterations
5 directly
6
7This is equivalent to what `GVariantIter` does, but it means that
8`g_variant_deep_copy()` is making its own `g_variant_get_child_value()`
9calls.
10
11This will be useful in an upcoming commit, where those child values will
12be inspected a little more deeply.
13
14Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
15
16Helps: #2121
17
18CVE: CVE-2023-32665
19
20Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793]
21
22Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
23---
24 glib/gvariant.c | 7 +++----
25 1 file changed, 3 insertions(+), 4 deletions(-)
26
27diff --git a/glib/gvariant.c b/glib/gvariant.c
28index 42ffc9a..ca13cc1 100644
29--- a/glib/gvariant.c
30+++ b/glib/gvariant.c
31@@ -5850,14 +5850,13 @@ g_variant_deep_copy (GVariant *value)
32 case G_VARIANT_CLASS_VARIANT:
33 {
34 GVariantBuilder builder;
35- GVariantIter iter;
36- GVariant *child;
37+ gsize i, n_children;
38
39 g_variant_builder_init (&builder, g_variant_get_type (value));
40- g_variant_iter_init (&iter, value);
41
42- while ((child = g_variant_iter_next_value (&iter)))
43+ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
44 {
45+ GVariant *child = g_variant_get_child_value (value, i);
46 g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
47 g_variant_unref (child);
48 }
49--
502.40.0
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..9b074a543d
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
@@ -0,0 +1,395 @@
1From d1a293c4e29880b8d17bb826c9a426a440ca4a91 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 01:30:38 +0000
4Subject: [PATCH] gvariant: Track checked and ordered offsets independently
5
6The past few commits introduced the concept of known-good offsets in the
7offset table (which is used for variable-width arrays and tuples).
8Good offsets are ones which are non-overlapping with all the previous
9offsets in the table.
10
11If a bad offset is encountered when indexing into the array or tuple,
12the cached known-good offset index will not be increased. In this way,
13all child variants at and beyond the first bad offset can be returned as
14default values rather than dereferencing potentially invalid data.
15
16In this case, there was no information about the fact that the indexes
17between the highest known-good index and the requested one had been
18checked already. That could lead to a pathological case where an offset
19table with an invalid first offset is repeatedly checked in full when
20trying to access higher-indexed children.
21
22Avoid that by storing the index of the highest checked offset in the
23table, as well as the index of the highest good/ordered offset.
24
25Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
26
27Helps: #2121
28
29CVE: CVE-2023-32665
30
31Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/d1a293c4e29880b8d17bb826c9a426a440ca4a91]
32
33Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
34---
35 glib/gvariant-core.c | 28 ++++++++++++++++++++++++
36 glib/gvariant-serialiser.c | 44 +++++++++++++++++++++++++++-----------
37 glib/gvariant-serialiser.h | 9 ++++++++
38 glib/gvariant.c | 1 +
39 glib/tests/gvariant.c | 5 +++++
40 5 files changed, 75 insertions(+), 12 deletions(-)
41
42diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
43index c57ee77..7b71efc 100644
44--- a/glib/gvariant-core.c
45+++ b/glib/gvariant-core.c
46@@ -67,6 +67,7 @@ struct _GVariant
47 GBytes *bytes;
48 gconstpointer data;
49 gsize ordered_offsets_up_to;
50+ gsize checked_offsets_up_to;
51 } serialised;
52
53 struct
54@@ -182,6 +183,24 @@ struct _GVariant
55 * This field is only relevant for arrays of non
56 * fixed width types and for tuples.
57 *
58+ * .checked_offsets_up_to: Similarly to .ordered_offsets_up_to, this stores
59+ * the index of the highest element, n, whose frame
60+ * offsets (and all the preceding frame offsets)
61+ * have been checked for validity.
62+ *
63+ * It is always the case that
64+ * .checked_offsets_up_to ≥ .ordered_offsets_up_to.
65+ *
66+ * If .checked_offsets_up_to == .ordered_offsets_up_to,
67+ * then a bad offset has not been found so far.
68+ *
69+ * If .checked_offsets_up_to > .ordered_offsets_up_to,
70+ * then a bad offset has been found at
71+ * (.ordered_offsets_up_to + 1).
72+ *
73+ * This field is only relevant for arrays of non
74+ * fixed width types and for tuples.
75+ *
76 * .tree: Only valid when the instance is in tree form.
77 *
78 * Note that accesses from other threads could result in
79@@ -386,6 +405,7 @@ g_variant_to_serialised (GVariant *value)
80 value->size,
81 value->depth,
82 value->contents.serialised.ordered_offsets_up_to,
83+ value->contents.serialised.checked_offsets_up_to,
84 };
85 return serialised;
86 }
87@@ -418,6 +438,7 @@ g_variant_serialise (GVariant *value,
88 serialised.data = data;
89 serialised.depth = value->depth;
90 serialised.ordered_offsets_up_to = 0;
91+ serialised.checked_offsets_up_to = 0;
92
93 children = (gpointer *) value->contents.tree.children;
94 n_children = value->contents.tree.n_children;
95@@ -464,10 +485,12 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
96 if (value->state & STATE_SERIALISED)
97 {
98 serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
99+ serialised->checked_offsets_up_to = value->contents.serialised.checked_offsets_up_to;
100 }
101 else
102 {
103 serialised->ordered_offsets_up_to = 0;
104+ serialised->checked_offsets_up_to = 0;
105 }
106
107 if (serialised->data)
108@@ -513,6 +536,7 @@ g_variant_ensure_serialised (GVariant *value)
109 value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
110 value->contents.serialised.bytes = bytes;
111 value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
112+ value->contents.serialised.checked_offsets_up_to = G_MAXSIZE;
113 value->state |= STATE_SERIALISED;
114 }
115 }
116@@ -594,6 +618,7 @@ g_variant_new_from_bytes (const GVariantType *type,
117 serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
118 serialised.depth = 0;
119 serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
120+ serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
121
122 if (!g_variant_serialised_check (serialised))
123 {
124@@ -645,6 +670,7 @@ g_variant_new_from_bytes (const GVariantType *type,
125 }
126
127 value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
128+ value->contents.serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
129
130 g_clear_pointer (&owned_bytes, g_bytes_unref);
131
132@@ -1142,6 +1168,7 @@ g_variant_get_child_value (GVariant *value,
133
134 /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
135 value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
136+ value->contents.serialised.checked_offsets_up_to = MAX (value->contents.serialised.checked_offsets_up_to, serialised.checked_offsets_up_to);
137
138 /* Check whether this would cause nesting too deep. If so, return a fake
139 * child. The only situation we expect this to happen in is with a variant,
140@@ -1169,6 +1196,7 @@ g_variant_get_child_value (GVariant *value,
141 g_bytes_ref (value->contents.serialised.bytes);
142 child->contents.serialised.data = s_child.data;
143 child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
144+ child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
145
146 return child;
147 }
148diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
149index d46d05c..9c7f12a 100644
150--- a/glib/gvariant-serialiser.c
151+++ b/glib/gvariant-serialiser.c
152@@ -120,6 +120,8 @@
153 *
154 * @depth has no restrictions; the depth of a top-level serialized #GVariant is
155 * zero, and it increases for each level of nested child.
156+ *
157+ * @checked_offsets_up_to is always ≥ @ordered_offsets_up_to
158 */
159
160 /* < private >
161@@ -147,6 +149,9 @@ g_variant_serialised_check (GVariantSerialised serialised)
162 !(serialised.size == 0 || serialised.data != NULL))
163 return FALSE;
164
165+ if (serialised.ordered_offsets_up_to > serialised.checked_offsets_up_to)
166+ return FALSE;
167+
168 /* Depending on the native alignment requirements of the machine, the
169 * compiler will insert either 3 or 7 padding bytes after the char.
170 * This will result in the sizeof() the struct being 12 or 16.
171@@ -266,6 +271,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
172 g_variant_type_info_ref (value.type_info);
173 value.depth++;
174 value.ordered_offsets_up_to = 0;
175+ value.checked_offsets_up_to = 0;
176
177 return value;
178 }
179@@ -297,7 +303,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
180 {
181 if (n_children)
182 {
183- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
184+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0, 0 };
185
186 gvs_filler (&child, children[0]);
187 }
188@@ -320,6 +326,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
189 value.type_info = g_variant_type_info_element (value.type_info);
190 value.depth++;
191 value.ordered_offsets_up_to = 0;
192+ value.checked_offsets_up_to = 0;
193
194 return g_variant_serialised_is_normal (value);
195 }
196@@ -362,6 +369,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
197
198 value.depth++;
199 value.ordered_offsets_up_to = 0;
200+ value.checked_offsets_up_to = 0;
201
202 return value;
203 }
204@@ -392,7 +400,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
205 {
206 if (n_children)
207 {
208- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
209+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0, 0 };
210
211 /* write the data for the child. */
212 gvs_filler (&child, children[0]);
213@@ -413,6 +421,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
214 value.size--;
215 value.depth++;
216 value.ordered_offsets_up_to = 0;
217+ value.checked_offsets_up_to = 0;
218
219 return g_variant_serialised_is_normal (value);
220 }
221@@ -739,39 +748,46 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
222
223 /* If the requested @index_ is beyond the set of indices whose framing offsets
224 * have been checked, check the remaining offsets to see whether they’re
225- * normal (in order, no overlapping array elements). */
226- if (index_ > value.ordered_offsets_up_to)
227+ * normal (in order, no overlapping array elements).
228+ *
229+ * Don’t bother checking if the highest known-good offset is lower than the
230+ * highest checked offset, as that means there’s an invalid element at that
231+ * index, so there’s no need to check further. */
232+ if (index_ > value.checked_offsets_up_to &&
233+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
234 {
235 switch (offsets.offset_size)
236 {
237 case 1:
238 {
239 value.ordered_offsets_up_to = find_unordered_guint8 (
240- offsets.array, value.ordered_offsets_up_to, index_ + 1);
241+ offsets.array, value.checked_offsets_up_to, index_ + 1);
242 break;
243 }
244 case 2:
245 {
246 value.ordered_offsets_up_to = find_unordered_guint16 (
247- offsets.array, value.ordered_offsets_up_to, index_ + 1);
248+ offsets.array, value.checked_offsets_up_to, index_ + 1);
249 break;
250 }
251 case 4:
252 {
253 value.ordered_offsets_up_to = find_unordered_guint32 (
254- offsets.array, value.ordered_offsets_up_to, index_ + 1);
255+ offsets.array, value.checked_offsets_up_to, index_ + 1);
256 break;
257 }
258 case 8:
259 {
260 value.ordered_offsets_up_to = find_unordered_guint64 (
261- offsets.array, value.ordered_offsets_up_to, index_ + 1);
262+ offsets.array, value.checked_offsets_up_to, index_ + 1);
263 break;
264 }
265 default:
266 /* gvs_get_offset_size() only returns maximum 8 */
267 g_assert_not_reached ();
268 }
269+
270+ value.checked_offsets_up_to = index_;
271 }
272
273 if (index_ > value.ordered_offsets_up_to)
274@@ -916,6 +932,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
275
276 /* All offsets have now been checked. */
277 value.ordered_offsets_up_to = G_MAXSIZE;
278+ value.checked_offsets_up_to = G_MAXSIZE;
279
280 return TRUE;
281 }
282@@ -1040,14 +1057,15 @@ gvs_tuple_get_child (GVariantSerialised value,
283 * all the tuple *elements* here, not just all the framing offsets, since
284 * tuples contain a mix of elements which use framing offsets and ones which
285 * don’t. None of them are allowed to overlap. */
286- if (index_ > value.ordered_offsets_up_to)
287+ if (index_ > value.checked_offsets_up_to &&
288+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
289 {
290 gsize i, prev_i_end = 0;
291
292- if (value.ordered_offsets_up_to > 0)
293- gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
294+ if (value.checked_offsets_up_to > 0)
295+ gvs_tuple_get_member_bounds (value, value.checked_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
296
297- for (i = value.ordered_offsets_up_to; i <= index_; i++)
298+ for (i = value.checked_offsets_up_to; i <= index_; i++)
299 {
300 gsize i_start, i_end;
301
302@@ -1060,6 +1078,7 @@ gvs_tuple_get_child (GVariantSerialised value,
303 }
304
305 value.ordered_offsets_up_to = i - 1;
306+ value.checked_offsets_up_to = index_;
307 }
308
309 if (index_ > value.ordered_offsets_up_to)
310@@ -1257,6 +1276,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
311
312 /* All element bounds have been checked above. */
313 value.ordered_offsets_up_to = G_MAXSIZE;
314+ value.checked_offsets_up_to = G_MAXSIZE;
315
316 {
317 gsize fixed_size;
318diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
319index 03826f9..2423e01 100644
320--- a/glib/gvariant-serialiser.h
321+++ b/glib/gvariant-serialiser.h
322@@ -40,6 +40,15 @@ typedef struct
323 * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
324 * rather than an index into the frame offsets. */
325 gsize ordered_offsets_up_to;
326+
327+ /* Similar to @ordered_offsets_up_to. This gives the index of the child element
328+ * whose frame offset is the highest in the offset table which has been
329+ * checked so far.
330+ *
331+ * This is always ≥ @ordered_offsets_up_to. It is always an element index.
332+ *
333+ * See documentation in gvariant-core.c for `struct GVariant` for details. */
334+ gsize checked_offsets_up_to;
335 } GVariantSerialised;
336
337 /* deserialization */
338diff --git a/glib/gvariant.c b/glib/gvariant.c
339index 1b1cbdc..2e288af 100644
340--- a/glib/gvariant.c
341+++ b/glib/gvariant.c
342@@ -5997,6 +5997,7 @@ g_variant_byteswap (GVariant *value)
343 serialised.data = g_malloc (serialised.size);
344 serialised.depth = g_variant_get_depth (trusted);
345 serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
346+ serialised.checked_offsets_up_to = G_MAXSIZE;
347 g_variant_store (trusted, serialised.data);
348 g_variant_unref (trusted);
349
350diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
351index 3ddff96..31a7dde 100644
352--- a/glib/tests/gvariant.c
353+++ b/glib/tests/gvariant.c
354@@ -1282,6 +1282,7 @@ random_instance_filler (GVariantSerialised *serialised,
355
356 serialised->depth = 0;
357 serialised->ordered_offsets_up_to = 0;
358+ serialised->checked_offsets_up_to = 0;
359
360 g_assert_true (serialised->type_info == instance->type_info);
361 g_assert_cmpuint (serialised->size, ==, instance->size);
362@@ -1449,6 +1450,7 @@ test_maybe (void)
363 serialised.size = needed_size;
364 serialised.depth = 0;
365 serialised.ordered_offsets_up_to = 0;
366+ serialised.checked_offsets_up_to = 0;
367
368 g_variant_serialiser_serialise (serialised,
369 random_instance_filler,
370@@ -1573,6 +1575,7 @@ test_array (void)
371 serialised.size = needed_size;
372 serialised.depth = 0;
373 serialised.ordered_offsets_up_to = 0;
374+ serialised.checked_offsets_up_to = 0;
375
376 g_variant_serialiser_serialise (serialised, random_instance_filler,
377 (gpointer *) instances, n_children);
378@@ -1738,6 +1741,7 @@ test_tuple (void)
379 serialised.size = needed_size;
380 serialised.depth = 0;
381 serialised.ordered_offsets_up_to = 0;
382+ serialised.checked_offsets_up_to = 0;
383
384 g_variant_serialiser_serialise (serialised, random_instance_filler,
385 (gpointer *) instances, n_children);
386@@ -1835,6 +1839,7 @@ test_variant (void)
387 serialised.size = needed_size;
388 serialised.depth = 0;
389 serialised.ordered_offsets_up_to = 0;
390+ serialised.checked_offsets_up_to = 0;
391
392 g_variant_serialiser_serialise (serialised, random_instance_filler,
393 (gpointer *) &instance, 1);
394--
3952.40.0
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..7a43b138f3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch
@@ -0,0 +1,98 @@
1From 298a537d5f6783e55d87e40011ee3fd3b22b72f9 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 01:39:01 +0000
4Subject: [PATCH] gvariant: Zero-initialise various GVariantSerialised objects
5
6The following few commits will add a couple of new fields to
7`GVariantSerialised`, and they should be zero-filled by default.
8
9Try and pre-empt that a bit by zero-filling `GVariantSerialised` by
10default in a few places.
11
12Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
13
14Helps: #2121
15
16CVE: CVE-2023-32665
17
18Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/298a537d5f6783e55d87e40011ee3fd3b22b72f9]
19
20Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
21---
22 glib/gvariant.c | 2 +-
23 glib/tests/gvariant.c | 12 ++++++------
24 2 files changed, 7 insertions(+), 7 deletions(-)
25
26diff --git a/glib/gvariant.c b/glib/gvariant.c
27index 2e288af..30a3280 100644
28--- a/glib/gvariant.c
29+++ b/glib/gvariant.c
30@@ -5987,7 +5987,7 @@ g_variant_byteswap (GVariant *value)
31 if (alignment)
32 /* (potentially) contains multi-byte numeric data */
33 {
34- GVariantSerialised serialised;
35+ GVariantSerialised serialised = { 0, };
36 GVariant *trusted;
37 GBytes *bytes;
38
39diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
40index 31a7dde..2f33a3e 100644
41--- a/glib/tests/gvariant.c
42+++ b/glib/tests/gvariant.c
43@@ -1442,7 +1442,7 @@ test_maybe (void)
44
45 for (flavour = 0; flavour < 8; flavour += alignment)
46 {
47- GVariantSerialised serialised;
48+ GVariantSerialised serialised = { 0, };
49 GVariantSerialised child;
50
51 serialised.type_info = type_info;
52@@ -1568,7 +1568,7 @@ test_array (void)
53
54 for (flavour = 0; flavour < 8; flavour += alignment)
55 {
56- GVariantSerialised serialised;
57+ GVariantSerialised serialised = { 0, };
58
59 serialised.type_info = array_info;
60 serialised.data = flavoured_malloc (needed_size, flavour);
61@@ -1734,7 +1734,7 @@ test_tuple (void)
62
63 for (flavour = 0; flavour < 8; flavour += alignment)
64 {
65- GVariantSerialised serialised;
66+ GVariantSerialised serialised = { 0, };
67
68 serialised.type_info = type_info;
69 serialised.data = flavoured_malloc (needed_size, flavour);
70@@ -1831,7 +1831,7 @@ test_variant (void)
71
72 for (flavour = 0; flavour < 8; flavour += alignment)
73 {
74- GVariantSerialised serialised;
75+ GVariantSerialised serialised = { 0, };
76 GVariantSerialised child;
77
78 serialised.type_info = type_info;
79@@ -2280,7 +2280,7 @@ serialise_tree (TreeInstance *tree,
80 static void
81 test_byteswap (void)
82 {
83- GVariantSerialised one, two;
84+ GVariantSerialised one = { 0, }, two = { 0, };
85 TreeInstance *tree;
86
87 tree = tree_instance_new (NULL, 3);
88@@ -2354,7 +2354,7 @@ test_serialiser_children (void)
89 static void
90 test_fuzz (gdouble *fuzziness)
91 {
92- GVariantSerialised serialised;
93+ GVariantSerialised serialised = { 0, };
94 TreeInstance *tree;
95
96 /* make an instance */
97--
982.40.0
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb
index b5ab6502a3..b04b5f0a44 100644
--- a/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb
+++ b/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb
@@ -17,6 +17,15 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
17 file://0001-meson-Run-atomics-test-on-clang-as-well.patch \ 17 file://0001-meson-Run-atomics-test-on-clang-as-well.patch \
18 file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ 18 file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \
19 file://0001-gio-tests-g-file-info-don-t-assume-million-in-one-ev.patch \ 19 file://0001-gio-tests-g-file-info-don-t-assume-million-in-one-ev.patch \
20 file://CVE-2023-32665-0001.patch \
21 file://CVE-2023-32665-0002.patch \
22 file://CVE-2023-32665-0003.patch \
23 file://CVE-2023-32665-0004.patch \
24 file://CVE-2023-32665-0005.patch \
25 file://CVE-2023-32665-0006.patch \
26 file://CVE-2023-32665-0007.patch \
27 file://CVE-2023-32665-0008.patch \
28 file://CVE-2023-32665-0009.patch \
20 " 29 "
21SRC_URI:append:class-native = " file://relocate-modules.patch" 30SRC_URI:append:class-native = " file://relocate-modules.patch"
22 31