diff options
Diffstat (limited to 'meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch')
-rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch | 255 |
1 files changed, 255 insertions, 0 deletions
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 | |||