diff options
author | Siddharth Doshi <sdoshi@mvista.com> | 2023-10-15 21:00:39 +0530 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2023-10-20 05:35:30 -1000 |
commit | aa99487732ab1ae453becdda08a3e72de0b7b269 (patch) | |
tree | 4e116f258212e3f01bcc04c3f1882916252b4cdf /meta | |
parent | 8ae21cd487a6147c3a2c9c2c0f0b2d5d149b7caf (diff) | |
download | poky-aa99487732ab1ae453becdda08a3e72de0b7b269.tar.gz |
glib-2.0: Fix multiple vulnerabilities
CVE's Fixed:
CVE-2023-29499: glib: GVariant offset table entry size is not checked in is_normal()
CVE-2023-32611: glib: g_variant_byteswap() can take a long time with some non-normal inputs
CVE-2023-32636: glib: Timeout in fuzz_variant_text
CVE-2023-32643: glib: Heap-buffer-overflow in g_variant_serialised_get_child
CVE-2023-32665: glib: GVariant deserialisation does not match spec for non-normal data
(From OE-Core rev: b576beba80d44e67762d46bf3bc2f14c05bc0f6b)
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
15 files changed, 2710 insertions, 0 deletions
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 @@ | |||
1 | From 5f4485c4ff57fdefb1661531788def7ca5a47328 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 17 Aug 2023 04:19:44 +0000 | ||
4 | Subject: [PATCH] gvariant-serialiser: Check offset table entry size is minimal | ||
5 | |||
6 | The entries in an offset table (which is used for variable sized arrays | ||
7 | and tuples containing variable sized members) are sized so that they can | ||
8 | address every byte in the overall variant. | ||
9 | |||
10 | The specification requires that for a variant to be in normal form, its | ||
11 | offset table entries must be the minimum width such that they can | ||
12 | address every byte in the variant. | ||
13 | |||
14 | That minimality requirement was not checked in | ||
15 | `g_variant_is_normal_form()`, leading to two different byte arrays being | ||
16 | interpreted as the normal form of a given variant tree. That kind of | ||
17 | confusion could potentially be exploited, and is certainly a bug. | ||
18 | |||
19 | Fix it by adding the necessary checks on offset table entry width, and | ||
20 | unit tests. | ||
21 | |||
22 | Spotted by William Manley. | ||
23 | |||
24 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
25 | |||
26 | Fixes: #2794 | ||
27 | |||
28 | CVE: CVE-2023-29499 | ||
29 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/5f4485c4ff57fdefb1661531788def7ca5a47328] | ||
30 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
31 | --- | ||
32 | glib/gvariant-serialiser.c | 19 +++- | ||
33 | glib/tests/gvariant.c | 176 +++++++++++++++++++++++++++++++++++++ | ||
34 | 2 files changed, 194 insertions(+), 1 deletion(-) | ||
35 | |||
36 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
37 | index 0bf7243..5aa2cbc 100644 | ||
38 | --- a/glib/gvariant-serialiser.c | ||
39 | +++ b/glib/gvariant-serialiser.c | ||
40 | @@ -694,6 +694,10 @@ gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value) | ||
41 | out.data_size = last_end; | ||
42 | out.array = value.data + last_end; | ||
43 | out.length = offsets_array_size / out.offset_size; | ||
44 | + | ||
45 | + if (out.length > 0 && gvs_calculate_total_size (last_end, out.length) != value.size) | ||
46 | + return out; /* offset size not minimal */ | ||
47 | + | ||
48 | out.is_normal = TRUE; | ||
49 | |||
50 | return out; | ||
51 | @@ -1201,6 +1205,7 @@ gvs_tuple_is_normal (GVariantSerialised value) | ||
52 | gsize length; | ||
53 | gsize offset; | ||
54 | gsize i; | ||
55 | + gsize offset_table_size; | ||
56 | |||
57 | /* as per the comment in gvs_tuple_get_child() */ | ||
58 | if G_UNLIKELY (value.data == NULL && value.size != 0) | ||
59 | @@ -1305,7 +1310,19 @@ gvs_tuple_is_normal (GVariantSerialised value) | ||
60 | } | ||
61 | } | ||
62 | |||
63 | - return offset_ptr == offset; | ||
64 | + /* @offset_ptr has been counting backwards from the end of the variant, to | ||
65 | + * find the beginning of the offset table. @offset has been counting forwards | ||
66 | + * from the beginning of the variant to find the end of the data. They should | ||
67 | + * have met in the middle. */ | ||
68 | + if (offset_ptr != offset) | ||
69 | + return FALSE; | ||
70 | + | ||
71 | + offset_table_size = value.size - offset_ptr; | ||
72 | + if (value.size > 0 && | ||
73 | + gvs_calculate_total_size (offset, offset_table_size / offset_size) != value.size) | ||
74 | + return FALSE; /* offset size not minimal */ | ||
75 | + | ||
76 | + return TRUE; | ||
77 | } | ||
78 | |||
79 | /* Variants {{{2 | ||
80 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
81 | index d640c81..4ce0e4f 100644 | ||
82 | --- a/glib/tests/gvariant.c | ||
83 | +++ b/glib/tests/gvariant.c | ||
84 | @@ -5092,6 +5092,86 @@ test_normal_checking_array_offsets2 (void) | ||
85 | g_variant_unref (variant); | ||
86 | } | ||
87 | |||
88 | +/* Test that an otherwise-valid serialised GVariant is considered non-normal if | ||
89 | + * its offset table entries are too wide. | ||
90 | + * | ||
91 | + * See §2.3.6 (Framing Offsets) of the GVariant specification. */ | ||
92 | +static void | ||
93 | +test_normal_checking_array_offsets_minimal_sized (void) | ||
94 | +{ | ||
95 | + GVariantBuilder builder; | ||
96 | + gsize i; | ||
97 | + GVariant *aay_constructed = NULL; | ||
98 | + const guint8 *data = NULL; | ||
99 | + guint8 *data_owned = NULL; | ||
100 | + GVariant *aay_deserialised = NULL; | ||
101 | + GVariant *aay_normalised = NULL; | ||
102 | + | ||
103 | + /* Construct an array of type aay, consisting of 128 elements which are each | ||
104 | + * an empty array, i.e. `[[] * 128]`. This is chosen because the inner | ||
105 | + * elements are variable sized (making the outer array variable sized, so it | ||
106 | + * must have an offset table), but they are also zero-sized when serialised. | ||
107 | + * So the serialised representation of @aay_constructed consists entirely of | ||
108 | + * its offset table, which is entirely zeroes. | ||
109 | + * | ||
110 | + * The array is chosen to be 128 elements long because that means offset | ||
111 | + * table entries which are 1 byte long. If the elements in the array were | ||
112 | + * non-zero-sized (to the extent that the overall array is ≥256 bytes long), | ||
113 | + * the offset table entries would end up being 2 bytes long. */ | ||
114 | + g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay")); | ||
115 | + | ||
116 | + for (i = 0; i < 128; i++) | ||
117 | + g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0)); | ||
118 | + | ||
119 | + aay_constructed = g_variant_builder_end (&builder); | ||
120 | + | ||
121 | + /* Verify that the constructed array is in normal form, and its serialised | ||
122 | + * form is `b'\0' * 128`. */ | ||
123 | + g_assert_true (g_variant_is_normal_form (aay_constructed)); | ||
124 | + g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128); | ||
125 | + g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128); | ||
126 | + | ||
127 | + data = g_variant_get_data (aay_constructed); | ||
128 | + for (i = 0; i < g_variant_get_size (aay_constructed); i++) | ||
129 | + g_assert_cmpuint (data[i], ==, 0); | ||
130 | + | ||
131 | + /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to | ||
132 | + * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table | ||
133 | + * entries, because each offset table entry has to be able to reference all of | ||
134 | + * the byte boundaries in the container. All the entries in the offset table | ||
135 | + * are zero, so all the elements of the array are zero-sized. */ | ||
136 | + data = data_owned = g_malloc0 (256); | ||
137 | + aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"), | ||
138 | + data, | ||
139 | + 256, | ||
140 | + FALSE, | ||
141 | + g_free, | ||
142 | + g_steal_pointer (&data_owned)); | ||
143 | + | ||
144 | + g_assert_false (g_variant_is_normal_form (aay_deserialised)); | ||
145 | + g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128); | ||
146 | + g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256); | ||
147 | + | ||
148 | + data = g_variant_get_data (aay_deserialised); | ||
149 | + for (i = 0; i < g_variant_get_size (aay_deserialised); i++) | ||
150 | + g_assert_cmpuint (data[i], ==, 0); | ||
151 | + | ||
152 | + /* Get its normal form. That should change the serialised size. */ | ||
153 | + aay_normalised = g_variant_get_normal_form (aay_deserialised); | ||
154 | + | ||
155 | + g_assert_true (g_variant_is_normal_form (aay_normalised)); | ||
156 | + g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128); | ||
157 | + g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128); | ||
158 | + | ||
159 | + data = g_variant_get_data (aay_normalised); | ||
160 | + for (i = 0; i < g_variant_get_size (aay_normalised); i++) | ||
161 | + g_assert_cmpuint (data[i], ==, 0); | ||
162 | + | ||
163 | + g_variant_unref (aay_normalised); | ||
164 | + g_variant_unref (aay_deserialised); | ||
165 | + g_variant_unref (aay_constructed); | ||
166 | +} | ||
167 | + | ||
168 | /* Test that a tuple with invalidly large values in its offset table is | ||
169 | * normalised successfully without looping infinitely. */ | ||
170 | static void | ||
171 | @@ -5286,6 +5366,98 @@ test_normal_checking_tuple_offsets4 (void) | ||
172 | g_variant_unref (variant); | ||
173 | } | ||
174 | |||
175 | +/* Test that an otherwise-valid serialised GVariant is considered non-normal if | ||
176 | + * its offset table entries are too wide. | ||
177 | + * | ||
178 | + * See §2.3.6 (Framing Offsets) of the GVariant specification. */ | ||
179 | +static void | ||
180 | +test_normal_checking_tuple_offsets_minimal_sized (void) | ||
181 | +{ | ||
182 | + GString *type_string = NULL; | ||
183 | + GVariantBuilder builder; | ||
184 | + gsize i; | ||
185 | + GVariant *ray_constructed = NULL; | ||
186 | + const guint8 *data = NULL; | ||
187 | + guint8 *data_owned = NULL; | ||
188 | + GVariant *ray_deserialised = NULL; | ||
189 | + GVariant *ray_normalised = NULL; | ||
190 | + | ||
191 | + /* Construct a tuple of type (ay…ay), consisting of 129 members which are each | ||
192 | + * an empty array, i.e. `([] * 129)`. This is chosen because the inner | ||
193 | + * members are variable sized, so the outer tuple must have an offset table, | ||
194 | + * but they are also zero-sized when serialised. So the serialised | ||
195 | + * representation of @ray_constructed consists entirely of its offset table, | ||
196 | + * which is entirely zeroes. | ||
197 | + * | ||
198 | + * The tuple is chosen to be 129 members long because that means it has 128 | ||
199 | + * offset table entries which are 1 byte long each. If the members in the | ||
200 | + * tuple were non-zero-sized (to the extent that the overall tuple is ≥256 | ||
201 | + * bytes long), the offset table entries would end up being 2 bytes long. | ||
202 | + * | ||
203 | + * 129 members are used unlike 128 array elements in | ||
204 | + * test_normal_checking_array_offsets_minimal_sized(), because the last member | ||
205 | + * in a tuple never needs an offset table entry. */ | ||
206 | + type_string = g_string_new (""); | ||
207 | + g_string_append_c (type_string, '('); | ||
208 | + for (i = 0; i < 129; i++) | ||
209 | + g_string_append (type_string, "ay"); | ||
210 | + g_string_append_c (type_string, ')'); | ||
211 | + | ||
212 | + g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str)); | ||
213 | + | ||
214 | + for (i = 0; i < 129; i++) | ||
215 | + g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0)); | ||
216 | + | ||
217 | + ray_constructed = g_variant_builder_end (&builder); | ||
218 | + | ||
219 | + /* Verify that the constructed tuple is in normal form, and its serialised | ||
220 | + * form is `b'\0' * 128`. */ | ||
221 | + g_assert_true (g_variant_is_normal_form (ray_constructed)); | ||
222 | + g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129); | ||
223 | + g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128); | ||
224 | + | ||
225 | + data = g_variant_get_data (ray_constructed); | ||
226 | + for (i = 0; i < g_variant_get_size (ray_constructed); i++) | ||
227 | + g_assert_cmpuint (data[i], ==, 0); | ||
228 | + | ||
229 | + /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has | ||
230 | + * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table | ||
231 | + * entries, because each offset table entry has to be able to reference all of | ||
232 | + * the byte boundaries in the container. All the entries in the offset table | ||
233 | + * are zero, so all the members of the tuple are zero-sized. */ | ||
234 | + data = data_owned = g_malloc0 (256); | ||
235 | + ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str), | ||
236 | + data, | ||
237 | + 256, | ||
238 | + FALSE, | ||
239 | + g_free, | ||
240 | + g_steal_pointer (&data_owned)); | ||
241 | + | ||
242 | + g_assert_false (g_variant_is_normal_form (ray_deserialised)); | ||
243 | + g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129); | ||
244 | + g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256); | ||
245 | + | ||
246 | + data = g_variant_get_data (ray_deserialised); | ||
247 | + for (i = 0; i < g_variant_get_size (ray_deserialised); i++) | ||
248 | + g_assert_cmpuint (data[i], ==, 0); | ||
249 | + | ||
250 | + /* Get its normal form. That should change the serialised size. */ | ||
251 | + ray_normalised = g_variant_get_normal_form (ray_deserialised); | ||
252 | + | ||
253 | + g_assert_true (g_variant_is_normal_form (ray_normalised)); | ||
254 | + g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129); | ||
255 | + g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128); | ||
256 | + | ||
257 | + data = g_variant_get_data (ray_normalised); | ||
258 | + for (i = 0; i < g_variant_get_size (ray_normalised); i++) | ||
259 | + g_assert_cmpuint (data[i], ==, 0); | ||
260 | + | ||
261 | + g_variant_unref (ray_normalised); | ||
262 | + g_variant_unref (ray_deserialised); | ||
263 | + g_variant_unref (ray_constructed); | ||
264 | + g_string_free (type_string, TRUE); | ||
265 | +} | ||
266 | + | ||
267 | /* Test that an empty object path is normalised successfully to the base object | ||
268 | * path, ‘/’. */ | ||
269 | static void | ||
270 | @@ -5431,6 +5603,8 @@ main (int argc, char **argv) | ||
271 | test_normal_checking_array_offsets); | ||
272 | g_test_add_func ("/gvariant/normal-checking/array-offsets2", | ||
273 | test_normal_checking_array_offsets2); | ||
274 | + g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized", | ||
275 | + test_normal_checking_array_offsets_minimal_sized); | ||
276 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets", | ||
277 | test_normal_checking_tuple_offsets); | ||
278 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets2", | ||
279 | @@ -5439,6 +5613,8 @@ main (int argc, char **argv) | ||
280 | test_normal_checking_tuple_offsets3); | ||
281 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets4", | ||
282 | test_normal_checking_tuple_offsets4); | ||
283 | + g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized", | ||
284 | + test_normal_checking_tuple_offsets_minimal_sized); | ||
285 | g_test_add_func ("/gvariant/normal-checking/empty-object-path", | ||
286 | test_normal_checking_empty_object_path); | ||
287 | |||
288 | -- | ||
289 | 2.24.4 | ||
290 | |||
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 @@ | |||
1 | From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001 | ||
2 | From: William Manley <will@stb-tester.com> | ||
3 | Date: Wed, 9 Aug 2023 10:04:49 +0000 | ||
4 | Subject: [PATCH] gvariant-core: Consolidate construction of | ||
5 | `GVariantSerialised` | ||
6 | |||
7 | So I only need to change it in one place. | ||
8 | |||
9 | This introduces no functional changes. | ||
10 | |||
11 | Helps: #2121 | ||
12 | |||
13 | CVE: CVE-2023-32665 | ||
14 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1] | ||
15 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
16 | --- | ||
17 | glib/gvariant.c | 8 +++++--- | ||
18 | glib/tests/gvariant.c | 24 ++++++++++++++++++++++++ | ||
19 | 2 files changed, 29 insertions(+), 3 deletions(-) | ||
20 | |||
21 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
22 | index 8ba701e..4dbd9e8 100644 | ||
23 | --- a/glib/gvariant.c | ||
24 | +++ b/glib/gvariant.c | ||
25 | @@ -5952,14 +5952,16 @@ g_variant_byteswap (GVariant *value) | ||
26 | g_variant_serialised_byteswap (serialised); | ||
27 | |||
28 | bytes = g_bytes_new_take (serialised.data, serialised.size); | ||
29 | - new = g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE); | ||
30 | + new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE)); | ||
31 | g_bytes_unref (bytes); | ||
32 | } | ||
33 | else | ||
34 | /* contains no multi-byte data */ | ||
35 | - new = value; | ||
36 | + new = g_variant_get_normal_form (value); | ||
37 | |||
38 | - return g_variant_ref_sink (new); | ||
39 | + g_assert (g_variant_is_trusted (new)); | ||
40 | + | ||
41 | + return g_steal_pointer (&new); | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
46 | index 4ce0e4f..3dda08e 100644 | ||
47 | --- a/glib/tests/gvariant.c | ||
48 | +++ b/glib/tests/gvariant.c | ||
49 | @@ -3834,6 +3834,29 @@ test_gv_byteswap (void) | ||
50 | g_free (string); | ||
51 | } | ||
52 | |||
53 | +static void | ||
54 | +test_gv_byteswap_non_normal_non_aligned (void) | ||
55 | +{ | ||
56 | + const guint8 data[] = { 0x02 }; | ||
57 | + GVariant *v = NULL; | ||
58 | + GVariant *v_byteswapped = NULL; | ||
59 | + | ||
60 | + g_test_summary ("Test that calling g_variant_byteswap() on a variant which " | ||
61 | + "is in non-normal form and doesn’t need byteswapping returns " | ||
62 | + "the same variant in normal form."); | ||
63 | + | ||
64 | + v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL); | ||
65 | + g_assert_false (g_variant_is_normal_form (v)); | ||
66 | + | ||
67 | + v_byteswapped = g_variant_byteswap (v); | ||
68 | + g_assert_true (g_variant_is_normal_form (v_byteswapped)); | ||
69 | + | ||
70 | + g_assert_cmpvariant (v, v_byteswapped); | ||
71 | + | ||
72 | + g_variant_unref (v); | ||
73 | + g_variant_unref (v_byteswapped); | ||
74 | +} | ||
75 | + | ||
76 | static void | ||
77 | test_parser (void) | ||
78 | { | ||
79 | @@ -5570,6 +5593,7 @@ main (int argc, char **argv) | ||
80 | g_test_add_func ("/gvariant/builder-memory", test_builder_memory); | ||
81 | g_test_add_func ("/gvariant/hashing", test_hashing); | ||
82 | g_test_add_func ("/gvariant/byteswap", test_gv_byteswap); | ||
83 | + g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned); | ||
84 | g_test_add_func ("/gvariant/parser", test_parses); | ||
85 | g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds); | ||
86 | g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion); | ||
87 | -- | ||
88 | 2.24.4 | ||
89 | |||
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 @@ | |||
1 | From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001 | ||
2 | From: William Manley <will@stb-tester.com> | ||
3 | Date: Wed, 9 Aug 2023 10:39:34 +0000 | ||
4 | Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with | ||
5 | framing offsets | ||
6 | |||
7 | This introduces no functional changes. | ||
8 | |||
9 | Helps: #2121 | ||
10 | |||
11 | CVE: CVE-2023-32665 | ||
12 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948] | ||
13 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
14 | --- | ||
15 | glib/gvariant.c | 81 +++++++++++++++++++++++++++++++++---------- | ||
16 | glib/tests/gvariant.c | 57 ++++++++++++++++++++++++++---- | ||
17 | 2 files changed, 112 insertions(+), 26 deletions(-) | ||
18 | |||
19 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
20 | index 4dbd9e8..a80c2c9 100644 | ||
21 | --- a/glib/gvariant.c | ||
22 | +++ b/glib/gvariant.c | ||
23 | @@ -5788,7 +5788,8 @@ g_variant_iter_loop (GVariantIter *iter, | ||
24 | |||
25 | /* Serialised data {{{1 */ | ||
26 | static GVariant * | ||
27 | -g_variant_deep_copy (GVariant *value) | ||
28 | +g_variant_deep_copy (GVariant *value, | ||
29 | + gboolean byteswap) | ||
30 | { | ||
31 | switch (g_variant_classify (value)) | ||
32 | { | ||
33 | @@ -5806,7 +5807,7 @@ g_variant_deep_copy (GVariant *value) | ||
34 | for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++) | ||
35 | { | ||
36 | GVariant *child = g_variant_get_child_value (value, i); | ||
37 | - g_variant_builder_add_value (&builder, g_variant_deep_copy (child)); | ||
38 | + g_variant_builder_add_value (&builder, g_variant_deep_copy (child, byteswap)); | ||
39 | g_variant_unref (child); | ||
40 | } | ||
41 | |||
42 | @@ -5820,28 +5821,63 @@ g_variant_deep_copy (GVariant *value) | ||
43 | return g_variant_new_byte (g_variant_get_byte (value)); | ||
44 | |||
45 | case G_VARIANT_CLASS_INT16: | ||
46 | - return g_variant_new_int16 (g_variant_get_int16 (value)); | ||
47 | + if (byteswap) | ||
48 | + return g_variant_new_int16 (GUINT16_SWAP_LE_BE (g_variant_get_int16 (value))); | ||
49 | + else | ||
50 | + return g_variant_new_int16 (g_variant_get_int16 (value)); | ||
51 | |||
52 | case G_VARIANT_CLASS_UINT16: | ||
53 | - return g_variant_new_uint16 (g_variant_get_uint16 (value)); | ||
54 | + if (byteswap) | ||
55 | + return g_variant_new_uint16 (GUINT16_SWAP_LE_BE (g_variant_get_uint16 (value))); | ||
56 | + else | ||
57 | + return g_variant_new_uint16 (g_variant_get_uint16 (value)); | ||
58 | |||
59 | case G_VARIANT_CLASS_INT32: | ||
60 | - return g_variant_new_int32 (g_variant_get_int32 (value)); | ||
61 | + if (byteswap) | ||
62 | + return g_variant_new_int32 (GUINT32_SWAP_LE_BE (g_variant_get_int32 (value))); | ||
63 | + else | ||
64 | + return g_variant_new_int32 (g_variant_get_int32 (value)); | ||
65 | |||
66 | case G_VARIANT_CLASS_UINT32: | ||
67 | - return g_variant_new_uint32 (g_variant_get_uint32 (value)); | ||
68 | + if (byteswap) | ||
69 | + return g_variant_new_uint32 (GUINT32_SWAP_LE_BE (g_variant_get_uint32 (value))); | ||
70 | + else | ||
71 | + return g_variant_new_uint32 (g_variant_get_uint32 (value)); | ||
72 | |||
73 | case G_VARIANT_CLASS_INT64: | ||
74 | - return g_variant_new_int64 (g_variant_get_int64 (value)); | ||
75 | + if (byteswap) | ||
76 | + return g_variant_new_int64 (GUINT64_SWAP_LE_BE (g_variant_get_int64 (value))); | ||
77 | + else | ||
78 | + return g_variant_new_int64 (g_variant_get_int64 (value)); | ||
79 | |||
80 | case G_VARIANT_CLASS_UINT64: | ||
81 | - return g_variant_new_uint64 (g_variant_get_uint64 (value)); | ||
82 | + if (byteswap) | ||
83 | + return g_variant_new_uint64 (GUINT64_SWAP_LE_BE (g_variant_get_uint64 (value))); | ||
84 | + else | ||
85 | + return g_variant_new_uint64 (g_variant_get_uint64 (value)); | ||
86 | |||
87 | case G_VARIANT_CLASS_HANDLE: | ||
88 | - return g_variant_new_handle (g_variant_get_handle (value)); | ||
89 | + if (byteswap) | ||
90 | + return g_variant_new_handle (GUINT32_SWAP_LE_BE (g_variant_get_handle (value))); | ||
91 | + else | ||
92 | + return g_variant_new_handle (g_variant_get_handle (value)); | ||
93 | |||
94 | case G_VARIANT_CLASS_DOUBLE: | ||
95 | - return g_variant_new_double (g_variant_get_double (value)); | ||
96 | + if (byteswap) | ||
97 | + { | ||
98 | + /* We have to convert the double to a uint64 here using a union, | ||
99 | + * because a cast will round it numerically. */ | ||
100 | + union | ||
101 | + { | ||
102 | + guint64 u64; | ||
103 | + gdouble dbl; | ||
104 | + } u1, u2; | ||
105 | + u1.dbl = g_variant_get_double (value); | ||
106 | + u2.u64 = GUINT64_SWAP_LE_BE (u1.u64); | ||
107 | + return g_variant_new_double (u2.dbl); | ||
108 | + } | ||
109 | + else | ||
110 | + return g_variant_new_double (g_variant_get_double (value)); | ||
111 | |||
112 | case G_VARIANT_CLASS_STRING: | ||
113 | return g_variant_new_string (g_variant_get_string (value, NULL)); | ||
114 | @@ -5896,7 +5932,7 @@ g_variant_get_normal_form (GVariant *value) | ||
115 | if (g_variant_is_normal_form (value)) | ||
116 | return g_variant_ref (value); | ||
117 | |||
118 | - trusted = g_variant_deep_copy (value); | ||
119 | + trusted = g_variant_deep_copy (value, FALSE); | ||
120 | g_assert (g_variant_is_trusted (trusted)); | ||
121 | |||
122 | return g_variant_ref_sink (trusted); | ||
123 | @@ -5916,6 +5952,11 @@ g_variant_get_normal_form (GVariant *value) | ||
124 | * contain multi-byte numeric data. That include strings, booleans, | ||
125 | * bytes and containers containing only these things (recursively). | ||
126 | * | ||
127 | + * While this function can safely handle untrusted, non-normal data, it is | ||
128 | + * recommended to check whether the input is in normal form beforehand, using | ||
129 | + * g_variant_is_normal_form(), and to reject non-normal inputs if your | ||
130 | + * application can be strict about what inputs it rejects. | ||
131 | + * | ||
132 | * The returned value is always in normal form and is marked as trusted. | ||
133 | * | ||
134 | * Returns: (transfer full): the byteswapped form of @value | ||
135 | @@ -5933,21 +5974,20 @@ g_variant_byteswap (GVariant *value) | ||
136 | |||
137 | g_variant_type_info_query (type_info, &alignment, NULL); | ||
138 | |||
139 | - if (alignment) | ||
140 | - /* (potentially) contains multi-byte numeric data */ | ||
141 | + if (alignment && g_variant_is_normal_form (value)) | ||
142 | { | ||
143 | + /* (potentially) contains multi-byte numeric data, but is also already in | ||
144 | + * normal form so we can use a faster byteswapping codepath on the | ||
145 | + * serialised data */ | ||
146 | GVariantSerialised serialised = { 0, }; | ||
147 | - GVariant *trusted; | ||
148 | GBytes *bytes; | ||
149 | |||
150 | - trusted = g_variant_get_normal_form (value); | ||
151 | - serialised.type_info = g_variant_get_type_info (trusted); | ||
152 | - serialised.size = g_variant_get_size (trusted); | ||
153 | + serialised.type_info = g_variant_get_type_info (value); | ||
154 | + serialised.size = g_variant_get_size (value); | ||
155 | serialised.data = g_malloc (serialised.size); | ||
156 | serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */ | ||
157 | serialised.checked_offsets_up_to = G_MAXSIZE; | ||
158 | - g_variant_store (trusted, serialised.data); | ||
159 | - g_variant_unref (trusted); | ||
160 | + g_variant_store (value, serialised.data); | ||
161 | |||
162 | g_variant_serialised_byteswap (serialised); | ||
163 | |||
164 | @@ -5955,6 +5995,9 @@ g_variant_byteswap (GVariant *value) | ||
165 | new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE)); | ||
166 | g_bytes_unref (bytes); | ||
167 | } | ||
168 | + else if (alignment) | ||
169 | + /* (potentially) contains multi-byte numeric data */ | ||
170 | + new = g_variant_ref_sink (g_variant_deep_copy (value, TRUE)); | ||
171 | else | ||
172 | /* contains no multi-byte data */ | ||
173 | new = g_variant_get_normal_form (value); | ||
174 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
175 | index 3dda08e..679dd40 100644 | ||
176 | --- a/glib/tests/gvariant.c | ||
177 | +++ b/glib/tests/gvariant.c | ||
178 | @@ -2284,24 +2284,67 @@ serialise_tree (TreeInstance *tree, | ||
179 | static void | ||
180 | test_byteswap (void) | ||
181 | { | ||
182 | - GVariantSerialised one = { 0, }, two = { 0, }; | ||
183 | + GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, }; | ||
184 | TreeInstance *tree; | ||
185 | - | ||
186 | + GVariant *one_variant = NULL; | ||
187 | + GVariant *two_variant = NULL; | ||
188 | + GVariant *two_byteswapped = NULL; | ||
189 | + GVariant *three_variant = NULL; | ||
190 | + GVariant *three_byteswapped = NULL; | ||
191 | + guint8 *three_data_copy = NULL; | ||
192 | + gsize three_size_copy = 0; | ||
193 | + | ||
194 | + /* Write a tree out twice, once normally and once byteswapped. */ | ||
195 | tree = tree_instance_new (NULL, 3); | ||
196 | serialise_tree (tree, &one); | ||
197 | |||
198 | + one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)), | ||
199 | + one.data, one.size, FALSE, NULL, NULL); | ||
200 | + | ||
201 | i_am_writing_byteswapped = TRUE; | ||
202 | serialise_tree (tree, &two); | ||
203 | + serialise_tree (tree, &three); | ||
204 | i_am_writing_byteswapped = FALSE; | ||
205 | |||
206 | - g_variant_serialised_byteswap (two); | ||
207 | - | ||
208 | - g_assert_cmpmem (one.data, one.size, two.data, two.size); | ||
209 | - g_assert_cmpuint (one.depth, ==, two.depth); | ||
210 | - | ||
211 | + /* Swap the first byteswapped one back using the function we want to test. */ | ||
212 | + two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)), | ||
213 | + two.data, two.size, FALSE, NULL, NULL); | ||
214 | + two_byteswapped = g_variant_byteswap (two_variant); | ||
215 | + | ||
216 | + /* Make the second byteswapped one non-normal (hopefully), and then byteswap | ||
217 | + * it back using the function we want to test in its non-normal mode. | ||
218 | + * This might not work because it’s not necessarily possible to make an | ||
219 | + * arbitrary random variant non-normal. Adding a single zero byte to the end | ||
220 | + * often makes something non-normal but still readable. */ | ||
221 | + three_size_copy = three.size + 1; | ||
222 | + three_data_copy = g_malloc (three_size_copy); | ||
223 | + memcpy (three_data_copy, three.data, three.size); | ||
224 | + three_data_copy[three.size] = '\0'; | ||
225 | + | ||
226 | + three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)), | ||
227 | + three_data_copy, three_size_copy, FALSE, NULL, NULL); | ||
228 | + three_byteswapped = g_variant_byteswap (three_variant); | ||
229 | + | ||
230 | + /* Check they’re the same. We can always compare @one_variant and | ||
231 | + * @two_byteswapped. We can only compare @two_byteswapped and | ||
232 | + * @three_byteswapped if @two_variant and @three_variant are equal: in that | ||
233 | + * case, the corruption to @three_variant was enough to make it non-normal but | ||
234 | + * not enough to change its value. */ | ||
235 | + g_assert_cmpvariant (one_variant, two_byteswapped); | ||
236 | + | ||
237 | + if (g_variant_equal (two_variant, three_variant)) | ||
238 | + g_assert_cmpvariant (two_byteswapped, three_byteswapped); | ||
239 | + | ||
240 | + g_variant_unref (three_byteswapped); | ||
241 | + g_variant_unref (three_variant); | ||
242 | + g_variant_unref (two_byteswapped); | ||
243 | + g_variant_unref (two_variant); | ||
244 | + g_variant_unref (one_variant); | ||
245 | tree_instance_free (tree); | ||
246 | g_free (one.data); | ||
247 | g_free (two.data); | ||
248 | + g_free (three.data); | ||
249 | + g_free (three_data_copy); | ||
250 | } | ||
251 | |||
252 | static void | ||
253 | -- | ||
254 | 2.24.4 | ||
255 | |||
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 @@ | |||
1 | From 21a204147b16539b3eda3143b32844c49e29f4d4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 17 Aug 2023 11:33:49 +0000 | ||
4 | Subject: [PATCH] gvariant: Propagate trust when getting a child of a | ||
5 | serialised variant | ||
6 | |||
7 | If a variant is trusted, that means all its children are trusted, so | ||
8 | ensure that their checked offsets are set as such. | ||
9 | |||
10 | This allows a lot of the offset table checks to be avoided when getting | ||
11 | children from trusted serialised tuples, which speeds things up. | ||
12 | |||
13 | No unit test is included because this is just a performance fix. If | ||
14 | there are other slownesses, or regressions, in serialised `GVariant` | ||
15 | performance, the fuzzing setup will catch them like it did this one. | ||
16 | |||
17 | This change does reduce the time to run the oss-fuzz reproducer from 80s | ||
18 | to about 0.7s on my machine. | ||
19 | |||
20 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
21 | |||
22 | Fixes: #2841 | ||
23 | oss-fuzz#54314 | ||
24 | |||
25 | CVE: CVE-2023-32636 | ||
26 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/21a204147b16539b3eda3143b32844c49e29f4d4] | ||
27 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
28 | --- | ||
29 | glib/gvariant-core.c | 4 ++-- | ||
30 | 1 file changed, 2 insertions(+), 2 deletions(-) | ||
31 | |||
32 | diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c | ||
33 | index 1b9d5cc..ed57c70 100644 | ||
34 | --- a/glib/gvariant-core.c | ||
35 | +++ b/glib/gvariant-core.c | ||
36 | @@ -1173,8 +1173,8 @@ g_variant_get_child_value (GVariant *value, | ||
37 | child->contents.serialised.bytes = | ||
38 | g_bytes_ref (value->contents.serialised.bytes); | ||
39 | child->contents.serialised.data = s_child.data; | ||
40 | - child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to; | ||
41 | - child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to; | ||
42 | + child->contents.serialised.ordered_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.ordered_offsets_up_to; | ||
43 | + child->contents.serialised.checked_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.checked_offsets_up_to; | ||
44 | |||
45 | return child; | ||
46 | } | ||
47 | -- | ||
48 | 2.24.4 | ||
49 | |||
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 @@ | |||
1 | From 78da5faccb3e065116b75b3ff87ff55381da6c76 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 17 Aug 2023 11:24:43 +0000 | ||
4 | Subject: [PATCH] gvariant: Check offset table doesn't fall outside variant | ||
5 | bounds | ||
6 | |||
7 | When dereferencing the first entry in the offset table for a tuple, | ||
8 | check that it doesn’t fall outside the bounds of the variant first. | ||
9 | |||
10 | This prevents an out-of-bounds read from some non-normal tuples. | ||
11 | |||
12 | This bug was introduced in commit 73d0aa81c2575a5c9ae77d. | ||
13 | |||
14 | Includes a unit test, although the test will likely only catch the | ||
15 | original bug if run with asan enabled. | ||
16 | |||
17 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
18 | |||
19 | Fixes: #2840 | ||
20 | oss-fuzz#54302 | ||
21 | |||
22 | CVE: CVE-2023-32643 | ||
23 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/78da5faccb3e065116b75b3ff87ff55381da6c76] | ||
24 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
25 | --- | ||
26 | glib/gvariant-serialiser.c | 12 ++++++-- | ||
27 | glib/tests/gvariant.c | 63 ++++++++++++++++++++++++++++++++++++++ | ||
28 | 2 files changed, 72 insertions(+), 3 deletions(-) | ||
29 | |||
30 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
31 | index 5aa2cbc..4e50ed7 100644 | ||
32 | --- a/glib/gvariant-serialiser.c | ||
33 | +++ b/glib/gvariant-serialiser.c | ||
34 | @@ -979,7 +979,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
35 | |||
36 | member_info = g_variant_type_info_member_info (value.type_info, index_); | ||
37 | |||
38 | - if (member_info->i + 1) | ||
39 | + if (member_info->i + 1 && | ||
40 | + offset_size * (member_info->i + 1) <= value.size) | ||
41 | member_start = gvs_read_unaligned_le (value.data + value.size - | ||
42 | offset_size * (member_info->i + 1), | ||
43 | offset_size); | ||
44 | @@ -990,7 +991,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
45 | member_start &= member_info->b; | ||
46 | member_start |= member_info->c; | ||
47 | |||
48 | - if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST) | ||
49 | + if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST && | ||
50 | + offset_size * (member_info->i + 1) <= value.size) | ||
51 | member_end = value.size - offset_size * (member_info->i + 1); | ||
52 | |||
53 | else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED) | ||
54 | @@ -1001,11 +1003,15 @@ gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
55 | member_end = member_start + fixed_size; | ||
56 | } | ||
57 | |||
58 | - else /* G_VARIANT_MEMBER_ENDING_OFFSET */ | ||
59 | + else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET && | ||
60 | + offset_size * (member_info->i + 2) <= value.size) | ||
61 | member_end = gvs_read_unaligned_le (value.data + value.size - | ||
62 | offset_size * (member_info->i + 2), | ||
63 | offset_size); | ||
64 | |||
65 | + else /* invalid */ | ||
66 | + member_end = G_MAXSIZE; | ||
67 | + | ||
68 | if (out_member_start != NULL) | ||
69 | *out_member_start = member_start; | ||
70 | if (out_member_end != NULL) | ||
71 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
72 | index 679dd40..2eca8be 100644 | ||
73 | --- a/glib/tests/gvariant.c | ||
74 | +++ b/glib/tests/gvariant.c | ||
75 | @@ -5432,6 +5432,67 @@ test_normal_checking_tuple_offsets4 (void) | ||
76 | g_variant_unref (variant); | ||
77 | } | ||
78 | |||
79 | +/* This is a regression test that dereferencing the first element in the offset | ||
80 | + * table doesn’t dereference memory before the start of the GVariant. The first | ||
81 | + * element in the offset table gives the offset of the final member in the | ||
82 | + * tuple (the offset table is stored in reverse), and the position of this final | ||
83 | + * member is needed to check that none of the tuple members overlap with the | ||
84 | + * offset table | ||
85 | + * | ||
86 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */ | ||
87 | +static void | ||
88 | +test_normal_checking_tuple_offsets5 (void) | ||
89 | +{ | ||
90 | + /* A tuple of type (sss) in normal form would have an offset table with two | ||
91 | + * entries: | ||
92 | + * - The first entry (lowest index in the table) gives the offset of the | ||
93 | + * third `s` in the tuple, as the offset table is reversed compared to the | ||
94 | + * tuple members. | ||
95 | + * - The second entry (highest index in the table) gives the offset of the | ||
96 | + * second `s` in the tuple. | ||
97 | + * - The offset of the first `s` in the tuple is always 0. | ||
98 | + * | ||
99 | + * See §2.5.4 (Structures) of the GVariant specification for details, noting | ||
100 | + * that the table is only layed out this way because all three members of the | ||
101 | + * tuple have non-fixed sizes. | ||
102 | + * | ||
103 | + * It’s not clear whether the 0xaa data of this variant is part of the strings | ||
104 | + * in the tuple, or part of the offset table. It doesn’t really matter. This | ||
105 | + * is a regression test to check that the code to validate the offset table | ||
106 | + * doesn’t unconditionally try to access the first entry in the offset table | ||
107 | + * by subtracting the table size from the end of the GVariant data. | ||
108 | + * | ||
109 | + * In this non-normal case, that would result in an address off the start of | ||
110 | + * the GVariant data, and an out-of-bounds read, because the GVariant is one | ||
111 | + * byte long, but the offset table is calculated as two bytes long (with 1B | ||
112 | + * sized entries) from the tuple’s type. | ||
113 | + */ | ||
114 | + const GVariantType *data_type = G_VARIANT_TYPE ("(sss)"); | ||
115 | + const guint8 data[] = { 0xaa }; | ||
116 | + gsize size = sizeof (data); | ||
117 | + GVariant *variant = NULL; | ||
118 | + GVariant *normal_variant = NULL; | ||
119 | + GVariant *expected = NULL; | ||
120 | + | ||
121 | + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840"); | ||
122 | + | ||
123 | + variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL); | ||
124 | + g_assert_nonnull (variant); | ||
125 | + | ||
126 | + g_assert_false (g_variant_is_normal_form (variant)); | ||
127 | + | ||
128 | + normal_variant = g_variant_get_normal_form (variant); | ||
129 | + g_assert_nonnull (normal_variant); | ||
130 | + | ||
131 | + expected = g_variant_new_parsed ("('', '', '')"); | ||
132 | + g_assert_cmpvariant (expected, variant); | ||
133 | + g_assert_cmpvariant (expected, normal_variant); | ||
134 | + | ||
135 | + g_variant_unref (expected); | ||
136 | + g_variant_unref (normal_variant); | ||
137 | + g_variant_unref (variant); | ||
138 | +} | ||
139 | + | ||
140 | /* Test that an otherwise-valid serialised GVariant is considered non-normal if | ||
141 | * its offset table entries are too wide. | ||
142 | * | ||
143 | @@ -5680,6 +5741,8 @@ main (int argc, char **argv) | ||
144 | test_normal_checking_tuple_offsets3); | ||
145 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets4", | ||
146 | test_normal_checking_tuple_offsets4); | ||
147 | + g_test_add_func ("/gvariant/normal-checking/tuple-offsets5", | ||
148 | + test_normal_checking_tuple_offsets5); | ||
149 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized", | ||
150 | test_normal_checking_tuple_offsets_minimal_sized); | ||
151 | g_test_add_func ("/gvariant/normal-checking/empty-object-path", | ||
152 | -- | ||
153 | 2.24.4 | ||
154 | |||
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 @@ | |||
1 | From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001 | ||
2 | From: William Manley <will@stb-tester.com> | ||
3 | Date: Wed, 9 Aug 2023 10:04:49 +0000 | ||
4 | Subject: [PATCH] gvariant-core: Consolidate construction of | ||
5 | `GVariantSerialised` | ||
6 | |||
7 | So I only need to change it in one place. | ||
8 | |||
9 | This introduces no functional changes. | ||
10 | |||
11 | Helps: #2121 | ||
12 | |||
13 | CVE: CVE-2023-32665 | ||
14 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1] | ||
15 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
16 | --- | ||
17 | glib/gvariant-core.c | 49 ++++++++++++++++++++++---------------------- | ||
18 | 1 file changed, 25 insertions(+), 24 deletions(-) | ||
19 | |||
20 | diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c | ||
21 | index 9397573..aa0e0a0 100644 | ||
22 | --- a/glib/gvariant-core.c | ||
23 | +++ b/glib/gvariant-core.c | ||
24 | @@ -349,6 +349,27 @@ g_variant_ensure_size (GVariant *value) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | +/* < private > | ||
29 | + * g_variant_to_serialised: | ||
30 | + * @value: a #GVariant | ||
31 | + * | ||
32 | + * Gets a GVariantSerialised for a GVariant in state STATE_SERIALISED. | ||
33 | + */ | ||
34 | +inline static GVariantSerialised | ||
35 | +g_variant_to_serialised (GVariant *value) | ||
36 | +{ | ||
37 | + g_assert (value->state & STATE_SERIALISED); | ||
38 | + { | ||
39 | + GVariantSerialised serialised = { | ||
40 | + value->type_info, | ||
41 | + (gpointer) value->contents.serialised.data, | ||
42 | + value->size, | ||
43 | + value->depth, | ||
44 | + }; | ||
45 | + return serialised; | ||
46 | + } | ||
47 | +} | ||
48 | + | ||
49 | /* < private > | ||
50 | * g_variant_serialise: | ||
51 | * @value: a #GVariant | ||
52 | @@ -991,16 +1012,8 @@ g_variant_n_children (GVariant *value) | ||
53 | g_variant_lock (value); | ||
54 | |||
55 | if (value->state & STATE_SERIALISED) | ||
56 | - { | ||
57 | - GVariantSerialised serialised = { | ||
58 | - value->type_info, | ||
59 | - (gpointer) value->contents.serialised.data, | ||
60 | - value->size, | ||
61 | - value->depth, | ||
62 | - }; | ||
63 | - | ||
64 | - n_children = g_variant_serialised_n_children (serialised); | ||
65 | - } | ||
66 | + n_children = g_variant_serialised_n_children ( | ||
67 | + g_variant_to_serialised (value)); | ||
68 | else | ||
69 | n_children = value->contents.tree.n_children; | ||
70 | |||
71 | @@ -1061,12 +1074,7 @@ g_variant_get_child_value (GVariant *value, | ||
72 | } | ||
73 | |||
74 | { | ||
75 | - GVariantSerialised serialised = { | ||
76 | - value->type_info, | ||
77 | - (gpointer) value->contents.serialised.data, | ||
78 | - value->size, | ||
79 | - value->depth, | ||
80 | - }; | ||
81 | + GVariantSerialised serialised = g_variant_to_serialised (value); | ||
82 | GVariantSerialised s_child; | ||
83 | GVariant *child; | ||
84 | |||
85 | @@ -1179,14 +1187,7 @@ g_variant_is_normal_form (GVariant *value) | ||
86 | |||
87 | if (value->state & STATE_SERIALISED) | ||
88 | { | ||
89 | - GVariantSerialised serialised = { | ||
90 | - value->type_info, | ||
91 | - (gpointer) value->contents.serialised.data, | ||
92 | - value->size, | ||
93 | - value->depth | ||
94 | - }; | ||
95 | - | ||
96 | - if (g_variant_serialised_is_normal (serialised)) | ||
97 | + if (g_variant_serialised_is_normal (g_variant_to_serialised (value))) | ||
98 | value->state |= STATE_TRUSTED; | ||
99 | } | ||
100 | else | ||
101 | -- | ||
102 | 2.24.4 | ||
103 | |||
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 @@ | |||
1 | From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001 | ||
2 | From: William Manley <will@stb-tester.com> | ||
3 | Date: Wed, 9 Aug 2023 10:39:34 +0000 | ||
4 | Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with | ||
5 | framing offsets | ||
6 | |||
7 | This introduces no functional changes. | ||
8 | |||
9 | Helps: #2121 | ||
10 | |||
11 | CVE: CVE-2023-32665 | ||
12 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948] | ||
13 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
14 | --- | ||
15 | glib/gvariant-serialiser.c | 108 +++++++++++++++++++------------------ | ||
16 | 1 file changed, 57 insertions(+), 51 deletions(-) | ||
17 | |||
18 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
19 | index 83e9d85..c7c2114 100644 | ||
20 | --- a/glib/gvariant-serialiser.c | ||
21 | +++ b/glib/gvariant-serialiser.c | ||
22 | @@ -633,30 +633,62 @@ gvs_calculate_total_size (gsize body_size, | ||
23 | return body_size + 8 * offsets; | ||
24 | } | ||
25 | |||
26 | +struct Offsets | ||
27 | +{ | ||
28 | + gsize data_size; | ||
29 | + | ||
30 | + guchar *array; | ||
31 | + gsize length; | ||
32 | + guint offset_size; | ||
33 | + | ||
34 | + gboolean is_normal; | ||
35 | +}; | ||
36 | + | ||
37 | static gsize | ||
38 | -gvs_variable_sized_array_n_children (GVariantSerialised value) | ||
39 | +gvs_offsets_get_offset_n (struct Offsets *offsets, | ||
40 | + gsize n) | ||
41 | +{ | ||
42 | + return gvs_read_unaligned_le ( | ||
43 | + offsets->array + (offsets->offset_size * n), offsets->offset_size); | ||
44 | +} | ||
45 | + | ||
46 | +static struct Offsets | ||
47 | +gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value) | ||
48 | { | ||
49 | + struct Offsets out = { 0, }; | ||
50 | gsize offsets_array_size; | ||
51 | - gsize offset_size; | ||
52 | gsize last_end; | ||
53 | |||
54 | if (value.size == 0) | ||
55 | - return 0; | ||
56 | - | ||
57 | - offset_size = gvs_get_offset_size (value.size); | ||
58 | + { | ||
59 | + out.is_normal = TRUE; | ||
60 | + return out; | ||
61 | + } | ||
62 | |||
63 | - last_end = gvs_read_unaligned_le (value.data + value.size - | ||
64 | - offset_size, offset_size); | ||
65 | + out.offset_size = gvs_get_offset_size (value.size); | ||
66 | + last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size, | ||
67 | + out.offset_size); | ||
68 | |||
69 | if (last_end > value.size) | ||
70 | - return 0; | ||
71 | + return out; /* offsets not normal */ | ||
72 | |||
73 | offsets_array_size = value.size - last_end; | ||
74 | |||
75 | - if (offsets_array_size % offset_size) | ||
76 | - return 0; | ||
77 | + if (offsets_array_size % out.offset_size) | ||
78 | + return out; /* offsets not normal */ | ||
79 | + | ||
80 | + out.data_size = last_end; | ||
81 | + out.array = value.data + last_end; | ||
82 | + out.length = offsets_array_size / out.offset_size; | ||
83 | + out.is_normal = TRUE; | ||
84 | |||
85 | - return offsets_array_size / offset_size; | ||
86 | + return out; | ||
87 | +} | ||
88 | + | ||
89 | +static gsize | ||
90 | +gvs_variable_sized_array_n_children (GVariantSerialised value) | ||
91 | +{ | ||
92 | + return gvs_variable_sized_array_get_frame_offsets (value).length; | ||
93 | } | ||
94 | |||
95 | static GVariantSerialised | ||
96 | @@ -664,8 +696,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value, | ||
97 | gsize index_) | ||
98 | { | ||
99 | GVariantSerialised child = { 0, }; | ||
100 | - gsize offset_size; | ||
101 | - gsize last_end; | ||
102 | + | ||
103 | + struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value); | ||
104 | + | ||
105 | gsize start; | ||
106 | gsize end; | ||
107 | |||
108 | @@ -673,18 +706,11 @@ gvs_variable_sized_array_get_child (GVariantSerialised value, | ||
109 | g_variant_type_info_ref (child.type_info); | ||
110 | child.depth = value.depth + 1; | ||
111 | |||
112 | - offset_size = gvs_get_offset_size (value.size); | ||
113 | - | ||
114 | - last_end = gvs_read_unaligned_le (value.data + value.size - | ||
115 | - offset_size, offset_size); | ||
116 | - | ||
117 | if (index_ > 0) | ||
118 | { | ||
119 | guint alignment; | ||
120 | |||
121 | - start = gvs_read_unaligned_le (value.data + last_end + | ||
122 | - (offset_size * (index_ - 1)), | ||
123 | - offset_size); | ||
124 | + start = gvs_offsets_get_offset_n (&offsets, index_ - 1); | ||
125 | |||
126 | g_variant_type_info_query (child.type_info, &alignment, NULL); | ||
127 | start += (-start) & alignment; | ||
128 | @@ -692,11 +718,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value, | ||
129 | else | ||
130 | start = 0; | ||
131 | |||
132 | - end = gvs_read_unaligned_le (value.data + last_end + | ||
133 | - (offset_size * index_), | ||
134 | - offset_size); | ||
135 | + end = gvs_offsets_get_offset_n (&offsets, index_); | ||
136 | |||
137 | - if (start < end && end <= value.size && end <= last_end) | ||
138 | + if (start < end && end <= value.size && end <= offsets.data_size) | ||
139 | { | ||
140 | child.data = value.data + start; | ||
141 | child.size = end - start; | ||
142 | @@ -768,34 +792,16 @@ static gboolean | ||
143 | gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
144 | { | ||
145 | GVariantSerialised child = { 0, }; | ||
146 | - gsize offsets_array_size; | ||
147 | - guchar *offsets_array; | ||
148 | - guint offset_size; | ||
149 | guint alignment; | ||
150 | - gsize last_end; | ||
151 | - gsize length; | ||
152 | gsize offset; | ||
153 | gsize i; | ||
154 | |||
155 | - if (value.size == 0) | ||
156 | - return TRUE; | ||
157 | - | ||
158 | - offset_size = gvs_get_offset_size (value.size); | ||
159 | - last_end = gvs_read_unaligned_le (value.data + value.size - | ||
160 | - offset_size, offset_size); | ||
161 | + struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value); | ||
162 | |||
163 | - if (last_end > value.size) | ||
164 | + if (!offsets.is_normal) | ||
165 | return FALSE; | ||
166 | |||
167 | - offsets_array_size = value.size - last_end; | ||
168 | - | ||
169 | - if (offsets_array_size % offset_size) | ||
170 | - return FALSE; | ||
171 | - | ||
172 | - offsets_array = value.data + value.size - offsets_array_size; | ||
173 | - length = offsets_array_size / offset_size; | ||
174 | - | ||
175 | - if (length == 0) | ||
176 | + if (value.size != 0 && offsets.length == 0) | ||
177 | return FALSE; | ||
178 | |||
179 | child.type_info = g_variant_type_info_element (value.type_info); | ||
180 | @@ -803,14 +809,14 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
181 | child.depth = value.depth + 1; | ||
182 | offset = 0; | ||
183 | |||
184 | - for (i = 0; i < length; i++) | ||
185 | + for (i = 0; i < offsets.length; i++) | ||
186 | { | ||
187 | gsize this_end; | ||
188 | |||
189 | - this_end = gvs_read_unaligned_le (offsets_array + offset_size * i, | ||
190 | - offset_size); | ||
191 | + this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i, | ||
192 | + offsets.offset_size); | ||
193 | |||
194 | - if (this_end < offset || this_end > last_end) | ||
195 | + if (this_end < offset || this_end > offsets.data_size) | ||
196 | return FALSE; | ||
197 | |||
198 | while (offset & alignment) | ||
199 | @@ -832,7 +838,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
200 | offset = this_end; | ||
201 | } | ||
202 | |||
203 | - g_assert (offset == last_end); | ||
204 | + g_assert (offset == offsets.data_size); | ||
205 | |||
206 | return TRUE; | ||
207 | } | ||
208 | -- | ||
209 | 2.24.4 | ||
210 | |||
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 @@ | |||
1 | From ade71fb544391b2e33e1859645726bfee0d5eaaf Mon Sep 17 00:00:00 2001 | ||
2 | From: William Manley <will@stb-tester.com> | ||
3 | Date: Wed, 16 Aug 2023 03:12:21 +0000 | ||
4 | Subject: [PATCH] gvariant: Don't allow child elements to overlap with each | ||
5 | other | ||
6 | |||
7 | If different elements of a variable sized array can overlap with each | ||
8 | other then we can cause a `GVariant` to normalise to a much larger type. | ||
9 | |||
10 | This commit changes the behaviour of `GVariant` with non-normal form data. If | ||
11 | an invalid frame offset is found all subsequent elements are given their | ||
12 | default value. | ||
13 | |||
14 | When 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 | ||
16 | for that type. This guarantees that elements don't overlap with each | ||
17 | other. We remember the offset we've scanned up to so we don't need to | ||
18 | repeat this work on subsequent accesses. We skip these checks for trusted | ||
19 | data. | ||
20 | |||
21 | Unfortunately this makes random access of untrusted data O(n) — at least | ||
22 | on first access. It doesn't affect the algorithmic complexity of accessing | ||
23 | elements in order, such as when using the `GVariantIter` interface. Also: | ||
24 | the cost of validation will be amortised as the `GVariant` instance is | ||
25 | continued to be used. | ||
26 | |||
27 | I've implemented this with 4 different functions, 1 for each element size, | ||
28 | rather than looping calling `gvs_read_unaligned_le` in the hope that the | ||
29 | compiler will find it easy to optimise and should produce fairly tight | ||
30 | code. | ||
31 | |||
32 | Fixes: #2121 | ||
33 | |||
34 | CVE: CVE-2023-32665 | ||
35 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/ade71fb544391b2e33e1859645726bfee0d5eaaf] | ||
36 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
37 | --- | ||
38 | glib/gvariant-core.c | 35 ++++++++++++++++ | ||
39 | glib/gvariant-serialiser.c | 86 ++++++++++++++++++++++++++++++++++++-- | ||
40 | glib/gvariant-serialiser.h | 8 ++++ | ||
41 | glib/tests/gvariant.c | 45 ++++++++++++++++++++ | ||
42 | 4 files changed, 171 insertions(+), 3 deletions(-) | ||
43 | |||
44 | diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c | ||
45 | index aa0e0a0..9b51e15 100644 | ||
46 | --- a/glib/gvariant-core.c | ||
47 | +++ b/glib/gvariant-core.c | ||
48 | @@ -65,6 +65,7 @@ struct _GVariant | ||
49 | { | ||
50 | GBytes *bytes; | ||
51 | gconstpointer data; | ||
52 | + gsize ordered_offsets_up_to; | ||
53 | } serialised; | ||
54 | |||
55 | struct | ||
56 | @@ -162,6 +163,24 @@ struct _GVariant | ||
57 | * if .data pointed to the appropriate number of nul | ||
58 | * bytes. | ||
59 | * | ||
60 | + * .ordered_offsets_up_to: If ordered_offsets_up_to == n this means that all | ||
61 | + * the frame offsets up to and including the frame | ||
62 | + * offset determining the end of element n are in | ||
63 | + * order. This guarantees that the bytes of element | ||
64 | + * n don't overlap with any previous element. | ||
65 | + * | ||
66 | + * For trusted data this is set to G_MAXSIZE and we | ||
67 | + * don't check that the frame offsets are in order. | ||
68 | + * | ||
69 | + * Note: This doesn't imply the offsets are good in | ||
70 | + * any way apart from their ordering. In particular | ||
71 | + * offsets may be out of bounds for this value or | ||
72 | + * may imply that the data overlaps the frame | ||
73 | + * offsets themselves. | ||
74 | + * | ||
75 | + * This field is only relevant for arrays of non | ||
76 | + * fixed width types. | ||
77 | + * | ||
78 | * .tree: Only valid when the instance is in tree form. | ||
79 | * | ||
80 | * Note that accesses from other threads could result in | ||
81 | @@ -365,6 +384,7 @@ g_variant_to_serialised (GVariant *value) | ||
82 | (gpointer) value->contents.serialised.data, | ||
83 | value->size, | ||
84 | value->depth, | ||
85 | + value->contents.serialised.ordered_offsets_up_to, | ||
86 | }; | ||
87 | return serialised; | ||
88 | } | ||
89 | @@ -396,6 +416,7 @@ g_variant_serialise (GVariant *value, | ||
90 | serialised.size = value->size; | ||
91 | serialised.data = data; | ||
92 | serialised.depth = value->depth; | ||
93 | + serialised.ordered_offsets_up_to = 0; | ||
94 | |||
95 | children = (gpointer *) value->contents.tree.children; | ||
96 | n_children = value->contents.tree.n_children; | ||
97 | @@ -439,6 +460,15 @@ g_variant_fill_gvs (GVariantSerialised *serialised, | ||
98 | g_assert (serialised->size == value->size); | ||
99 | serialised->depth = value->depth; | ||
100 | |||
101 | + if (value->state & STATE_SERIALISED) | ||
102 | + { | ||
103 | + serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to; | ||
104 | + } | ||
105 | + else | ||
106 | + { | ||
107 | + serialised->ordered_offsets_up_to = 0; | ||
108 | + } | ||
109 | + | ||
110 | if (serialised->data) | ||
111 | /* g_variant_store() is a public API, so it | ||
112 | * it will reacquire the lock if it needs to. | ||
113 | @@ -481,6 +511,7 @@ g_variant_ensure_serialised (GVariant *value) | ||
114 | bytes = g_bytes_new_take (data, value->size); | ||
115 | value->contents.serialised.data = g_bytes_get_data (bytes, NULL); | ||
116 | value->contents.serialised.bytes = bytes; | ||
117 | + value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE; | ||
118 | value->state |= STATE_SERIALISED; | ||
119 | } | ||
120 | } | ||
121 | @@ -561,6 +592,7 @@ g_variant_new_from_bytes (const GVariantType *type, | ||
122 | serialised.type_info = value->type_info; | ||
123 | serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size); | ||
124 | serialised.depth = 0; | ||
125 | + serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0; | ||
126 | |||
127 | if (!g_variant_serialised_check (serialised)) | ||
128 | { | ||
129 | @@ -610,6 +642,8 @@ g_variant_new_from_bytes (const GVariantType *type, | ||
130 | value->contents.serialised.data = g_bytes_get_data (bytes, &value->size); | ||
131 | } | ||
132 | |||
133 | + value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0; | ||
134 | + | ||
135 | g_clear_pointer (&owned_bytes, g_bytes_unref); | ||
136 | |||
137 | return value; | ||
138 | @@ -1108,6 +1142,7 @@ g_variant_get_child_value (GVariant *value, | ||
139 | child->contents.serialised.bytes = | ||
140 | g_bytes_ref (value->contents.serialised.bytes); | ||
141 | child->contents.serialised.data = s_child.data; | ||
142 | + child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to; | ||
143 | |||
144 | return child; | ||
145 | } | ||
146 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
147 | index c7c2114..fe0b1a4 100644 | ||
148 | --- a/glib/gvariant-serialiser.c | ||
149 | +++ b/glib/gvariant-serialiser.c | ||
150 | @@ -1,6 +1,7 @@ | ||
151 | /* | ||
152 | * Copyright © 2007, 2008 Ryan Lortie | ||
153 | * Copyright © 2010 Codethink Limited | ||
154 | + * Copyright © 2020 William Manley | ||
155 | * | ||
156 | * This library is free software; you can redistribute it and/or | ||
157 | * modify it under the terms of the GNU Lesser General Public | ||
158 | @@ -264,6 +265,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value, | ||
159 | value.type_info = g_variant_type_info_element (value.type_info); | ||
160 | g_variant_type_info_ref (value.type_info); | ||
161 | value.depth++; | ||
162 | + value.ordered_offsets_up_to = 0; | ||
163 | |||
164 | return value; | ||
165 | } | ||
166 | @@ -295,7 +297,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value, | ||
167 | { | ||
168 | if (n_children) | ||
169 | { | ||
170 | - GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1 }; | ||
171 | + GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 }; | ||
172 | |||
173 | gvs_filler (&child, children[0]); | ||
174 | } | ||
175 | @@ -317,6 +319,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value) | ||
176 | /* proper element size: "Just". recurse to the child. */ | ||
177 | value.type_info = g_variant_type_info_element (value.type_info); | ||
178 | value.depth++; | ||
179 | + value.ordered_offsets_up_to = 0; | ||
180 | |||
181 | return g_variant_serialised_is_normal (value); | ||
182 | } | ||
183 | @@ -358,6 +361,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value, | ||
184 | value.data = NULL; | ||
185 | |||
186 | value.depth++; | ||
187 | + value.ordered_offsets_up_to = 0; | ||
188 | |||
189 | return value; | ||
190 | } | ||
191 | @@ -388,7 +392,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value, | ||
192 | { | ||
193 | if (n_children) | ||
194 | { | ||
195 | - GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1 }; | ||
196 | + GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 }; | ||
197 | |||
198 | /* write the data for the child. */ | ||
199 | gvs_filler (&child, children[0]); | ||
200 | @@ -408,6 +412,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value) | ||
201 | value.type_info = g_variant_type_info_element (value.type_info); | ||
202 | value.size--; | ||
203 | value.depth++; | ||
204 | + value.ordered_offsets_up_to = 0; | ||
205 | |||
206 | return g_variant_serialised_is_normal (value); | ||
207 | } | ||
208 | @@ -691,6 +696,32 @@ gvs_variable_sized_array_n_children (GVariantSerialised value) | ||
209 | return gvs_variable_sized_array_get_frame_offsets (value).length; | ||
210 | } | ||
211 | |||
212 | +/* Find the index of the first out-of-order element in @data, assuming that | ||
213 | + * @data is an array of elements of given @type, starting at index @start and | ||
214 | + * containing a further @len-@start elements. */ | ||
215 | +#define DEFINE_FIND_UNORDERED(type) \ | ||
216 | + static gsize \ | ||
217 | + find_unordered_##type (const guint8 *data, gsize start, gsize len) \ | ||
218 | + { \ | ||
219 | + gsize off; \ | ||
220 | + type current, previous; \ | ||
221 | + \ | ||
222 | + memcpy (&previous, data + start * sizeof (current), sizeof (current)); \ | ||
223 | + for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \ | ||
224 | + { \ | ||
225 | + memcpy (¤t, data + off, sizeof (current)); \ | ||
226 | + if (current < previous) \ | ||
227 | + break; \ | ||
228 | + previous = current; \ | ||
229 | + } \ | ||
230 | + return off / sizeof (current) - 1; \ | ||
231 | + } | ||
232 | + | ||
233 | +DEFINE_FIND_UNORDERED (guint8); | ||
234 | +DEFINE_FIND_UNORDERED (guint16); | ||
235 | +DEFINE_FIND_UNORDERED (guint32); | ||
236 | +DEFINE_FIND_UNORDERED (guint64); | ||
237 | + | ||
238 | static GVariantSerialised | ||
239 | gvs_variable_sized_array_get_child (GVariantSerialised value, | ||
240 | gsize index_) | ||
241 | @@ -706,6 +737,49 @@ gvs_variable_sized_array_get_child (GVariantSerialised value, | ||
242 | g_variant_type_info_ref (child.type_info); | ||
243 | child.depth = value.depth + 1; | ||
244 | |||
245 | + /* If the requested @index_ is beyond the set of indices whose framing offsets | ||
246 | + * have been checked, check the remaining offsets to see whether they’re | ||
247 | + * normal (in order, no overlapping array elements). */ | ||
248 | + if (index_ > value.ordered_offsets_up_to) | ||
249 | + { | ||
250 | + switch (offsets.offset_size) | ||
251 | + { | ||
252 | + case 1: | ||
253 | + { | ||
254 | + value.ordered_offsets_up_to = find_unordered_guint8 ( | ||
255 | + offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
256 | + break; | ||
257 | + } | ||
258 | + case 2: | ||
259 | + { | ||
260 | + value.ordered_offsets_up_to = find_unordered_guint16 ( | ||
261 | + offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
262 | + break; | ||
263 | + } | ||
264 | + case 4: | ||
265 | + { | ||
266 | + value.ordered_offsets_up_to = find_unordered_guint32 ( | ||
267 | + offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
268 | + break; | ||
269 | + } | ||
270 | + case 8: | ||
271 | + { | ||
272 | + value.ordered_offsets_up_to = find_unordered_guint64 ( | ||
273 | + offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
274 | + break; | ||
275 | + } | ||
276 | + default: | ||
277 | + /* gvs_get_offset_size() only returns maximum 8 */ | ||
278 | + g_assert_not_reached (); | ||
279 | + } | ||
280 | + } | ||
281 | + | ||
282 | + if (index_ > value.ordered_offsets_up_to) | ||
283 | + { | ||
284 | + /* Offsets are invalid somewhere, so return an empty child. */ | ||
285 | + return child; | ||
286 | + } | ||
287 | + | ||
288 | if (index_ > 0) | ||
289 | { | ||
290 | guint alignment; | ||
291 | @@ -840,6 +914,9 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
292 | |||
293 | g_assert (offset == offsets.data_size); | ||
294 | |||
295 | + /* All offsets have now been checked. */ | ||
296 | + value.ordered_offsets_up_to = G_MAXSIZE; | ||
297 | + | ||
298 | return TRUE; | ||
299 | } | ||
300 | |||
301 | @@ -1072,7 +1149,7 @@ gvs_tuple_is_normal (GVariantSerialised value) | ||
302 | for (i = 0; i < length; i++) | ||
303 | { | ||
304 | const GVariantMemberInfo *member_info; | ||
305 | - GVariantSerialised child; | ||
306 | + GVariantSerialised child = { 0, }; | ||
307 | gsize fixed_size; | ||
308 | guint alignment; | ||
309 | gsize end; | ||
310 | @@ -1132,6 +1209,9 @@ gvs_tuple_is_normal (GVariantSerialised value) | ||
311 | offset = end; | ||
312 | } | ||
313 | |||
314 | + /* All element bounds have been checked above. */ | ||
315 | + value.ordered_offsets_up_to = G_MAXSIZE; | ||
316 | + | ||
317 | { | ||
318 | gsize fixed_size; | ||
319 | guint alignment; | ||
320 | diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h | ||
321 | index 81343e9..99d18ef 100644 | ||
322 | --- a/glib/gvariant-serialiser.h | ||
323 | +++ b/glib/gvariant-serialiser.h | ||
324 | @@ -29,6 +29,14 @@ typedef struct | ||
325 | guchar *data; | ||
326 | gsize size; | ||
327 | gsize depth; /* same semantics as GVariant.depth */ | ||
328 | + /* If ordered_offsets_up_to == n this means that all the frame offsets up to and | ||
329 | + * including the frame offset determining the end of element n are in order. | ||
330 | + * This guarantees that the bytes of element n don't overlap with any previous | ||
331 | + * element. | ||
332 | + * | ||
333 | + * This is both read and set by g_variant_serialised_get_child for arrays of | ||
334 | + * non-fixed-width types */ | ||
335 | + gsize ordered_offsets_up_to; | ||
336 | } GVariantSerialised; | ||
337 | |||
338 | /* deserialisation */ | ||
339 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
340 | index 0e5ec8e..967e9a1 100644 | ||
341 | --- a/glib/tests/gvariant.c | ||
342 | +++ b/glib/tests/gvariant.c | ||
343 | @@ -1,5 +1,6 @@ | ||
344 | /* | ||
345 | * Copyright © 2010 Codethink Limited | ||
346 | + * Copyright © 2020 William Manley | ||
347 | * | ||
348 | * This library is free software; you can redistribute it and/or | ||
349 | * modify it under the terms of the GNU Lesser General Public | ||
350 | @@ -1283,6 +1284,7 @@ random_instance_filler (GVariantSerialised *serialised, | ||
351 | serialised->size = instance->size; | ||
352 | |||
353 | serialised->depth = 0; | ||
354 | + serialised->ordered_offsets_up_to = 0; | ||
355 | |||
356 | g_assert_true (serialised->type_info == instance->type_info); | ||
357 | g_assert_cmpuint (serialised->size, ==, instance->size); | ||
358 | @@ -5039,6 +5041,47 @@ test_normal_checking_array_offsets (void) | ||
359 | g_variant_unref (variant); | ||
360 | } | ||
361 | |||
362 | +/* This is a regression test that we can't have non-normal values that take up | ||
363 | + * significantly more space than the normal equivalent, by specifying the | ||
364 | + * offset table entries so that array elements overlap. | ||
365 | + * | ||
366 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */ | ||
367 | +static void | ||
368 | +test_normal_checking_array_offsets2 (void) | ||
369 | +{ | ||
370 | + const guint8 data[] = { | ||
371 | + 'h', 'i', '\0', | ||
372 | + 0x03, 0x00, 0x03, | ||
373 | + 0x06, 0x00, 0x06, | ||
374 | + 0x09, 0x00, 0x09, | ||
375 | + 0x0c, 0x00, 0x0c, | ||
376 | + 0x0f, 0x00, 0x0f, | ||
377 | + 0x12, 0x00, 0x12, | ||
378 | + 0x15, 0x00, 0x15, | ||
379 | + }; | ||
380 | + gsize size = sizeof (data); | ||
381 | + const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas"); | ||
382 | + GVariant *variant = NULL; | ||
383 | + GVariant *normal_variant = NULL; | ||
384 | + GVariant *expected = NULL; | ||
385 | + | ||
386 | + variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL); | ||
387 | + g_assert_nonnull (variant); | ||
388 | + | ||
389 | + normal_variant = g_variant_get_normal_form (variant); | ||
390 | + g_assert_nonnull (normal_variant); | ||
391 | + g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2); | ||
392 | + | ||
393 | + expected = g_variant_new_parsed ( | ||
394 | + "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]"); | ||
395 | + g_assert_cmpvariant (expected, variant); | ||
396 | + g_assert_cmpvariant (expected, normal_variant); | ||
397 | + | ||
398 | + g_variant_unref (expected); | ||
399 | + g_variant_unref (normal_variant); | ||
400 | + g_variant_unref (variant); | ||
401 | +} | ||
402 | + | ||
403 | /* Test that a tuple with invalidly large values in its offset table is | ||
404 | * normalised successfully without looping infinitely. */ | ||
405 | static void | ||
406 | @@ -5206,6 +5249,8 @@ main (int argc, char **argv) | ||
407 | test_normal_checking_tuples); | ||
408 | g_test_add_func ("/gvariant/normal-checking/array-offsets", | ||
409 | test_normal_checking_array_offsets); | ||
410 | + g_test_add_func ("/gvariant/normal-checking/array-offsets2", | ||
411 | + test_normal_checking_array_offsets2); | ||
412 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets", | ||
413 | test_normal_checking_tuple_offsets); | ||
414 | g_test_add_func ("/gvariant/normal-checking/empty-object-path", | ||
415 | -- | ||
416 | 2.24.4 | ||
417 | |||
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 @@ | |||
1 | From 345cae9c1aa7bf6752039225ef4c8d8d69fa8d76 Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Fri, 11 Aug 2023 04:09:12 +0000 | ||
4 | Subject: [PATCH] gvariant-serialiser: Factor out code to get bounds of a tuple | ||
5 | member | ||
6 | |||
7 | This introduces no functional changes. | ||
8 | |||
9 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
10 | |||
11 | Helps: #2121 | ||
12 | |||
13 | CVE: CVE-2023-32665 | ||
14 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/345cae9c1aa7bf6752039225ef4c8d8d69fa8d76] | ||
15 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
16 | --- | ||
17 | glib/gvariant-serialiser.c | 73 ++++++++++++++++++++++++-------------- | ||
18 | 1 file changed, 46 insertions(+), 27 deletions(-) | ||
19 | |||
20 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
21 | index fe0b1a4..6f9b366 100644 | ||
22 | --- a/glib/gvariant-serialiser.c | ||
23 | +++ b/glib/gvariant-serialiser.c | ||
24 | @@ -942,6 +942,51 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
25 | * for the tuple. See the notes in gvarianttypeinfo.h. | ||
26 | */ | ||
27 | |||
28 | +static void | ||
29 | +gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
30 | + gsize index_, | ||
31 | + gsize offset_size, | ||
32 | + gsize *out_member_start, | ||
33 | + gsize *out_member_end) | ||
34 | +{ | ||
35 | + const GVariantMemberInfo *member_info; | ||
36 | + gsize member_start, member_end; | ||
37 | + | ||
38 | + member_info = g_variant_type_info_member_info (value.type_info, index_); | ||
39 | + | ||
40 | + if (member_info->i + 1) | ||
41 | + member_start = gvs_read_unaligned_le (value.data + value.size - | ||
42 | + offset_size * (member_info->i + 1), | ||
43 | + offset_size); | ||
44 | + else | ||
45 | + member_start = 0; | ||
46 | + | ||
47 | + member_start += member_info->a; | ||
48 | + member_start &= member_info->b; | ||
49 | + member_start |= member_info->c; | ||
50 | + | ||
51 | + if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST) | ||
52 | + member_end = value.size - offset_size * (member_info->i + 1); | ||
53 | + | ||
54 | + else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED) | ||
55 | + { | ||
56 | + gsize fixed_size; | ||
57 | + | ||
58 | + g_variant_type_info_query (member_info->type_info, NULL, &fixed_size); | ||
59 | + member_end = member_start + fixed_size; | ||
60 | + } | ||
61 | + | ||
62 | + else /* G_VARIANT_MEMBER_ENDING_OFFSET */ | ||
63 | + member_end = gvs_read_unaligned_le (value.data + value.size - | ||
64 | + offset_size * (member_info->i + 2), | ||
65 | + offset_size); | ||
66 | + | ||
67 | + if (out_member_start != NULL) | ||
68 | + *out_member_start = member_start; | ||
69 | + if (out_member_end != NULL) | ||
70 | + *out_member_end = member_end; | ||
71 | +} | ||
72 | + | ||
73 | static gsize | ||
74 | gvs_tuple_n_children (GVariantSerialised value) | ||
75 | { | ||
76 | @@ -997,33 +1042,7 @@ gvs_tuple_get_child (GVariantSerialised value, | ||
77 | } | ||
78 | } | ||
79 | |||
80 | - if (member_info->i + 1) | ||
81 | - start = gvs_read_unaligned_le (value.data + value.size - | ||
82 | - offset_size * (member_info->i + 1), | ||
83 | - offset_size); | ||
84 | - else | ||
85 | - start = 0; | ||
86 | - | ||
87 | - start += member_info->a; | ||
88 | - start &= member_info->b; | ||
89 | - start |= member_info->c; | ||
90 | - | ||
91 | - if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST) | ||
92 | - end = value.size - offset_size * (member_info->i + 1); | ||
93 | - | ||
94 | - else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED) | ||
95 | - { | ||
96 | - gsize fixed_size; | ||
97 | - | ||
98 | - g_variant_type_info_query (child.type_info, NULL, &fixed_size); | ||
99 | - end = start + fixed_size; | ||
100 | - child.size = fixed_size; | ||
101 | - } | ||
102 | - | ||
103 | - else /* G_VARIANT_MEMBER_ENDING_OFFSET */ | ||
104 | - end = gvs_read_unaligned_le (value.data + value.size - | ||
105 | - offset_size * (member_info->i + 2), | ||
106 | - offset_size); | ||
107 | + gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end); | ||
108 | |||
109 | /* The child should not extend into the offset table. */ | ||
110 | if (index_ != g_variant_type_info_n_members (value.type_info) - 1) | ||
111 | -- | ||
112 | 2.24.4 | ||
113 | |||
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 @@ | |||
1 | From 73d0aa81c2575a5c9ae77dcb94da919579014fc0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Fri, 11 Aug 2023 04:13:02 +0000 | ||
4 | Subject: [PATCH] gvariant-serialiser: Rework child size calculation | ||
5 | |||
6 | This reduces a few duplicate calls to `g_variant_type_info_query()` and | ||
7 | explains why they’re needed. | ||
8 | |||
9 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
10 | |||
11 | Helps: #2121 | ||
12 | |||
13 | CVE: CVE-2023-32665 | ||
14 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/73d0aa81c2575a5c9ae77dcb94da919579014fc0] | ||
15 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
16 | --- | ||
17 | glib/gvariant-serialiser.c | 31 +++++++++---------------------- | ||
18 | 1 file changed, 9 insertions(+), 22 deletions(-) | ||
19 | |||
20 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
21 | index 6f9b366..fb75923 100644 | ||
22 | --- a/glib/gvariant-serialiser.c | ||
23 | +++ b/glib/gvariant-serialiser.c | ||
24 | @@ -1007,14 +1007,18 @@ gvs_tuple_get_child (GVariantSerialised value, | ||
25 | child.depth = value.depth + 1; | ||
26 | offset_size = gvs_get_offset_size (value.size); | ||
27 | |||
28 | + /* Ensure the size is set for fixed-sized children, or | ||
29 | + * g_variant_serialised_check() will fail, even if we return | ||
30 | + * (child.data == NULL) to indicate an error. */ | ||
31 | + if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED) | ||
32 | + g_variant_type_info_query (child.type_info, NULL, &child.size); | ||
33 | + | ||
34 | /* tuples are the only (potentially) fixed-sized containers, so the | ||
35 | * only ones that have to deal with the possibility of having %NULL | ||
36 | * data with a non-zero %size if errors occurred elsewhere. | ||
37 | */ | ||
38 | if G_UNLIKELY (value.data == NULL && value.size != 0) | ||
39 | { | ||
40 | - g_variant_type_info_query (child.type_info, NULL, &child.size); | ||
41 | - | ||
42 | /* this can only happen in fixed-sized tuples, | ||
43 | * so the child must also be fixed sized. | ||
44 | */ | ||
45 | @@ -1032,29 +1036,12 @@ gvs_tuple_get_child (GVariantSerialised value, | ||
46 | else | ||
47 | { | ||
48 | if (offset_size * (member_info->i + 1) > value.size) | ||
49 | - { | ||
50 | - /* if the child is fixed size, return its size. | ||
51 | - * if child is not fixed-sized, return size = 0. | ||
52 | - */ | ||
53 | - g_variant_type_info_query (child.type_info, NULL, &child.size); | ||
54 | - | ||
55 | - return child; | ||
56 | - } | ||
57 | + return child; | ||
58 | } | ||
59 | |||
60 | - gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end); | ||
61 | - | ||
62 | /* The child should not extend into the offset table. */ | ||
63 | - if (index_ != g_variant_type_info_n_members (value.type_info) - 1) | ||
64 | - { | ||
65 | - GVariantSerialised last_child; | ||
66 | - last_child = gvs_tuple_get_child (value, | ||
67 | - g_variant_type_info_n_members (value.type_info) - 1); | ||
68 | - last_end = last_child.data + last_child.size - value.data; | ||
69 | - g_variant_type_info_unref (last_child.type_info); | ||
70 | - } | ||
71 | - else | ||
72 | - last_end = end; | ||
73 | + gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end); | ||
74 | + gvs_tuple_get_member_bounds (value, g_variant_type_info_n_members (value.type_info) - 1, offset_size, NULL, &last_end); | ||
75 | |||
76 | if (start < end && end <= value.size && end <= last_end) | ||
77 | { | ||
78 | -- | ||
79 | 2.24.4 | ||
80 | |||
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 @@ | |||
1 | From 7cf6f5b69146d20948d42f0c476688fe17fef787 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 16 Aug 2023 12:09:06 +0000 | ||
4 | Subject: [PATCH] gvariant: Don't allow child elements of a tuple to overlap | ||
5 | each other | ||
6 | |||
7 | This is similar to the earlier commit which prevents child elements of a | ||
8 | variable-sized array from overlapping each other, but this time for | ||
9 | tuples. It is based heavily on ideas by William Manley. | ||
10 | |||
11 | Tuples are slightly different from variable-sized arrays in that they | ||
12 | contain a mixture of fixed and variable sized elements. All but one of | ||
13 | the variable sized elements have an entry in the frame offsets table. | ||
14 | This means that if we were to just check the ordering of the frame | ||
15 | offsets table, the variable sized elements could still overlap | ||
16 | interleaving fixed sized elements, which would be bad. | ||
17 | |||
18 | Therefore we have to check the elements rather than the frame offsets. | ||
19 | |||
20 | The logic of checking the elements up to the index currently being | ||
21 | requested, and caching the result in `ordered_offsets_up_to`, means that | ||
22 | the algorithmic cost implications are the same for this commit as for | ||
23 | variable-sized arrays: an O(N) cost for these checks is amortised out | ||
24 | over N accesses to O(1) per access. | ||
25 | |||
26 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
27 | |||
28 | Fixes: #2121 | ||
29 | |||
30 | CVE: CVE-2023-32665 | ||
31 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/7cf6f5b69146d20948d42f0c476688fe17fef787] | ||
32 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
33 | --- | ||
34 | glib/gvariant-core.c | 6 +- | ||
35 | glib/gvariant-serialiser.c | 40 ++++++++ | ||
36 | glib/gvariant-serialiser.h | 7 +- | ||
37 | glib/gvariant.c | 1 + | ||
38 | glib/tests/gvariant.c | 181 +++++++++++++++++++++++++++++++++++++ | ||
39 | 5 files changed, 232 insertions(+), 3 deletions(-) | ||
40 | |||
41 | diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c | ||
42 | index 9b51e15..b951cd9 100644 | ||
43 | --- a/glib/gvariant-core.c | ||
44 | +++ b/glib/gvariant-core.c | ||
45 | @@ -1,6 +1,7 @@ | ||
46 | /* | ||
47 | * Copyright © 2007, 2008 Ryan Lortie | ||
48 | * Copyright © 2010 Codethink Limited | ||
49 | + * Copyright © 2022 Endless OS Foundation, LLC | ||
50 | * | ||
51 | * This library is free software; you can redistribute it and/or | ||
52 | * modify it under the terms of the GNU Lesser General Public | ||
53 | @@ -179,7 +180,7 @@ struct _GVariant | ||
54 | * offsets themselves. | ||
55 | * | ||
56 | * This field is only relevant for arrays of non | ||
57 | - * fixed width types. | ||
58 | + * fixed width types and for tuples. | ||
59 | * | ||
60 | * .tree: Only valid when the instance is in tree form. | ||
61 | * | ||
62 | @@ -1117,6 +1118,9 @@ g_variant_get_child_value (GVariant *value, | ||
63 | */ | ||
64 | s_child = g_variant_serialised_get_child (serialised, index_); | ||
65 | |||
66 | + /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */ | ||
67 | + value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to); | ||
68 | + | ||
69 | /* Check whether this would cause nesting too deep. If so, return a fake | ||
70 | * child. The only situation we expect this to happen in is with a variant, | ||
71 | * as all other deeply-nested types have a static type, and hence should | ||
72 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
73 | index fb75923..cd4a3e6 100644 | ||
74 | --- a/glib/gvariant-serialiser.c | ||
75 | +++ b/glib/gvariant-serialiser.c | ||
76 | @@ -942,6 +942,10 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
77 | * for the tuple. See the notes in gvarianttypeinfo.h. | ||
78 | */ | ||
79 | |||
80 | +/* Note: This doesn’t guarantee that @out_member_end >= @out_member_start; that | ||
81 | + * condition may not hold true for invalid serialised variants. The caller is | ||
82 | + * responsible for checking the returned values and handling invalid ones | ||
83 | + * appropriately. */ | ||
84 | static void | ||
85 | gvs_tuple_get_member_bounds (GVariantSerialised value, | ||
86 | gsize index_, | ||
87 | @@ -1028,6 +1032,42 @@ gvs_tuple_get_child (GVariantSerialised value, | ||
88 | return child; | ||
89 | } | ||
90 | |||
91 | + /* If the requested @index_ is beyond the set of indices whose framing offsets | ||
92 | + * have been checked, check the remaining offsets to see whether they’re | ||
93 | + * normal (in order, no overlapping tuple elements). | ||
94 | + * | ||
95 | + * Unlike the checks in gvs_variable_sized_array_get_child(), we have to check | ||
96 | + * all the tuple *elements* here, not just all the framing offsets, since | ||
97 | + * tuples contain a mix of elements which use framing offsets and ones which | ||
98 | + * don’t. None of them are allowed to overlap. */ | ||
99 | + if (index_ > value.ordered_offsets_up_to) | ||
100 | + { | ||
101 | + gsize i, prev_i_end = 0; | ||
102 | + | ||
103 | + if (value.ordered_offsets_up_to > 0) | ||
104 | + gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end); | ||
105 | + | ||
106 | + for (i = value.ordered_offsets_up_to; i <= index_; i++) | ||
107 | + { | ||
108 | + gsize i_start, i_end; | ||
109 | + | ||
110 | + gvs_tuple_get_member_bounds (value, i, offset_size, &i_start, &i_end); | ||
111 | + | ||
112 | + if (i_start > i_end || i_start < prev_i_end || i_end > value.size) | ||
113 | + break; | ||
114 | + | ||
115 | + prev_i_end = i_end; | ||
116 | + } | ||
117 | + | ||
118 | + value.ordered_offsets_up_to = i - 1; | ||
119 | + } | ||
120 | + | ||
121 | + if (index_ > value.ordered_offsets_up_to) | ||
122 | + { | ||
123 | + /* Offsets are invalid somewhere, so return an empty child. */ | ||
124 | + return child; | ||
125 | + } | ||
126 | + | ||
127 | if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET) | ||
128 | { | ||
129 | if (offset_size * (member_info->i + 2) > value.size) | ||
130 | diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h | ||
131 | index 99d18ef..144aec8 100644 | ||
132 | --- a/glib/gvariant-serialiser.h | ||
133 | +++ b/glib/gvariant-serialiser.h | ||
134 | @@ -34,8 +34,11 @@ typedef struct | ||
135 | * This guarantees that the bytes of element n don't overlap with any previous | ||
136 | * element. | ||
137 | * | ||
138 | - * This is both read and set by g_variant_serialised_get_child for arrays of | ||
139 | - * non-fixed-width types */ | ||
140 | + * This is both read and set by g_variant_serialised_get_child() for arrays of | ||
141 | + * non-fixed-width types, and for tuples. | ||
142 | + * | ||
143 | + * Even when dealing with tuples, @ordered_offsets_up_to is an element index, | ||
144 | + * rather than an index into the frame offsets. */ | ||
145 | gsize ordered_offsets_up_to; | ||
146 | } GVariantSerialised; | ||
147 | |||
148 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
149 | index d6f68a9..cdb428e 100644 | ||
150 | --- a/glib/gvariant.c | ||
151 | +++ b/glib/gvariant.c | ||
152 | @@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value) | ||
153 | serialised.type_info = g_variant_get_type_info (trusted); | ||
154 | serialised.size = g_variant_get_size (trusted); | ||
155 | serialised.data = g_malloc (serialised.size); | ||
156 | + serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */ | ||
157 | g_variant_store (trusted, serialised.data); | ||
158 | g_variant_unref (trusted); | ||
159 | |||
160 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
161 | index 967e9a1..a84b02e 100644 | ||
162 | --- a/glib/tests/gvariant.c | ||
163 | +++ b/glib/tests/gvariant.c | ||
164 | @@ -1,6 +1,7 @@ | ||
165 | /* | ||
166 | * Copyright © 2010 Codethink Limited | ||
167 | * Copyright © 2020 William Manley | ||
168 | + * Copyright © 2022 Endless OS Foundation, LLC | ||
169 | * | ||
170 | * This library is free software; you can redistribute it and/or | ||
171 | * modify it under the terms of the GNU Lesser General Public | ||
172 | @@ -1451,6 +1452,7 @@ test_maybe (void) | ||
173 | serialised.data = flavoured_malloc (needed_size, flavour); | ||
174 | serialised.size = needed_size; | ||
175 | serialised.depth = 0; | ||
176 | + serialised.ordered_offsets_up_to = 0; | ||
177 | |||
178 | g_variant_serialiser_serialise (serialised, | ||
179 | random_instance_filler, | ||
180 | @@ -1574,6 +1576,7 @@ test_array (void) | ||
181 | serialised.data = flavoured_malloc (needed_size, flavour); | ||
182 | serialised.size = needed_size; | ||
183 | serialised.depth = 0; | ||
184 | + serialised.ordered_offsets_up_to = 0; | ||
185 | |||
186 | g_variant_serialiser_serialise (serialised, random_instance_filler, | ||
187 | (gpointer *) instances, n_children); | ||
188 | @@ -1738,6 +1741,7 @@ test_tuple (void) | ||
189 | serialised.data = flavoured_malloc (needed_size, flavour); | ||
190 | serialised.size = needed_size; | ||
191 | serialised.depth = 0; | ||
192 | + serialised.ordered_offsets_up_to = 0; | ||
193 | |||
194 | g_variant_serialiser_serialise (serialised, random_instance_filler, | ||
195 | (gpointer *) instances, n_children); | ||
196 | @@ -1834,6 +1838,7 @@ test_variant (void) | ||
197 | serialised.data = flavoured_malloc (needed_size, flavour); | ||
198 | serialised.size = needed_size; | ||
199 | serialised.depth = 0; | ||
200 | + serialised.ordered_offsets_up_to = 0; | ||
201 | |||
202 | g_variant_serialiser_serialise (serialised, random_instance_filler, | ||
203 | (gpointer *) &instance, 1); | ||
204 | @@ -5106,6 +5111,176 @@ test_normal_checking_tuple_offsets (void) | ||
205 | g_variant_unref (variant); | ||
206 | } | ||
207 | |||
208 | +/* This is a regression test that we can't have non-normal values that take up | ||
209 | + * significantly more space than the normal equivalent, by specifying the | ||
210 | + * offset table entries so that tuple elements overlap. | ||
211 | + * | ||
212 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and | ||
213 | + * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */ | ||
214 | +static void | ||
215 | +test_normal_checking_tuple_offsets2 (void) | ||
216 | +{ | ||
217 | + const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)"); | ||
218 | + const guint8 data[] = { | ||
219 | + 0x12, 0x34, 0x56, 0x78, 0x01, | ||
220 | + /* | ||
221 | + ^───────────────────┘ | ||
222 | + | ||
223 | + ^^^^^^^^^^ 1st yy | ||
224 | + ^^^^^^^^^^ 2nd yy | ||
225 | + ^^^^^^^^^^ 3rd yy | ||
226 | + ^^^^ Framing offsets | ||
227 | + */ | ||
228 | + | ||
229 | + /* If this variant was encoded normally, it would be something like this: | ||
230 | + * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX | ||
231 | + * ^─────────────────────────────────────────────────────┘ | ||
232 | + * | ||
233 | + * ^^^^^^^^^^ 1st yy | ||
234 | + * ^^^^^^^^^^ 2nd yy | ||
235 | + * ^^^^^^^^^^ 3rd yy | ||
236 | + * ^^^^ Framing offsets | ||
237 | + */ | ||
238 | + }; | ||
239 | + gsize size = sizeof (data); | ||
240 | + GVariant *variant = NULL; | ||
241 | + GVariant *normal_variant = NULL; | ||
242 | + GVariant *expected = NULL; | ||
243 | + | ||
244 | + variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL); | ||
245 | + g_assert_nonnull (variant); | ||
246 | + | ||
247 | + normal_variant = g_variant_get_normal_form (variant); | ||
248 | + g_assert_nonnull (normal_variant); | ||
249 | + g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3); | ||
250 | + | ||
251 | + expected = g_variant_new_parsed ( | ||
252 | + "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)"); | ||
253 | + g_assert_cmpvariant (expected, variant); | ||
254 | + g_assert_cmpvariant (expected, normal_variant); | ||
255 | + | ||
256 | + g_variant_unref (expected); | ||
257 | + g_variant_unref (normal_variant); | ||
258 | + g_variant_unref (variant); | ||
259 | +} | ||
260 | + | ||
261 | +/* This is a regression test that overlapping entries in the offset table are | ||
262 | + * decoded consistently, even though they’re non-normal. | ||
263 | + * | ||
264 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */ | ||
265 | +static void | ||
266 | +test_normal_checking_tuple_offsets3 (void) | ||
267 | +{ | ||
268 | + /* The expected decoding of this non-normal byte stream is complex. See | ||
269 | + * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant | ||
270 | + * specification. | ||
271 | + * | ||
272 | + * The rule “Child Values Overlapping Framing Offsets” from the specification | ||
273 | + * says that the first `ay` must be decoded as `[0x01]` even though it | ||
274 | + * overlaps the first byte of the offset table. However, since commit | ||
275 | + * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow | ||
276 | + * this as it’s exploitable. So the first `ay` must be given a default value. | ||
277 | + * | ||
278 | + * The second and third `ay`s must be given default values because of rule | ||
279 | + * “End Boundary Precedes Start Boundary”. | ||
280 | + * | ||
281 | + * The `i` must be given a default value because of rule “Start or End | ||
282 | + * Boundary of a Child Falls Outside the Container”. | ||
283 | + */ | ||
284 | + const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)"); | ||
285 | + const guint8 data[] = { | ||
286 | + 0x01, 0x00, 0x02, | ||
287 | + /* | ||
288 | + ^──┘ | ||
289 | + | ||
290 | + ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above) | ||
291 | + 2nd ay, bytes 2-0 | ||
292 | + i, bytes 0-4 | ||
293 | + 3rd ay, bytes 4-1 | ||
294 | + ^^^^^^^^^^ Framing offsets | ||
295 | + */ | ||
296 | + }; | ||
297 | + gsize size = sizeof (data); | ||
298 | + GVariant *variant = NULL; | ||
299 | + GVariant *normal_variant = NULL; | ||
300 | + GVariant *expected = NULL; | ||
301 | + | ||
302 | + variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL); | ||
303 | + g_assert_nonnull (variant); | ||
304 | + | ||
305 | + g_assert_false (g_variant_is_normal_form (variant)); | ||
306 | + | ||
307 | + normal_variant = g_variant_get_normal_form (variant); | ||
308 | + g_assert_nonnull (normal_variant); | ||
309 | + g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3); | ||
310 | + | ||
311 | + expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])"); | ||
312 | + g_assert_cmpvariant (expected, variant); | ||
313 | + g_assert_cmpvariant (expected, normal_variant); | ||
314 | + | ||
315 | + g_variant_unref (expected); | ||
316 | + g_variant_unref (normal_variant); | ||
317 | + g_variant_unref (variant); | ||
318 | +} | ||
319 | + | ||
320 | +/* This is a regression test that overlapping entries in the offset table are | ||
321 | + * decoded consistently, even though they’re non-normal. | ||
322 | + * | ||
323 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */ | ||
324 | +static void | ||
325 | +test_normal_checking_tuple_offsets4 (void) | ||
326 | +{ | ||
327 | + /* The expected decoding of this non-normal byte stream is complex. See | ||
328 | + * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant | ||
329 | + * specification. | ||
330 | + * | ||
331 | + * The rule “Child Values Overlapping Framing Offsets” from the specification | ||
332 | + * says that the first `ay` must be decoded as `[0x01]` even though it | ||
333 | + * overlaps the first byte of the offset table. However, since commit | ||
334 | + * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow | ||
335 | + * this as it’s exploitable. So the first `ay` must be given a default value. | ||
336 | + * | ||
337 | + * The second `ay` must be given a default value because of rule “End Boundary | ||
338 | + * Precedes Start Boundary”. | ||
339 | + * | ||
340 | + * The third `ay` must be given a default value because its framing offsets | ||
341 | + * overlap that of the first `ay`. | ||
342 | + */ | ||
343 | + const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)"); | ||
344 | + const guint8 data[] = { | ||
345 | + 0x01, 0x00, 0x02, | ||
346 | + /* | ||
347 | + ^──┘ | ||
348 | + | ||
349 | + ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above) | ||
350 | + 2nd ay, bytes 2-0 | ||
351 | + 3rd ay, bytes 0-1 | ||
352 | + ^^^^^^^^^^ Framing offsets | ||
353 | + */ | ||
354 | + }; | ||
355 | + gsize size = sizeof (data); | ||
356 | + GVariant *variant = NULL; | ||
357 | + GVariant *normal_variant = NULL; | ||
358 | + GVariant *expected = NULL; | ||
359 | + | ||
360 | + variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL); | ||
361 | + g_assert_nonnull (variant); | ||
362 | + | ||
363 | + g_assert_false (g_variant_is_normal_form (variant)); | ||
364 | + | ||
365 | + normal_variant = g_variant_get_normal_form (variant); | ||
366 | + g_assert_nonnull (normal_variant); | ||
367 | + g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3); | ||
368 | + | ||
369 | + expected = g_variant_new_parsed ("@(ayayay) ([], [], [])"); | ||
370 | + g_assert_cmpvariant (expected, variant); | ||
371 | + g_assert_cmpvariant (expected, normal_variant); | ||
372 | + | ||
373 | + g_variant_unref (expected); | ||
374 | + g_variant_unref (normal_variant); | ||
375 | + g_variant_unref (variant); | ||
376 | +} | ||
377 | + | ||
378 | /* Test that an empty object path is normalised successfully to the base object | ||
379 | * path, ‘/’. */ | ||
380 | static void | ||
381 | @@ -5253,6 +5428,12 @@ main (int argc, char **argv) | ||
382 | test_normal_checking_array_offsets2); | ||
383 | g_test_add_func ("/gvariant/normal-checking/tuple-offsets", | ||
384 | test_normal_checking_tuple_offsets); | ||
385 | + g_test_add_func ("/gvariant/normal-checking/tuple-offsets2", | ||
386 | + test_normal_checking_tuple_offsets2); | ||
387 | + g_test_add_func ("/gvariant/normal-checking/tuple-offsets3", | ||
388 | + test_normal_checking_tuple_offsets3); | ||
389 | + g_test_add_func ("/gvariant/normal-checking/tuple-offsets4", | ||
390 | + test_normal_checking_tuple_offsets4); | ||
391 | g_test_add_func ("/gvariant/normal-checking/empty-object-path", | ||
392 | test_normal_checking_empty_object_path); | ||
393 | |||
394 | -- | ||
395 | 2.24.4 | ||
396 | |||
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 @@ | |||
1 | From e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 16 Aug 2023 03:42:47 +0000 | ||
4 | Subject: [PATCH] gvariant: Port g_variant_deep_copy() to count its iterations | ||
5 | directly | ||
6 | |||
7 | This is equivalent to what `GVariantIter` does, but it means that | ||
8 | `g_variant_deep_copy()` is making its own `g_variant_get_child_value()` | ||
9 | calls. | ||
10 | |||
11 | This will be useful in an upcoming commit, where those child values will | ||
12 | be inspected a little more deeply. | ||
13 | |||
14 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
15 | |||
16 | Helps: #2121 | ||
17 | |||
18 | CVE: CVE-2023-32665 | ||
19 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793] | ||
20 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
21 | --- | ||
22 | glib/gvariant.c | 7 +++---- | ||
23 | 1 file changed, 3 insertions(+), 4 deletions(-) | ||
24 | |||
25 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
26 | index cdb428e..fdd36be 100644 | ||
27 | --- a/glib/gvariant.c | ||
28 | +++ b/glib/gvariant.c | ||
29 | @@ -5799,14 +5799,13 @@ g_variant_deep_copy (GVariant *value) | ||
30 | case G_VARIANT_CLASS_VARIANT: | ||
31 | { | ||
32 | GVariantBuilder builder; | ||
33 | - GVariantIter iter; | ||
34 | - GVariant *child; | ||
35 | + gsize i, n_children; | ||
36 | |||
37 | g_variant_builder_init (&builder, g_variant_get_type (value)); | ||
38 | - g_variant_iter_init (&iter, value); | ||
39 | |||
40 | - while ((child = g_variant_iter_next_value (&iter))) | ||
41 | + for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++) | ||
42 | { | ||
43 | + GVariant *child = g_variant_get_child_value (value, i); | ||
44 | g_variant_builder_add_value (&builder, g_variant_deep_copy (child)); | ||
45 | g_variant_unref (child); | ||
46 | } | ||
47 | -- | ||
48 | 2.24.4 | ||
49 | |||
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 @@ | |||
1 | From d1a293c4e29880b8d17bb826c9a426a440ca4a91 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 17 Aug 2023 01:30:38 +0000 | ||
4 | Subject: [PATCH] gvariant: Track checked and ordered offsets independently | ||
5 | |||
6 | The past few commits introduced the concept of known-good offsets in the | ||
7 | offset table (which is used for variable-width arrays and tuples). | ||
8 | Good offsets are ones which are non-overlapping with all the previous | ||
9 | offsets in the table. | ||
10 | |||
11 | If a bad offset is encountered when indexing into the array or tuple, | ||
12 | the cached known-good offset index will not be increased. In this way, | ||
13 | all child variants at and beyond the first bad offset can be returned as | ||
14 | default values rather than dereferencing potentially invalid data. | ||
15 | |||
16 | In this case, there was no information about the fact that the indexes | ||
17 | between the highest known-good index and the requested one had been | ||
18 | checked already. That could lead to a pathological case where an offset | ||
19 | table with an invalid first offset is repeatedly checked in full when | ||
20 | trying to access higher-indexed children. | ||
21 | |||
22 | Avoid that by storing the index of the highest checked offset in the | ||
23 | table, as well as the index of the highest good/ordered offset. | ||
24 | |||
25 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
26 | |||
27 | Helps: #2121 | ||
28 | |||
29 | CVE: CVE-2023-32665 | ||
30 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/d1a293c4e29880b8d17bb826c9a426a440ca4a91] | ||
31 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
32 | --- | ||
33 | glib/gvariant-core.c | 28 ++++++++++++++++++++++++ | ||
34 | glib/gvariant-serialiser.c | 44 +++++++++++++++++++++++++++----------- | ||
35 | glib/gvariant-serialiser.h | 9 ++++++++ | ||
36 | glib/gvariant.c | 1 + | ||
37 | glib/tests/gvariant.c | 5 +++++ | ||
38 | 5 files changed, 75 insertions(+), 12 deletions(-) | ||
39 | |||
40 | diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c | ||
41 | index b951cd9..1b9d5cc 100644 | ||
42 | --- a/glib/gvariant-core.c | ||
43 | +++ b/glib/gvariant-core.c | ||
44 | @@ -67,6 +67,7 @@ struct _GVariant | ||
45 | GBytes *bytes; | ||
46 | gconstpointer data; | ||
47 | gsize ordered_offsets_up_to; | ||
48 | + gsize checked_offsets_up_to; | ||
49 | } serialised; | ||
50 | |||
51 | struct | ||
52 | @@ -182,6 +183,24 @@ struct _GVariant | ||
53 | * This field is only relevant for arrays of non | ||
54 | * fixed width types and for tuples. | ||
55 | * | ||
56 | + * .checked_offsets_up_to: Similarly to .ordered_offsets_up_to, this stores | ||
57 | + * the index of the highest element, n, whose frame | ||
58 | + * offsets (and all the preceding frame offsets) | ||
59 | + * have been checked for validity. | ||
60 | + * | ||
61 | + * It is always the case that | ||
62 | + * .checked_offsets_up_to ≥ .ordered_offsets_up_to. | ||
63 | + * | ||
64 | + * If .checked_offsets_up_to == .ordered_offsets_up_to, | ||
65 | + * then a bad offset has not been found so far. | ||
66 | + * | ||
67 | + * If .checked_offsets_up_to > .ordered_offsets_up_to, | ||
68 | + * then a bad offset has been found at | ||
69 | + * (.ordered_offsets_up_to + 1). | ||
70 | + * | ||
71 | + * This field is only relevant for arrays of non | ||
72 | + * fixed width types and for tuples. | ||
73 | + * | ||
74 | * .tree: Only valid when the instance is in tree form. | ||
75 | * | ||
76 | * Note that accesses from other threads could result in | ||
77 | @@ -386,6 +405,7 @@ g_variant_to_serialised (GVariant *value) | ||
78 | value->size, | ||
79 | value->depth, | ||
80 | value->contents.serialised.ordered_offsets_up_to, | ||
81 | + value->contents.serialised.checked_offsets_up_to, | ||
82 | }; | ||
83 | return serialised; | ||
84 | } | ||
85 | @@ -418,6 +438,7 @@ g_variant_serialise (GVariant *value, | ||
86 | serialised.data = data; | ||
87 | serialised.depth = value->depth; | ||
88 | serialised.ordered_offsets_up_to = 0; | ||
89 | + serialised.checked_offsets_up_to = 0; | ||
90 | |||
91 | children = (gpointer *) value->contents.tree.children; | ||
92 | n_children = value->contents.tree.n_children; | ||
93 | @@ -464,10 +485,12 @@ g_variant_fill_gvs (GVariantSerialised *serialised, | ||
94 | if (value->state & STATE_SERIALISED) | ||
95 | { | ||
96 | serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to; | ||
97 | + serialised->checked_offsets_up_to = value->contents.serialised.checked_offsets_up_to; | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | serialised->ordered_offsets_up_to = 0; | ||
102 | + serialised->checked_offsets_up_to = 0; | ||
103 | } | ||
104 | |||
105 | if (serialised->data) | ||
106 | @@ -513,6 +536,7 @@ g_variant_ensure_serialised (GVariant *value) | ||
107 | value->contents.serialised.data = g_bytes_get_data (bytes, NULL); | ||
108 | value->contents.serialised.bytes = bytes; | ||
109 | value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE; | ||
110 | + value->contents.serialised.checked_offsets_up_to = G_MAXSIZE; | ||
111 | value->state |= STATE_SERIALISED; | ||
112 | } | ||
113 | } | ||
114 | @@ -594,6 +618,7 @@ g_variant_new_from_bytes (const GVariantType *type, | ||
115 | serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size); | ||
116 | serialised.depth = 0; | ||
117 | serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0; | ||
118 | + serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0; | ||
119 | |||
120 | if (!g_variant_serialised_check (serialised)) | ||
121 | { | ||
122 | @@ -644,6 +669,7 @@ g_variant_new_from_bytes (const GVariantType *type, | ||
123 | } | ||
124 | |||
125 | value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0; | ||
126 | + value->contents.serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0; | ||
127 | |||
128 | g_clear_pointer (&owned_bytes, g_bytes_unref); | ||
129 | |||
130 | @@ -1120,6 +1146,7 @@ g_variant_get_child_value (GVariant *value, | ||
131 | |||
132 | /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */ | ||
133 | value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to); | ||
134 | + value->contents.serialised.checked_offsets_up_to = MAX (value->contents.serialised.checked_offsets_up_to, serialised.checked_offsets_up_to); | ||
135 | |||
136 | /* Check whether this would cause nesting too deep. If so, return a fake | ||
137 | * child. The only situation we expect this to happen in is with a variant, | ||
138 | @@ -1147,6 +1174,7 @@ g_variant_get_child_value (GVariant *value, | ||
139 | g_bytes_ref (value->contents.serialised.bytes); | ||
140 | child->contents.serialised.data = s_child.data; | ||
141 | child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to; | ||
142 | + child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to; | ||
143 | |||
144 | return child; | ||
145 | } | ||
146 | diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c | ||
147 | index cd4a3e6..0bf7243 100644 | ||
148 | --- a/glib/gvariant-serialiser.c | ||
149 | +++ b/glib/gvariant-serialiser.c | ||
150 | @@ -120,6 +120,8 @@ | ||
151 | * | ||
152 | * @depth has no restrictions; the depth of a top-level serialised #GVariant is | ||
153 | * zero, and it increases for each level of nested child. | ||
154 | + * | ||
155 | + * @checked_offsets_up_to is always ≥ @ordered_offsets_up_to | ||
156 | */ | ||
157 | |||
158 | /* < private > | ||
159 | @@ -147,6 +149,9 @@ g_variant_serialised_check (GVariantSerialised serialised) | ||
160 | !(serialised.size == 0 || serialised.data != NULL)) | ||
161 | return FALSE; | ||
162 | |||
163 | + if (serialised.ordered_offsets_up_to > serialised.checked_offsets_up_to) | ||
164 | + return FALSE; | ||
165 | + | ||
166 | /* Depending on the native alignment requirements of the machine, the | ||
167 | * compiler will insert either 3 or 7 padding bytes after the char. | ||
168 | * This will result in the sizeof() the struct being 12 or 16. | ||
169 | @@ -266,6 +271,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value, | ||
170 | g_variant_type_info_ref (value.type_info); | ||
171 | value.depth++; | ||
172 | value.ordered_offsets_up_to = 0; | ||
173 | + value.checked_offsets_up_to = 0; | ||
174 | |||
175 | return value; | ||
176 | } | ||
177 | @@ -297,7 +303,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value, | ||
178 | { | ||
179 | if (n_children) | ||
180 | { | ||
181 | - GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 }; | ||
182 | + GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0, 0 }; | ||
183 | |||
184 | gvs_filler (&child, children[0]); | ||
185 | } | ||
186 | @@ -320,6 +326,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value) | ||
187 | value.type_info = g_variant_type_info_element (value.type_info); | ||
188 | value.depth++; | ||
189 | value.ordered_offsets_up_to = 0; | ||
190 | + value.checked_offsets_up_to = 0; | ||
191 | |||
192 | return g_variant_serialised_is_normal (value); | ||
193 | } | ||
194 | @@ -362,6 +369,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value, | ||
195 | |||
196 | value.depth++; | ||
197 | value.ordered_offsets_up_to = 0; | ||
198 | + value.checked_offsets_up_to = 0; | ||
199 | |||
200 | return value; | ||
201 | } | ||
202 | @@ -392,7 +400,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value, | ||
203 | { | ||
204 | if (n_children) | ||
205 | { | ||
206 | - GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 }; | ||
207 | + GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0, 0 }; | ||
208 | |||
209 | /* write the data for the child. */ | ||
210 | gvs_filler (&child, children[0]); | ||
211 | @@ -413,6 +421,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value) | ||
212 | value.size--; | ||
213 | value.depth++; | ||
214 | value.ordered_offsets_up_to = 0; | ||
215 | + value.checked_offsets_up_to = 0; | ||
216 | |||
217 | return g_variant_serialised_is_normal (value); | ||
218 | } | ||
219 | @@ -739,39 +748,46 @@ gvs_variable_sized_array_get_child (GVariantSerialised value, | ||
220 | |||
221 | /* If the requested @index_ is beyond the set of indices whose framing offsets | ||
222 | * have been checked, check the remaining offsets to see whether they’re | ||
223 | - * normal (in order, no overlapping array elements). */ | ||
224 | - if (index_ > value.ordered_offsets_up_to) | ||
225 | + * normal (in order, no overlapping array elements). | ||
226 | + * | ||
227 | + * Don’t bother checking if the highest known-good offset is lower than the | ||
228 | + * highest checked offset, as that means there’s an invalid element at that | ||
229 | + * index, so there’s no need to check further. */ | ||
230 | + if (index_ > value.checked_offsets_up_to && | ||
231 | + value.ordered_offsets_up_to == value.checked_offsets_up_to) | ||
232 | { | ||
233 | switch (offsets.offset_size) | ||
234 | { | ||
235 | case 1: | ||
236 | { | ||
237 | value.ordered_offsets_up_to = find_unordered_guint8 ( | ||
238 | - offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
239 | + offsets.array, value.checked_offsets_up_to, index_ + 1); | ||
240 | break; | ||
241 | } | ||
242 | case 2: | ||
243 | { | ||
244 | value.ordered_offsets_up_to = find_unordered_guint16 ( | ||
245 | - offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
246 | + offsets.array, value.checked_offsets_up_to, index_ + 1); | ||
247 | break; | ||
248 | } | ||
249 | case 4: | ||
250 | { | ||
251 | value.ordered_offsets_up_to = find_unordered_guint32 ( | ||
252 | - offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
253 | + offsets.array, value.checked_offsets_up_to, index_ + 1); | ||
254 | break; | ||
255 | } | ||
256 | case 8: | ||
257 | { | ||
258 | value.ordered_offsets_up_to = find_unordered_guint64 ( | ||
259 | - offsets.array, value.ordered_offsets_up_to, index_ + 1); | ||
260 | + offsets.array, value.checked_offsets_up_to, index_ + 1); | ||
261 | break; | ||
262 | } | ||
263 | default: | ||
264 | /* gvs_get_offset_size() only returns maximum 8 */ | ||
265 | g_assert_not_reached (); | ||
266 | } | ||
267 | + | ||
268 | + value.checked_offsets_up_to = index_; | ||
269 | } | ||
270 | |||
271 | if (index_ > value.ordered_offsets_up_to) | ||
272 | @@ -916,6 +932,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value) | ||
273 | |||
274 | /* All offsets have now been checked. */ | ||
275 | value.ordered_offsets_up_to = G_MAXSIZE; | ||
276 | + value.checked_offsets_up_to = G_MAXSIZE; | ||
277 | |||
278 | return TRUE; | ||
279 | } | ||
280 | @@ -1040,14 +1057,15 @@ gvs_tuple_get_child (GVariantSerialised value, | ||
281 | * all the tuple *elements* here, not just all the framing offsets, since | ||
282 | * tuples contain a mix of elements which use framing offsets and ones which | ||
283 | * don’t. None of them are allowed to overlap. */ | ||
284 | - if (index_ > value.ordered_offsets_up_to) | ||
285 | + if (index_ > value.checked_offsets_up_to && | ||
286 | + value.ordered_offsets_up_to == value.checked_offsets_up_to) | ||
287 | { | ||
288 | gsize i, prev_i_end = 0; | ||
289 | |||
290 | - if (value.ordered_offsets_up_to > 0) | ||
291 | - gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end); | ||
292 | + if (value.checked_offsets_up_to > 0) | ||
293 | + gvs_tuple_get_member_bounds (value, value.checked_offsets_up_to - 1, offset_size, NULL, &prev_i_end); | ||
294 | |||
295 | - for (i = value.ordered_offsets_up_to; i <= index_; i++) | ||
296 | + for (i = value.checked_offsets_up_to; i <= index_; i++) | ||
297 | { | ||
298 | gsize i_start, i_end; | ||
299 | |||
300 | @@ -1060,6 +1078,7 @@ gvs_tuple_get_child (GVariantSerialised value, | ||
301 | } | ||
302 | |||
303 | value.ordered_offsets_up_to = i - 1; | ||
304 | + value.checked_offsets_up_to = index_; | ||
305 | } | ||
306 | |||
307 | if (index_ > value.ordered_offsets_up_to) | ||
308 | @@ -1257,6 +1276,7 @@ gvs_tuple_is_normal (GVariantSerialised value) | ||
309 | |||
310 | /* All element bounds have been checked above. */ | ||
311 | value.ordered_offsets_up_to = G_MAXSIZE; | ||
312 | + value.checked_offsets_up_to = G_MAXSIZE; | ||
313 | |||
314 | { | ||
315 | gsize fixed_size; | ||
316 | diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h | ||
317 | index 144aec8..e132451 100644 | ||
318 | --- a/glib/gvariant-serialiser.h | ||
319 | +++ b/glib/gvariant-serialiser.h | ||
320 | @@ -40,6 +40,15 @@ typedef struct | ||
321 | * Even when dealing with tuples, @ordered_offsets_up_to is an element index, | ||
322 | * rather than an index into the frame offsets. */ | ||
323 | gsize ordered_offsets_up_to; | ||
324 | + | ||
325 | + /* Similar to @ordered_offsets_up_to. This gives the index of the child element | ||
326 | + * whose frame offset is the highest in the offset table which has been | ||
327 | + * checked so far. | ||
328 | + * | ||
329 | + * This is always ≥ @ordered_offsets_up_to. It is always an element index. | ||
330 | + * | ||
331 | + * See documentation in gvariant-core.c for `struct GVariant` for details. */ | ||
332 | + gsize checked_offsets_up_to; | ||
333 | } GVariantSerialised; | ||
334 | |||
335 | /* deserialisation */ | ||
336 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
337 | index fdd36be..f910bd4 100644 | ||
338 | --- a/glib/gvariant.c | ||
339 | +++ b/glib/gvariant.c | ||
340 | @@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value) | ||
341 | serialised.size = g_variant_get_size (trusted); | ||
342 | serialised.data = g_malloc (serialised.size); | ||
343 | serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */ | ||
344 | + serialised.checked_offsets_up_to = G_MAXSIZE; | ||
345 | g_variant_store (trusted, serialised.data); | ||
346 | g_variant_unref (trusted); | ||
347 | |||
348 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
349 | index a84b02e..640f3c0 100644 | ||
350 | --- a/glib/tests/gvariant.c | ||
351 | +++ b/glib/tests/gvariant.c | ||
352 | @@ -1286,6 +1286,7 @@ random_instance_filler (GVariantSerialised *serialised, | ||
353 | |||
354 | serialised->depth = 0; | ||
355 | serialised->ordered_offsets_up_to = 0; | ||
356 | + serialised->checked_offsets_up_to = 0; | ||
357 | |||
358 | g_assert_true (serialised->type_info == instance->type_info); | ||
359 | g_assert_cmpuint (serialised->size, ==, instance->size); | ||
360 | @@ -1453,6 +1454,7 @@ test_maybe (void) | ||
361 | serialised.size = needed_size; | ||
362 | serialised.depth = 0; | ||
363 | serialised.ordered_offsets_up_to = 0; | ||
364 | + serialised.checked_offsets_up_to = 0; | ||
365 | |||
366 | g_variant_serialiser_serialise (serialised, | ||
367 | random_instance_filler, | ||
368 | @@ -1577,6 +1579,7 @@ test_array (void) | ||
369 | serialised.size = needed_size; | ||
370 | serialised.depth = 0; | ||
371 | serialised.ordered_offsets_up_to = 0; | ||
372 | + serialised.checked_offsets_up_to = 0; | ||
373 | |||
374 | g_variant_serialiser_serialise (serialised, random_instance_filler, | ||
375 | (gpointer *) instances, n_children); | ||
376 | @@ -1742,6 +1745,7 @@ test_tuple (void) | ||
377 | serialised.size = needed_size; | ||
378 | serialised.depth = 0; | ||
379 | serialised.ordered_offsets_up_to = 0; | ||
380 | + serialised.checked_offsets_up_to = 0; | ||
381 | |||
382 | g_variant_serialiser_serialise (serialised, random_instance_filler, | ||
383 | (gpointer *) instances, n_children); | ||
384 | @@ -1839,6 +1843,7 @@ test_variant (void) | ||
385 | serialised.size = needed_size; | ||
386 | serialised.depth = 0; | ||
387 | serialised.ordered_offsets_up_to = 0; | ||
388 | + serialised.checked_offsets_up_to = 0; | ||
389 | |||
390 | g_variant_serialiser_serialise (serialised, random_instance_filler, | ||
391 | (gpointer *) &instance, 1); | ||
392 | -- | ||
393 | 2.24.4 | ||
394 | |||
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 @@ | |||
1 | From 298a537d5f6783e55d87e40011ee3fd3b22b72f9 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 17 Aug 2023 01:39:01 +0000 | ||
4 | Subject: [PATCH] gvariant: Zero-initialise various GVariantSerialised objects | ||
5 | |||
6 | The following few commits will add a couple of new fields to | ||
7 | `GVariantSerialised`, and they should be zero-filled by default. | ||
8 | |||
9 | Try and pre-empt that a bit by zero-filling `GVariantSerialised` by | ||
10 | default in a few places. | ||
11 | |||
12 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
13 | |||
14 | Helps: #2121 | ||
15 | |||
16 | CVE: CVE-2023-32665 | ||
17 | Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/298a537d5f6783e55d87e40011ee3fd3b22b72f9] | ||
18 | Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | ||
19 | --- | ||
20 | glib/gvariant.c | 2 +- | ||
21 | glib/tests/gvariant.c | 12 ++++++------ | ||
22 | 2 files changed, 7 insertions(+), 7 deletions(-) | ||
23 | |||
24 | diff --git a/glib/gvariant.c b/glib/gvariant.c | ||
25 | index f910bd4..8ba701e 100644 | ||
26 | --- a/glib/gvariant.c | ||
27 | +++ b/glib/gvariant.c | ||
28 | @@ -5936,7 +5936,7 @@ g_variant_byteswap (GVariant *value) | ||
29 | if (alignment) | ||
30 | /* (potentially) contains multi-byte numeric data */ | ||
31 | { | ||
32 | - GVariantSerialised serialised; | ||
33 | + GVariantSerialised serialised = { 0, }; | ||
34 | GVariant *trusted; | ||
35 | GBytes *bytes; | ||
36 | |||
37 | diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c | ||
38 | index 640f3c0..d640c81 100644 | ||
39 | --- a/glib/tests/gvariant.c | ||
40 | +++ b/glib/tests/gvariant.c | ||
41 | @@ -1446,7 +1446,7 @@ test_maybe (void) | ||
42 | |||
43 | for (flavour = 0; flavour < 8; flavour += alignment) | ||
44 | { | ||
45 | - GVariantSerialised serialised; | ||
46 | + GVariantSerialised serialised = { 0, }; | ||
47 | GVariantSerialised child; | ||
48 | |||
49 | serialised.type_info = type_info; | ||
50 | @@ -1572,7 +1572,7 @@ test_array (void) | ||
51 | |||
52 | for (flavour = 0; flavour < 8; flavour += alignment) | ||
53 | { | ||
54 | - GVariantSerialised serialised; | ||
55 | + GVariantSerialised serialised = { 0, }; | ||
56 | |||
57 | serialised.type_info = array_info; | ||
58 | serialised.data = flavoured_malloc (needed_size, flavour); | ||
59 | @@ -1738,7 +1738,7 @@ test_tuple (void) | ||
60 | |||
61 | for (flavour = 0; flavour < 8; flavour += alignment) | ||
62 | { | ||
63 | - GVariantSerialised serialised; | ||
64 | + GVariantSerialised serialised = { 0, }; | ||
65 | |||
66 | serialised.type_info = type_info; | ||
67 | serialised.data = flavoured_malloc (needed_size, flavour); | ||
68 | @@ -1835,7 +1835,7 @@ test_variant (void) | ||
69 | |||
70 | for (flavour = 0; flavour < 8; flavour += alignment) | ||
71 | { | ||
72 | - GVariantSerialised serialised; | ||
73 | + GVariantSerialised serialised = { 0, }; | ||
74 | GVariantSerialised child; | ||
75 | |||
76 | serialised.type_info = type_info; | ||
77 | @@ -2284,7 +2284,7 @@ serialise_tree (TreeInstance *tree, | ||
78 | static void | ||
79 | test_byteswap (void) | ||
80 | { | ||
81 | - GVariantSerialised one, two; | ||
82 | + GVariantSerialised one = { 0, }, two = { 0, }; | ||
83 | TreeInstance *tree; | ||
84 | |||
85 | tree = tree_instance_new (NULL, 3); | ||
86 | @@ -2358,7 +2358,7 @@ test_serialiser_children (void) | ||
87 | static void | ||
88 | test_fuzz (gdouble *fuzziness) | ||
89 | { | ||
90 | - GVariantSerialised serialised; | ||
91 | + GVariantSerialised serialised = { 0, }; | ||
92 | TreeInstance *tree; | ||
93 | |||
94 | /* make an instance */ | ||
95 | -- | ||
96 | 2.24.4 | ||
97 | |||
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 c2145bc6c2..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 | |||
@@ -42,6 +42,20 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \ | |||
42 | file://CVE-2021-28153-3.patch \ | 42 | file://CVE-2021-28153-3.patch \ |
43 | file://CVE-2021-28153-4.patch \ | 43 | file://CVE-2021-28153-4.patch \ |
44 | file://CVE-2021-28153-5.patch \ | 44 | file://CVE-2021-28153-5.patch \ |
45 | file://CVE-2023-32665-0001.patch \ | ||
46 | file://CVE-2023-32665-0002.patch \ | ||
47 | file://CVE-2023-32665-0003.patch \ | ||
48 | file://CVE-2023-32665-0004.patch \ | ||
49 | file://CVE-2023-32665-0005.patch \ | ||
50 | file://CVE-2023-32665-0006.patch \ | ||
51 | file://CVE-2023-32665-0007.patch \ | ||
52 | file://CVE-2023-32665-0008.patch \ | ||
53 | file://CVE-2023-32665-0009.patch \ | ||
54 | file://CVE-2023-29499.patch \ | ||
55 | file://CVE-2023-32611-0001.patch \ | ||
56 | file://CVE-2023-32611-0002.patch \ | ||
57 | file://CVE-2023-32643.patch \ | ||
58 | file://CVE-2023-32636.patch \ | ||
45 | " | 59 | " |
46 | 60 | ||
47 | SRC_URI_append_class-native = " file://relocate-modules.patch" | 61 | SRC_URI_append_class-native = " file://relocate-modules.patch" |