diff options
Diffstat (limited to 'meta/recipes-core/glib-2.0')
40 files changed, 5248 insertions, 1 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch new file mode 100644 index 0000000000..6257763d8d --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch | |||
@@ -0,0 +1,129 @@ | |||
1 | Backport of: | ||
2 | |||
3 | From 0f384c88a241bbbd884487b1c40b7b75f1e638d3 Mon Sep 17 00:00:00 2001 | ||
4 | From: Krzesimir Nowak <qdlacz@gmail.com> | ||
5 | Date: Wed, 10 Feb 2021 23:51:07 +0100 | ||
6 | Subject: [PATCH] gbytearray: Do not accept too large byte arrays | ||
7 | |||
8 | GByteArray uses guint for storing the length of the byte array, but it | ||
9 | also has a constructor (g_byte_array_new_take) that takes length as a | ||
10 | gsize. gsize may be larger than guint (64 bits for gsize vs 32 bits | ||
11 | for guint). It is possible to call the function with a value greater | ||
12 | than G_MAXUINT, which will result in silent length truncation. This | ||
13 | may happen as a result of unreffing GBytes into GByteArray, so rather | ||
14 | be loud about it. | ||
15 | |||
16 | (Test case tweaked by Philip Withnall.) | ||
17 | |||
18 | (Backport 2.66: Add #include gstrfuncsprivate.h in the test case for | ||
19 | `g_memdup2()`.) | ||
20 | |||
21 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
22 | CVE: CVE-2021-27218 | ||
23 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
24 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
25 | |||
26 | --- | ||
27 | glib/garray.c | 6 ++++++ | ||
28 | glib/gbytes.c | 4 ++++ | ||
29 | glib/tests/bytes.c | 35 ++++++++++++++++++++++++++++++++++- | ||
30 | 3 files changed, 44 insertions(+), 1 deletion(-) | ||
31 | |||
32 | --- a/glib/garray.c | ||
33 | +++ b/glib/garray.c | ||
34 | @@ -2234,6 +2234,10 @@ g_byte_array_steal (GByteArray *array, | ||
35 | * Create byte array containing the data. The data will be owned by the array | ||
36 | * and will be freed with g_free(), i.e. it could be allocated using g_strdup(). | ||
37 | * | ||
38 | + * Do not use it if @len is greater than %G_MAXUINT. #GByteArray | ||
39 | + * stores the length of its data in #guint, which may be shorter than | ||
40 | + * #gsize. | ||
41 | + * | ||
42 | * Since: 2.32 | ||
43 | * | ||
44 | * Returns: (transfer full): a new #GByteArray | ||
45 | @@ -2245,6 +2249,8 @@ g_byte_array_new_take (guint8 *data, | ||
46 | GByteArray *array; | ||
47 | GRealArray *real; | ||
48 | |||
49 | + g_return_val_if_fail (len <= G_MAXUINT, NULL); | ||
50 | + | ||
51 | array = g_byte_array_new (); | ||
52 | real = (GRealArray *)array; | ||
53 | g_assert (real->data == NULL); | ||
54 | --- a/glib/gbytes.c | ||
55 | +++ b/glib/gbytes.c | ||
56 | @@ -519,6 +519,10 @@ g_bytes_unref_to_data (GBytes *bytes, | ||
57 | * g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all | ||
58 | * other cases the data is copied. | ||
59 | * | ||
60 | + * Do not use it if @bytes contains more than %G_MAXUINT | ||
61 | + * bytes. #GByteArray stores the length of its data in #guint, which | ||
62 | + * may be shorter than #gsize, that @bytes is using. | ||
63 | + * | ||
64 | * Returns: (transfer full): a new mutable #GByteArray containing the same byte data | ||
65 | * | ||
66 | * Since: 2.32 | ||
67 | --- a/glib/tests/bytes.c | ||
68 | +++ b/glib/tests/bytes.c | ||
69 | @@ -10,12 +10,12 @@ | ||
70 | */ | ||
71 | |||
72 | #undef G_DISABLE_ASSERT | ||
73 | -#undef G_LOG_DOMAIN | ||
74 | |||
75 | #include <stdio.h> | ||
76 | #include <stdlib.h> | ||
77 | #include <string.h> | ||
78 | #include "glib.h" | ||
79 | +#include "glib/gstrfuncsprivate.h" | ||
80 | |||
81 | /* Keep in sync with glib/gbytes.c */ | ||
82 | struct _GBytes | ||
83 | @@ -334,6 +334,38 @@ test_to_array_transferred (void) | ||
84 | } | ||
85 | |||
86 | static void | ||
87 | +test_to_array_transferred_oversize (void) | ||
88 | +{ | ||
89 | + g_test_message ("g_bytes_unref_to_array() can only take GBytes up to " | ||
90 | + "G_MAXUINT in length; test that longer ones are rejected"); | ||
91 | + | ||
92 | + if (sizeof (guint) >= sizeof (gsize)) | ||
93 | + { | ||
94 | + g_test_skip ("Skipping test as guint is not smaller than gsize"); | ||
95 | + } | ||
96 | + else if (g_test_undefined ()) | ||
97 | + { | ||
98 | + GByteArray *array = NULL; | ||
99 | + GBytes *bytes = NULL; | ||
100 | + gpointer data = g_memdup2 (NYAN, N_NYAN); | ||
101 | + gsize len = ((gsize) G_MAXUINT) + 1; | ||
102 | + | ||
103 | + bytes = g_bytes_new_take (data, len); | ||
104 | + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, | ||
105 | + "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed"); | ||
106 | + array = g_bytes_unref_to_array (g_steal_pointer (&bytes)); | ||
107 | + g_test_assert_expected_messages (); | ||
108 | + g_assert_null (array); | ||
109 | + | ||
110 | + g_free (data); | ||
111 | + } | ||
112 | + else | ||
113 | + { | ||
114 | + g_test_skip ("Skipping test as testing undefined behaviour is disabled"); | ||
115 | + } | ||
116 | +} | ||
117 | + | ||
118 | +static void | ||
119 | test_to_array_two_refs (void) | ||
120 | { | ||
121 | gconstpointer memory; | ||
122 | @@ -410,6 +442,7 @@ main (int argc, char *argv[]) | ||
123 | g_test_add_func ("/bytes/to-array/transfered", test_to_array_transferred); | ||
124 | g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs); | ||
125 | g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc); | ||
126 | + g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize); | ||
127 | g_test_add_func ("/bytes/null", test_null); | ||
128 | |||
129 | return g_test_run (); | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch new file mode 100644 index 0000000000..2af9dd6aa4 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch | |||
@@ -0,0 +1,170 @@ | |||
1 | Backport of: | ||
2 | |||
3 | From 5e5f75a77e399c638be66d74e5daa8caeb433e00 Mon Sep 17 00:00:00 2001 | ||
4 | From: Philip Withnall <pwithnall@endlessos.org> | ||
5 | Date: Thu, 4 Feb 2021 13:30:52 +0000 | ||
6 | Subject: [PATCH 01/11] gstrfuncs: Add internal g_memdup2() function | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: text/plain; charset=UTF-8 | ||
9 | Content-Transfer-Encoding: 8bit | ||
10 | |||
11 | This will replace the existing `g_memdup()` function for use within | ||
12 | GLib. It has an unavoidable security flaw of taking its `byte_size` | ||
13 | argument as a `guint` rather than as a `gsize`. Most callers will | ||
14 | expect it to be a `gsize`, and may pass in large values which could | ||
15 | silently be truncated, resulting in an undersize allocation compared | ||
16 | to what the caller expects. | ||
17 | |||
18 | This could lead to a classic buffer overflow vulnerability for many | ||
19 | callers of `g_memdup()`. | ||
20 | |||
21 | `g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`. | ||
22 | |||
23 | Spotted by Kevin Backhouse of GHSL. | ||
24 | |||
25 | In GLib 2.68, `g_memdup2()` will be a new public API. In this version | ||
26 | for backport to older stable releases, it’s a new `static inline` API | ||
27 | in a private header, so that use of `g_memdup()` within GLib can be | ||
28 | fixed without adding a new API in a stable release series. | ||
29 | |||
30 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
31 | Helps: GHSL-2021-045 | ||
32 | Helps: #2319 | ||
33 | |||
34 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
35 | CVE: CVE-2021-27219 | ||
36 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
37 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
38 | |||
39 | --- | ||
40 | docs/reference/glib/meson.build | 1 + | ||
41 | glib/gstrfuncsprivate.h | 55 +++++++++++++++++++++++++++++++++ | ||
42 | glib/meson.build | 1 + | ||
43 | glib/tests/strfuncs.c | 23 ++++++++++++++ | ||
44 | 4 files changed, 80 insertions(+) | ||
45 | create mode 100644 glib/gstrfuncsprivate.h | ||
46 | |||
47 | --- a/docs/reference/glib/meson.build | ||
48 | +++ b/docs/reference/glib/meson.build | ||
49 | @@ -22,6 +22,7 @@ if get_option('gtk_doc') | ||
50 | 'gprintfint.h', | ||
51 | 'gmirroringtable.h', | ||
52 | 'gscripttable.h', | ||
53 | + 'gstrfuncsprivate.h', | ||
54 | 'glib-mirroring-tab', | ||
55 | 'gnulib', | ||
56 | 'pcre', | ||
57 | --- /dev/null | ||
58 | +++ b/glib/gstrfuncsprivate.h | ||
59 | @@ -0,0 +1,55 @@ | ||
60 | +/* GLIB - Library of useful routines for C programming | ||
61 | + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald | ||
62 | + * | ||
63 | + * This library is free software; you can redistribute it and/or | ||
64 | + * modify it under the terms of the GNU Lesser General Public | ||
65 | + * License as published by the Free Software Foundation; either | ||
66 | + * version 2.1 of the License, or (at your option) any later version. | ||
67 | + * | ||
68 | + * This library is distributed in the hope that it will be useful, | ||
69 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
70 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
71 | + * Lesser General Public License for more details. | ||
72 | + * | ||
73 | + * You should have received a copy of the GNU Lesser General Public | ||
74 | + * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||
75 | + */ | ||
76 | + | ||
77 | +#include <glib.h> | ||
78 | +#include <string.h> | ||
79 | + | ||
80 | +/* | ||
81 | + * g_memdup2: | ||
82 | + * @mem: (nullable): the memory to copy. | ||
83 | + * @byte_size: the number of bytes to copy. | ||
84 | + * | ||
85 | + * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it | ||
86 | + * from @mem. If @mem is %NULL it returns %NULL. | ||
87 | + * | ||
88 | + * This replaces g_memdup(), which was prone to integer overflows when | ||
89 | + * converting the argument from a #gsize to a #guint. | ||
90 | + * | ||
91 | + * This static inline version is a backport of the new public API from | ||
92 | + * GLib 2.68, kept internal to GLib for backport to older stable releases. | ||
93 | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319. | ||
94 | + * | ||
95 | + * Returns: (nullable): a pointer to the newly-allocated copy of the memory, | ||
96 | + * or %NULL if @mem is %NULL. | ||
97 | + * Since: 2.68 | ||
98 | + */ | ||
99 | +static inline gpointer | ||
100 | +g_memdup2 (gconstpointer mem, | ||
101 | + gsize byte_size) | ||
102 | +{ | ||
103 | + gpointer new_mem; | ||
104 | + | ||
105 | + if (mem && byte_size != 0) | ||
106 | + { | ||
107 | + new_mem = g_malloc (byte_size); | ||
108 | + memcpy (new_mem, mem, byte_size); | ||
109 | + } | ||
110 | + else | ||
111 | + new_mem = NULL; | ||
112 | + | ||
113 | + return new_mem; | ||
114 | +} | ||
115 | --- a/glib/meson.build | ||
116 | +++ b/glib/meson.build | ||
117 | @@ -268,6 +268,7 @@ glib_sources = files( | ||
118 | 'gslist.c', | ||
119 | 'gstdio.c', | ||
120 | 'gstrfuncs.c', | ||
121 | + 'gstrfuncsprivate.h', | ||
122 | 'gstring.c', | ||
123 | 'gstringchunk.c', | ||
124 | 'gtestutils.c', | ||
125 | --- a/glib/tests/strfuncs.c | ||
126 | +++ b/glib/tests/strfuncs.c | ||
127 | @@ -32,6 +32,8 @@ | ||
128 | #include <string.h> | ||
129 | #include "glib.h" | ||
130 | |||
131 | +#include "gstrfuncsprivate.h" | ||
132 | + | ||
133 | #if defined (_MSC_VER) && (_MSC_VER <= 1800) | ||
134 | #define isnan(x) _isnan(x) | ||
135 | |||
136 | @@ -219,6 +221,26 @@ test_memdup (void) | ||
137 | g_free (str_dup); | ||
138 | } | ||
139 | |||
140 | +/* Testing g_memdup2() function with various positive and negative cases */ | ||
141 | +static void | ||
142 | +test_memdup2 (void) | ||
143 | +{ | ||
144 | + gchar *str_dup = NULL; | ||
145 | + const gchar *str = "The quick brown fox jumps over the lazy dog"; | ||
146 | + | ||
147 | + /* Testing negative cases */ | ||
148 | + g_assert_null (g_memdup2 (NULL, 1024)); | ||
149 | + g_assert_null (g_memdup2 (str, 0)); | ||
150 | + g_assert_null (g_memdup2 (NULL, 0)); | ||
151 | + | ||
152 | + /* Testing normal usage cases */ | ||
153 | + str_dup = g_memdup2 (str, strlen (str) + 1); | ||
154 | + g_assert_nonnull (str_dup); | ||
155 | + g_assert_cmpstr (str, ==, str_dup); | ||
156 | + | ||
157 | + g_free (str_dup); | ||
158 | +} | ||
159 | + | ||
160 | /* Testing g_strpcpy() function with various positive and negative cases */ | ||
161 | static void | ||
162 | test_stpcpy (void) | ||
163 | @@ -2523,6 +2545,7 @@ main (int argc, | ||
164 | g_test_add_func ("/strfuncs/has-prefix", test_has_prefix); | ||
165 | g_test_add_func ("/strfuncs/has-suffix", test_has_suffix); | ||
166 | g_test_add_func ("/strfuncs/memdup", test_memdup); | ||
167 | + g_test_add_func ("/strfuncs/memdup2", test_memdup2); | ||
168 | g_test_add_func ("/strfuncs/stpcpy", test_stpcpy); | ||
169 | g_test_add_func ("/strfuncs/str_match_string", test_str_match_string); | ||
170 | g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold); | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch new file mode 100644 index 0000000000..20137ea5f3 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch | |||
@@ -0,0 +1,249 @@ | |||
1 | From be8834340a2d928ece82025463ae23dee2c333d0 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 13:37:56 +0000 | ||
4 | Subject: [PATCH 02/11] gio: Use g_memdup2() instead of g_memdup() in obvious | ||
5 | places | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=UTF-8 | ||
8 | Content-Transfer-Encoding: 8bit | ||
9 | |||
10 | Convert all the call sites which use `g_memdup()`’s length argument | ||
11 | trivially (for example, by passing a `sizeof()`), so that they use | ||
12 | `g_memdup2()` instead. | ||
13 | |||
14 | In almost all of these cases the use of `g_memdup()` would not have | ||
15 | caused problems, but it will soon be deprecated, so best port away from | ||
16 | it. | ||
17 | |||
18 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
19 | Helps: #2319 | ||
20 | |||
21 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
22 | CVE: CVE-2021-27219 | ||
23 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
24 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
25 | |||
26 | --- | ||
27 | gio/gdbusconnection.c | 5 +++-- | ||
28 | gio/gdbusinterfaceskeleton.c | 3 ++- | ||
29 | gio/gfile.c | 7 ++++--- | ||
30 | gio/gsettingsschema.c | 5 +++-- | ||
31 | gio/gwin32registrykey.c | 8 +++++--- | ||
32 | gio/tests/async-close-output-stream.c | 6 ++++-- | ||
33 | gio/tests/gdbus-export.c | 5 +++-- | ||
34 | gio/win32/gwinhttpfile.c | 9 +++++---- | ||
35 | 8 files changed, 29 insertions(+), 19 deletions(-) | ||
36 | |||
37 | --- a/gio/gdbusconnection.c | ||
38 | +++ b/gio/gdbusconnection.c | ||
39 | @@ -110,6 +110,7 @@ | ||
40 | #include "gasyncinitable.h" | ||
41 | #include "giostream.h" | ||
42 | #include "gasyncresult.h" | ||
43 | +#include "gstrfuncsprivate.h" | ||
44 | #include "gtask.h" | ||
45 | #include "gmarshal-internal.h" | ||
46 | |||
47 | @@ -4007,7 +4008,7 @@ _g_dbus_interface_vtable_copy (const GDB | ||
48 | /* Don't waste memory by copying padding - remember to update this | ||
49 | * when changing struct _GDBusInterfaceVTable in gdbusconnection.h | ||
50 | */ | ||
51 | - return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
52 | + return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
53 | } | ||
54 | |||
55 | static void | ||
56 | @@ -4024,7 +4025,7 @@ _g_dbus_subtree_vtable_copy (const GDBus | ||
57 | /* Don't waste memory by copying padding - remember to update this | ||
58 | * when changing struct _GDBusSubtreeVTable in gdbusconnection.h | ||
59 | */ | ||
60 | - return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
61 | + return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); | ||
62 | } | ||
63 | |||
64 | static void | ||
65 | --- a/gio/gdbusinterfaceskeleton.c | ||
66 | +++ b/gio/gdbusinterfaceskeleton.c | ||
67 | @@ -28,6 +28,7 @@ | ||
68 | #include "gdbusmethodinvocation.h" | ||
69 | #include "gdbusconnection.h" | ||
70 | #include "gmarshal-internal.h" | ||
71 | +#include "gstrfuncsprivate.h" | ||
72 | #include "gtask.h" | ||
73 | #include "gioerror.h" | ||
74 | |||
75 | @@ -701,7 +702,7 @@ add_connection_locked (GDBusInterfaceSke | ||
76 | * properly before building the hooked_vtable, so we create it | ||
77 | * once at the last minute. | ||
78 | */ | ||
79 | - interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); | ||
80 | + interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); | ||
81 | interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call; | ||
82 | } | ||
83 | |||
84 | --- a/gio/gfile.c | ||
85 | +++ b/gio/gfile.c | ||
86 | @@ -60,6 +60,7 @@ | ||
87 | #include "gasyncresult.h" | ||
88 | #include "gioerror.h" | ||
89 | #include "glibintl.h" | ||
90 | +#include "gstrfuncsprivate.h" | ||
91 | |||
92 | |||
93 | /** | ||
94 | @@ -7854,7 +7855,7 @@ measure_disk_usage_progress (gboolean re | ||
95 | g_main_context_invoke_full (g_task_get_context (task), | ||
96 | g_task_get_priority (task), | ||
97 | measure_disk_usage_invoke_progress, | ||
98 | - g_memdup (&progress, sizeof progress), | ||
99 | + g_memdup2 (&progress, sizeof progress), | ||
100 | g_free); | ||
101 | } | ||
102 | |||
103 | @@ -7872,7 +7873,7 @@ measure_disk_usage_thread (GTask | ||
104 | data->progress_callback ? measure_disk_usage_progress : NULL, task, | ||
105 | &result.disk_usage, &result.num_dirs, &result.num_files, | ||
106 | &error)) | ||
107 | - g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free); | ||
108 | + g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free); | ||
109 | else | ||
110 | g_task_return_error (task, error); | ||
111 | } | ||
112 | @@ -7896,7 +7897,7 @@ g_file_real_measure_disk_usage_async (GF | ||
113 | |||
114 | task = g_task_new (file, cancellable, callback, user_data); | ||
115 | g_task_set_source_tag (task, g_file_real_measure_disk_usage_async); | ||
116 | - g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free); | ||
117 | + g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free); | ||
118 | g_task_set_priority (task, io_priority); | ||
119 | |||
120 | g_task_run_in_thread (task, measure_disk_usage_thread); | ||
121 | --- a/gio/gsettingsschema.c | ||
122 | +++ b/gio/gsettingsschema.c | ||
123 | @@ -20,6 +20,7 @@ | ||
124 | |||
125 | #include "gsettingsschema-internal.h" | ||
126 | #include "gsettings.h" | ||
127 | +#include "gstrfuncsprivate.h" | ||
128 | |||
129 | #include "gvdb/gvdb-reader.h" | ||
130 | #include "strinfo.c" | ||
131 | @@ -1067,9 +1068,9 @@ g_settings_schema_list_children (GSettin | ||
132 | |||
133 | if (g_str_has_suffix (key, "/")) | ||
134 | { | ||
135 | - gint length = strlen (key); | ||
136 | + gsize length = strlen (key); | ||
137 | |||
138 | - strv[j] = g_memdup (key, length); | ||
139 | + strv[j] = g_memdup2 (key, length); | ||
140 | strv[j][length - 1] = '\0'; | ||
141 | j++; | ||
142 | } | ||
143 | --- a/gio/gwin32registrykey.c | ||
144 | +++ b/gio/gwin32registrykey.c | ||
145 | @@ -28,6 +28,8 @@ | ||
146 | #include <ntstatus.h> | ||
147 | #include <winternl.h> | ||
148 | |||
149 | +#include "gstrfuncsprivate.h" | ||
150 | + | ||
151 | #ifndef _WDMDDK_ | ||
152 | typedef enum _KEY_INFORMATION_CLASS { | ||
153 | KeyBasicInformation, | ||
154 | @@ -247,7 +249,7 @@ g_win32_registry_value_iter_copy (const | ||
155 | new_iter->value_name_size = iter->value_name_size; | ||
156 | |||
157 | if (iter->value_data != NULL) | ||
158 | - new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size); | ||
159 | + new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size); | ||
160 | |||
161 | new_iter->value_data_size = iter->value_data_size; | ||
162 | |||
163 | @@ -268,8 +270,8 @@ g_win32_registry_value_iter_copy (const | ||
164 | new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize; | ||
165 | |||
166 | if (iter->value_data_expanded_u8 != NULL) | ||
167 | - new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8, | ||
168 | - iter->value_data_expanded_charsize); | ||
169 | + new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8, | ||
170 | + iter->value_data_expanded_charsize); | ||
171 | |||
172 | new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize; | ||
173 | |||
174 | --- a/gio/tests/async-close-output-stream.c | ||
175 | +++ b/gio/tests/async-close-output-stream.c | ||
176 | @@ -24,6 +24,8 @@ | ||
177 | #include <stdlib.h> | ||
178 | #include <string.h> | ||
179 | |||
180 | +#include "gstrfuncsprivate.h" | ||
181 | + | ||
182 | #define DATA_TO_WRITE "Hello world\n" | ||
183 | |||
184 | typedef struct | ||
185 | @@ -147,9 +149,9 @@ prepare_data (SetupData *data, | ||
186 | |||
187 | data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream)); | ||
188 | |||
189 | - g_assert_cmpint (data->expected_size, >, 0); | ||
190 | + g_assert_cmpuint (data->expected_size, >, 0); | ||
191 | |||
192 | - data->expected_output = g_memdup (written, (guint)data->expected_size); | ||
193 | + data->expected_output = g_memdup2 (written, data->expected_size); | ||
194 | |||
195 | /* then recreate the streams and prepare them for the asynchronous close */ | ||
196 | destroy_streams (data); | ||
197 | --- a/gio/tests/gdbus-export.c | ||
198 | +++ b/gio/tests/gdbus-export.c | ||
199 | @@ -23,6 +23,7 @@ | ||
200 | #include <string.h> | ||
201 | |||
202 | #include "gdbus-tests.h" | ||
203 | +#include "gstrfuncsprivate.h" | ||
204 | |||
205 | /* all tests rely on a shared mainloop */ | ||
206 | static GMainLoop *loop = NULL; | ||
207 | @@ -671,7 +672,7 @@ subtree_introspect (GDBusConnection | ||
208 | g_assert_not_reached (); | ||
209 | } | ||
210 | |||
211 | - return g_memdup (interfaces, 2 * sizeof (void *)); | ||
212 | + return g_memdup2 (interfaces, 2 * sizeof (void *)); | ||
213 | } | ||
214 | |||
215 | static const GDBusInterfaceVTable * | ||
216 | @@ -727,7 +728,7 @@ dynamic_subtree_introspect (GDBusConnect | ||
217 | { | ||
218 | const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL }; | ||
219 | |||
220 | - return g_memdup (interfaces, 2 * sizeof (void *)); | ||
221 | + return g_memdup2 (interfaces, 2 * sizeof (void *)); | ||
222 | } | ||
223 | |||
224 | static const GDBusInterfaceVTable * | ||
225 | --- a/gio/win32/gwinhttpfile.c | ||
226 | +++ b/gio/win32/gwinhttpfile.c | ||
227 | @@ -29,6 +29,7 @@ | ||
228 | #include "gio/gfile.h" | ||
229 | #include "gio/gfileattribute.h" | ||
230 | #include "gio/gfileinfo.h" | ||
231 | +#include "gstrfuncsprivate.h" | ||
232 | #include "gwinhttpfile.h" | ||
233 | #include "gwinhttpfileinputstream.h" | ||
234 | #include "gwinhttpfileoutputstream.h" | ||
235 | @@ -393,10 +394,10 @@ | ||
236 | child = g_object_new (G_TYPE_WINHTTP_FILE, NULL); | ||
237 | child->vfs = winhttp_file->vfs; | ||
238 | child->url = winhttp_file->url; | ||
239 | - child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); | ||
240 | - child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); | ||
241 | - child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); | ||
242 | - child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); | ||
243 | + child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); | ||
244 | + child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); | ||
245 | + child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); | ||
246 | + child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); | ||
247 | child->url.lpszUrlPath = wnew_path; | ||
248 | child->url.dwUrlPathLength = wcslen (wnew_path); | ||
249 | child->url.lpszExtraInfo = NULL; | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch new file mode 100644 index 0000000000..eceff161a6 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch | |||
@@ -0,0 +1,131 @@ | |||
1 | From 6110caea45b235420b98cd41d845cc92238f6781 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 13:39:25 +0000 | ||
4 | Subject: [PATCH 03/11] gobject: Use g_memdup2() instead of g_memdup() in | ||
5 | obvious places | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=UTF-8 | ||
8 | Content-Transfer-Encoding: 8bit | ||
9 | |||
10 | Convert all the call sites which use `g_memdup()`’s length argument | ||
11 | trivially (for example, by passing a `sizeof()`), so that they use | ||
12 | `g_memdup2()` instead. | ||
13 | |||
14 | In almost all of these cases the use of `g_memdup()` would not have | ||
15 | caused problems, but it will soon be deprecated, so best port away from | ||
16 | it. | ||
17 | |||
18 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
19 | Helps: #2319 | ||
20 | |||
21 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
22 | CVE: CVE-2021-27219 | ||
23 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
24 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
25 | |||
26 | --- | ||
27 | gobject/gsignal.c | 3 ++- | ||
28 | gobject/gtype.c | 9 +++++---- | ||
29 | gobject/gtypemodule.c | 3 ++- | ||
30 | gobject/tests/param.c | 4 +++- | ||
31 | 4 files changed, 12 insertions(+), 7 deletions(-) | ||
32 | |||
33 | --- a/gobject/gsignal.c | ||
34 | +++ b/gobject/gsignal.c | ||
35 | @@ -28,6 +28,7 @@ | ||
36 | #include <signal.h> | ||
37 | |||
38 | #include "gsignal.h" | ||
39 | +#include "gstrfuncsprivate.h" | ||
40 | #include "gtype-private.h" | ||
41 | #include "gbsearcharray.h" | ||
42 | #include "gvaluecollector.h" | ||
43 | @@ -1809,7 +1810,7 @@ g_signal_newv (const gchar *signal | ||
44 | node->single_va_closure_is_valid = FALSE; | ||
45 | node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; | ||
46 | node->n_params = n_params; | ||
47 | - node->param_types = g_memdup (param_types, sizeof (GType) * n_params); | ||
48 | + node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params); | ||
49 | node->return_type = return_type; | ||
50 | node->class_closure_bsa = NULL; | ||
51 | if (accumulator) | ||
52 | --- a/gobject/gtype.c | ||
53 | +++ b/gobject/gtype.c | ||
54 | @@ -33,6 +33,7 @@ | ||
55 | |||
56 | #include "glib-private.h" | ||
57 | #include "gconstructor.h" | ||
58 | +#include "gstrfuncsprivate.h" | ||
59 | |||
60 | #ifdef G_OS_WIN32 | ||
61 | #include <windows.h> | ||
62 | @@ -1470,7 +1471,7 @@ type_add_interface_Wm (TypeNode | ||
63 | iholder->next = iface_node_get_holders_L (iface); | ||
64 | iface_node_set_holders_W (iface, iholder); | ||
65 | iholder->instance_type = NODE_TYPE (node); | ||
66 | - iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL; | ||
67 | + iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL; | ||
68 | iholder->plugin = plugin; | ||
69 | |||
70 | /* create an iface entry for this type */ | ||
71 | @@ -1731,7 +1732,7 @@ type_iface_retrieve_holder_info_Wm (Type | ||
72 | INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface)); | ||
73 | |||
74 | check_interface_info_I (iface, instance_type, &tmp_info); | ||
75 | - iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); | ||
76 | + iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info)); | ||
77 | } | ||
78 | |||
79 | return iholder; /* we don't modify write lock upon returning NULL */ | ||
80 | @@ -2016,10 +2017,10 @@ type_iface_vtable_base_init_Wm (TypeNode | ||
81 | IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); | ||
82 | |||
83 | if (pentry) | ||
84 | - vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); | ||
85 | + vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size); | ||
86 | } | ||
87 | if (!vtable) | ||
88 | - vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); | ||
89 | + vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); | ||
90 | entry->vtable = vtable; | ||
91 | vtable->g_type = NODE_TYPE (iface); | ||
92 | vtable->g_instance_type = NODE_TYPE (node); | ||
93 | --- a/gobject/gtypemodule.c | ||
94 | +++ b/gobject/gtypemodule.c | ||
95 | @@ -19,6 +19,7 @@ | ||
96 | |||
97 | #include <stdlib.h> | ||
98 | |||
99 | +#include "gstrfuncsprivate.h" | ||
100 | #include "gtypeplugin.h" | ||
101 | #include "gtypemodule.h" | ||
102 | |||
103 | @@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule | ||
104 | module_type_info->loaded = TRUE; | ||
105 | module_type_info->info = *type_info; | ||
106 | if (type_info->value_table) | ||
107 | - module_type_info->info.value_table = g_memdup (type_info->value_table, | ||
108 | + module_type_info->info.value_table = g_memdup2 (type_info->value_table, | ||
109 | sizeof (GTypeValueTable)); | ||
110 | |||
111 | return module_type_info->type; | ||
112 | --- a/gobject/tests/param.c | ||
113 | +++ b/gobject/tests/param.c | ||
114 | @@ -2,6 +2,8 @@ | ||
115 | #include <glib-object.h> | ||
116 | #include <stdlib.h> | ||
117 | |||
118 | +#include "gstrfuncsprivate.h" | ||
119 | + | ||
120 | static void | ||
121 | test_param_value (void) | ||
122 | { | ||
123 | @@ -874,7 +876,7 @@ main (int argc, char *argv[]) | ||
124 | test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d", | ||
125 | data.change_this_flag, data.change_this_type, | ||
126 | data.use_this_flag, data.use_this_type); | ||
127 | - test_data = g_memdup (&data, sizeof (TestParamImplementData)); | ||
128 | + test_data = g_memdup2 (&data, sizeof (TestParamImplementData)); | ||
129 | g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free); | ||
130 | g_free (test_path); | ||
131 | } | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch new file mode 100644 index 0000000000..6a3ac6b552 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch | |||
@@ -0,0 +1,298 @@ | |||
1 | Backport of: | ||
2 | |||
3 | From 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa Mon Sep 17 00:00:00 2001 | ||
4 | From: Philip Withnall <pwithnall@endlessos.org> | ||
5 | Date: Thu, 4 Feb 2021 13:41:21 +0000 | ||
6 | Subject: [PATCH 04/11] glib: Use g_memdup2() instead of g_memdup() in obvious | ||
7 | places | ||
8 | MIME-Version: 1.0 | ||
9 | Content-Type: text/plain; charset=UTF-8 | ||
10 | Content-Transfer-Encoding: 8bit | ||
11 | |||
12 | Convert all the call sites which use `g_memdup()`’s length argument | ||
13 | trivially (for example, by passing a `sizeof()` or an existing `gsize` | ||
14 | variable), so that they use `g_memdup2()` instead. | ||
15 | |||
16 | In almost all of these cases the use of `g_memdup()` would not have | ||
17 | caused problems, but it will soon be deprecated, so best port away from | ||
18 | it | ||
19 | |||
20 | In particular, this fixes an overflow within `g_bytes_new()`, identified | ||
21 | as GHSL-2021-045 by GHSL team member Kevin Backhouse. | ||
22 | |||
23 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
24 | Fixes: GHSL-2021-045 | ||
25 | Helps: #2319 | ||
26 | |||
27 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
28 | CVE: CVE-2021-27219 | ||
29 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
30 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
31 | |||
32 | --- | ||
33 | glib/gbytes.c | 6 ++++-- | ||
34 | glib/gdir.c | 3 ++- | ||
35 | glib/ghash.c | 7 ++++--- | ||
36 | glib/giochannel.c | 5 +++-- | ||
37 | glib/gslice.c | 3 ++- | ||
38 | glib/gtestutils.c | 3 ++- | ||
39 | glib/gvariant.c | 7 ++++--- | ||
40 | glib/gvarianttype.c | 3 ++- | ||
41 | glib/tests/array-test.c | 4 +++- | ||
42 | glib/tests/option-context.c | 6 ++++-- | ||
43 | glib/tests/uri.c | 8 +++++--- | ||
44 | 11 files changed, 35 insertions(+), 20 deletions(-) | ||
45 | |||
46 | --- a/glib/gbytes.c | ||
47 | +++ b/glib/gbytes.c | ||
48 | @@ -34,6 +34,8 @@ | ||
49 | |||
50 | #include <string.h> | ||
51 | |||
52 | +#include "gstrfuncsprivate.h" | ||
53 | + | ||
54 | /** | ||
55 | * GBytes: | ||
56 | * | ||
57 | @@ -95,7 +97,7 @@ g_bytes_new (gconstpointer data, | ||
58 | { | ||
59 | g_return_val_if_fail (data != NULL || size == 0, NULL); | ||
60 | |||
61 | - return g_bytes_new_take (g_memdup (data, size), size); | ||
62 | + return g_bytes_new_take (g_memdup2 (data, size), size); | ||
63 | } | ||
64 | |||
65 | /** | ||
66 | @@ -499,7 +501,7 @@ g_bytes_unref_to_data (GBytes *bytes, | ||
67 | * Copy: Non g_malloc (or compatible) allocator, or static memory, | ||
68 | * so we have to copy, and then unref. | ||
69 | */ | ||
70 | - result = g_memdup (bytes->data, bytes->size); | ||
71 | + result = g_memdup2 (bytes->data, bytes->size); | ||
72 | *size = bytes->size; | ||
73 | g_bytes_unref (bytes); | ||
74 | } | ||
75 | --- a/glib/gdir.c | ||
76 | +++ b/glib/gdir.c | ||
77 | @@ -37,6 +37,7 @@ | ||
78 | #include "gconvert.h" | ||
79 | #include "gfileutils.h" | ||
80 | #include "gstrfuncs.h" | ||
81 | +#include "gstrfuncsprivate.h" | ||
82 | #include "gtestutils.h" | ||
83 | #include "glibintl.h" | ||
84 | |||
85 | @@ -112,7 +113,7 @@ g_dir_open_with_errno (const gchar *path | ||
86 | return NULL; | ||
87 | #endif | ||
88 | |||
89 | - return g_memdup (&dir, sizeof dir); | ||
90 | + return g_memdup2 (&dir, sizeof dir); | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | --- a/glib/ghash.c | ||
95 | +++ b/glib/ghash.c | ||
96 | @@ -34,6 +34,7 @@ | ||
97 | #include "gmacros.h" | ||
98 | #include "glib-private.h" | ||
99 | #include "gstrfuncs.h" | ||
100 | +#include "gstrfuncsprivate.h" | ||
101 | #include "gatomic.h" | ||
102 | #include "gtestutils.h" | ||
103 | #include "gslice.h" | ||
104 | @@ -962,7 +963,7 @@ g_hash_table_ensure_keyval_fits (GHashTa | ||
105 | if (hash_table->have_big_keys) | ||
106 | { | ||
107 | if (key != value) | ||
108 | - hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
109 | + hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
110 | /* Keys and values are both big now, so no need for further checks */ | ||
111 | return; | ||
112 | } | ||
113 | @@ -970,7 +971,7 @@ g_hash_table_ensure_keyval_fits (GHashTa | ||
114 | { | ||
115 | if (key != value) | ||
116 | { | ||
117 | - hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size); | ||
118 | + hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size); | ||
119 | is_a_set = FALSE; | ||
120 | } | ||
121 | } | ||
122 | @@ -998,7 +999,7 @@ g_hash_table_ensure_keyval_fits (GHashTa | ||
123 | |||
124 | /* Just split if necessary */ | ||
125 | if (is_a_set && key != value) | ||
126 | - hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
127 | + hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); | ||
128 | |||
129 | #endif | ||
130 | } | ||
131 | --- a/glib/giochannel.c | ||
132 | +++ b/glib/giochannel.c | ||
133 | @@ -35,7 +35,7 @@ | ||
134 | #include <errno.h> | ||
135 | |||
136 | #include "giochannel.h" | ||
137 | - | ||
138 | +#include "gstrfuncsprivate.h" | ||
139 | #include "gstrfuncs.h" | ||
140 | #include "gtestutils.h" | ||
141 | #include "glibintl.h" | ||
142 | |||
143 | @@ -1673,10 +1674,10 @@ g_io_channel_read_line (GIOChannel *cha | ||
144 | |||
145 | /* Copy the read bytes (including any embedded nuls) and nul-terminate. | ||
146 | * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a | ||
147 | - * #GString, so it’s safe to call g_memdup() with +1 length to allocate | ||
148 | + * #GString, so it’s safe to call g_memdup2() with +1 length to allocate | ||
149 | * a nul-terminator. */ | ||
150 | g_assert (USE_BUF (channel)); | ||
151 | - line = g_memdup (USE_BUF (channel)->str, got_length + 1); | ||
152 | + line = g_memdup2 (USE_BUF (channel)->str, got_length + 1); | ||
153 | line[got_length] = '\0'; | ||
154 | *str_return = g_steal_pointer (&line); | ||
155 | g_string_erase (USE_BUF (channel), 0, got_length); | ||
156 | --- a/glib/gslice.c | ||
157 | +++ b/glib/gslice.c | ||
158 | @@ -41,6 +41,7 @@ | ||
159 | #include "gmain.h" | ||
160 | #include "gmem.h" /* gslice.h */ | ||
161 | #include "gstrfuncs.h" | ||
162 | +#include "gstrfuncsprivate.h" | ||
163 | #include "gutils.h" | ||
164 | #include "gtrashstack.h" | ||
165 | #include "gtestutils.h" | ||
166 | @@ -350,7 +351,7 @@ g_slice_get_config_state (GSliceConfig c | ||
167 | array[i++] = allocator->contention_counters[address]; | ||
168 | array[i++] = allocator_get_magazine_threshold (allocator, address); | ||
169 | *n_values = i; | ||
170 | - return g_memdup (array, sizeof (array[0]) * *n_values); | ||
171 | + return g_memdup2 (array, sizeof (array[0]) * *n_values); | ||
172 | default: | ||
173 | return NULL; | ||
174 | } | ||
175 | --- a/glib/gtestutils.c | ||
176 | +++ b/glib/gtestutils.c | ||
177 | @@ -49,6 +49,7 @@ | ||
178 | #include "gpattern.h" | ||
179 | #include "grand.h" | ||
180 | #include "gstrfuncs.h" | ||
181 | +#include "gstrfuncsprivate.h" | ||
182 | #include "gtimer.h" | ||
183 | #include "gslice.h" | ||
184 | #include "gspawn.h" | ||
185 | @@ -3803,7 +3804,7 @@ g_test_log_extract (GTestLogBuffer *tbuf | ||
186 | if (p <= tbuffer->data->str + mlength) | ||
187 | { | ||
188 | g_string_erase (tbuffer->data, 0, mlength); | ||
189 | - tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg))); | ||
190 | + tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg))); | ||
191 | return TRUE; | ||
192 | } | ||
193 | |||
194 | --- a/glib/gvariant.c | ||
195 | +++ b/glib/gvariant.c | ||
196 | @@ -33,6 +33,7 @@ | ||
197 | |||
198 | #include <string.h> | ||
199 | |||
200 | +#include "gstrfuncsprivate.h" | ||
201 | |||
202 | /** | ||
203 | * SECTION:gvariant | ||
204 | @@ -725,7 +726,7 @@ g_variant_new_variant (GVariant *value) | ||
205 | g_variant_ref_sink (value); | ||
206 | |||
207 | return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT, | ||
208 | - g_memdup (&value, sizeof value), | ||
209 | + g_memdup2 (&value, sizeof value), | ||
210 | 1, g_variant_is_trusted (value)); | ||
211 | } | ||
212 | |||
213 | @@ -1229,7 +1230,7 @@ g_variant_new_fixed_array (const GVarian | ||
214 | return NULL; | ||
215 | } | ||
216 | |||
217 | - data = g_memdup (elements, n_elements * element_size); | ||
218 | + data = g_memdup2 (elements, n_elements * element_size); | ||
219 | value = g_variant_new_from_data (array_type, data, | ||
220 | n_elements * element_size, | ||
221 | FALSE, g_free, data); | ||
222 | @@ -1908,7 +1909,7 @@ g_variant_dup_bytestring (GVariant *valu | ||
223 | if (length) | ||
224 | *length = size; | ||
225 | |||
226 | - return g_memdup (original, size + 1); | ||
227 | + return g_memdup2 (original, size + 1); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | --- a/glib/gvarianttype.c | ||
232 | +++ b/glib/gvarianttype.c | ||
233 | @@ -28,6 +28,7 @@ | ||
234 | |||
235 | #include <string.h> | ||
236 | |||
237 | +#include "gstrfuncsprivate.h" | ||
238 | |||
239 | /** | ||
240 | * SECTION:gvarianttype | ||
241 | @@ -1181,7 +1182,7 @@ g_variant_type_new_tuple (const GVariant | ||
242 | g_assert (offset < sizeof buffer); | ||
243 | buffer[offset++] = ')'; | ||
244 | |||
245 | - return (GVariantType *) g_memdup (buffer, offset); | ||
246 | + return (GVariantType *) g_memdup2 (buffer, offset); | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | --- a/glib/tests/array-test.c | ||
251 | +++ b/glib/tests/array-test.c | ||
252 | @@ -29,6 +29,8 @@ | ||
253 | #include <string.h> | ||
254 | #include "glib.h" | ||
255 | |||
256 | +#include "gstrfuncsprivate.h" | ||
257 | + | ||
258 | /* Test data to be passed to any function which calls g_array_new(), providing | ||
259 | * the parameters for that call. Most #GArray tests should be repeated for all | ||
260 | * possible values of #ArrayTestData. */ | ||
261 | @@ -1917,7 +1919,7 @@ byte_array_new_take (void) | ||
262 | GByteArray *gbarray; | ||
263 | guint8 *data; | ||
264 | |||
265 | - data = g_memdup ("woooweeewow", 11); | ||
266 | + data = g_memdup2 ("woooweeewow", 11); | ||
267 | gbarray = g_byte_array_new_take (data, 11); | ||
268 | g_assert (gbarray->data == data); | ||
269 | g_assert_cmpuint (gbarray->len, ==, 11); | ||
270 | --- a/glib/tests/option-context.c | ||
271 | +++ b/glib/tests/option-context.c | ||
272 | @@ -27,6 +27,8 @@ | ||
273 | #include <string.h> | ||
274 | #include <locale.h> | ||
275 | |||
276 | +#include "gstrfuncsprivate.h" | ||
277 | + | ||
278 | static GOptionEntry main_entries[] = { | ||
279 | { "main-switch", 0, 0, | ||
280 | G_OPTION_ARG_NONE, NULL, | ||
281 | @@ -256,7 +258,7 @@ join_stringv (int argc, char **argv) | ||
282 | static char ** | ||
283 | copy_stringv (char **argv, int argc) | ||
284 | { | ||
285 | - return g_memdup (argv, sizeof (char *) * (argc + 1)); | ||
286 | + return g_memdup2 (argv, sizeof (char *) * (argc + 1)); | ||
287 | } | ||
288 | |||
289 | static void | ||
290 | @@ -2323,7 +2325,7 @@ test_group_parse (void) | ||
291 | g_option_context_add_group (context, group); | ||
292 | |||
293 | argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc); | ||
294 | - orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *)); | ||
295 | + orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *)); | ||
296 | |||
297 | retval = g_option_context_parse (context, &argc, &argv, &error); | ||
298 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch new file mode 100644 index 0000000000..4f86522d00 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch | |||
@@ -0,0 +1,54 @@ | |||
1 | From 0cbad673215ec8a049b7fe2ff44b0beed31b376e Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 16:12:24 +0000 | ||
4 | Subject: [PATCH 05/11] gwinhttpfile: Avoid arithmetic overflow when | ||
5 | calculating a size | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=UTF-8 | ||
8 | Content-Transfer-Encoding: 8bit | ||
9 | |||
10 | The members of `URL_COMPONENTS` (`winhttp_file->url`) are `DWORD`s, i.e. | ||
11 | 32-bit unsigned integers. Adding to and multiplying them may cause them | ||
12 | to overflow the unsigned integer bounds, even if the result is passed to | ||
13 | `g_memdup2()` which accepts a `gsize`. | ||
14 | |||
15 | Cast the `URL_COMPONENTS` members to `gsize` first to ensure that the | ||
16 | arithmetic is done in terms of `gsize`s rather than unsigned integers. | ||
17 | |||
18 | Spotted by Sebastian Dröge. | ||
19 | |||
20 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
21 | Helps: #2319 | ||
22 | |||
23 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
24 | CVE: CVE-2021-27219 | ||
25 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
26 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
27 | |||
28 | --- | ||
29 | gio/win32/gwinhttpfile.c | 8 ++++---- | ||
30 | 1 file changed, 4 insertions(+), 4 deletions(-) | ||
31 | |||
32 | diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c | ||
33 | index 3f8fbd838..e0340e247 100644 | ||
34 | --- a/gio/win32/gwinhttpfile.c | ||
35 | +++ b/gio/win32/gwinhttpfile.c | ||
36 | @@ -410,10 +410,10 @@ g_winhttp_file_resolve_relative_path (GFile *file, | ||
37 | child = g_object_new (G_TYPE_WINHTTP_FILE, NULL); | ||
38 | child->vfs = winhttp_file->vfs; | ||
39 | child->url = winhttp_file->url; | ||
40 | - child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); | ||
41 | - child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); | ||
42 | - child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); | ||
43 | - child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); | ||
44 | + child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2); | ||
45 | + child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2); | ||
46 | + child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2); | ||
47 | + child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2); | ||
48 | child->url.lpszUrlPath = wnew_path; | ||
49 | child->url.dwUrlPathLength = wcslen (wnew_path); | ||
50 | child->url.lpszExtraInfo = NULL; | ||
51 | -- | ||
52 | GitLab | ||
53 | |||
54 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch new file mode 100644 index 0000000000..d8043f5e29 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch | |||
@@ -0,0 +1,101 @@ | |||
1 | From f9ee2275cbc312c0b4cdbc338a4fbb76eb36fb9a Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 13:49:00 +0000 | ||
4 | Subject: [PATCH 06/11] gdatainputstream: Handle stop_chars_len internally as | ||
5 | gsize | ||
6 | |||
7 | Previously it was handled as a `gssize`, which meant that if the | ||
8 | `stop_chars` string was longer than `G_MAXSSIZE` there would be an | ||
9 | overflow. | ||
10 | |||
11 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
12 | Helps: #2319 | ||
13 | |||
14 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
15 | CVE: CVE-2021-27219 | ||
16 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
17 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
18 | |||
19 | --- | ||
20 | gio/gdatainputstream.c | 25 +++++++++++++++++-------- | ||
21 | 1 file changed, 17 insertions(+), 8 deletions(-) | ||
22 | |||
23 | diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c | ||
24 | index 2e7750cb5..2cdcbda19 100644 | ||
25 | --- a/gio/gdatainputstream.c | ||
26 | +++ b/gio/gdatainputstream.c | ||
27 | @@ -27,6 +27,7 @@ | ||
28 | #include "gioenumtypes.h" | ||
29 | #include "gioerror.h" | ||
30 | #include "glibintl.h" | ||
31 | +#include "gstrfuncsprivate.h" | ||
32 | |||
33 | #include <string.h> | ||
34 | |||
35 | @@ -856,7 +857,7 @@ static gssize | ||
36 | scan_for_chars (GDataInputStream *stream, | ||
37 | gsize *checked_out, | ||
38 | const char *stop_chars, | ||
39 | - gssize stop_chars_len) | ||
40 | + gsize stop_chars_len) | ||
41 | { | ||
42 | GBufferedInputStream *bstream; | ||
43 | const char *buffer; | ||
44 | @@ -952,7 +953,7 @@ typedef struct | ||
45 | gsize checked; | ||
46 | |||
47 | gchar *stop_chars; | ||
48 | - gssize stop_chars_len; | ||
49 | + gsize stop_chars_len; | ||
50 | gsize length; | ||
51 | } GDataInputStreamReadData; | ||
52 | |||
53 | @@ -1078,12 +1079,17 @@ g_data_input_stream_read_async (GDataInputStream *stream, | ||
54 | { | ||
55 | GDataInputStreamReadData *data; | ||
56 | GTask *task; | ||
57 | + gsize stop_chars_len_unsigned; | ||
58 | |||
59 | data = g_slice_new0 (GDataInputStreamReadData); | ||
60 | - if (stop_chars_len == -1) | ||
61 | - stop_chars_len = strlen (stop_chars); | ||
62 | - data->stop_chars = g_memdup (stop_chars, stop_chars_len); | ||
63 | - data->stop_chars_len = stop_chars_len; | ||
64 | + | ||
65 | + if (stop_chars_len < 0) | ||
66 | + stop_chars_len_unsigned = strlen (stop_chars); | ||
67 | + else | ||
68 | + stop_chars_len_unsigned = (gsize) stop_chars_len; | ||
69 | + | ||
70 | + data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned); | ||
71 | + data->stop_chars_len = stop_chars_len_unsigned; | ||
72 | data->last_saw_cr = FALSE; | ||
73 | |||
74 | task = g_task_new (stream, cancellable, callback, user_data); | ||
75 | @@ -1338,17 +1344,20 @@ g_data_input_stream_read_upto (GDataInputStream *stream, | ||
76 | gssize found_pos; | ||
77 | gssize res; | ||
78 | char *data_until; | ||
79 | + gsize stop_chars_len_unsigned; | ||
80 | |||
81 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); | ||
82 | |||
83 | if (stop_chars_len < 0) | ||
84 | - stop_chars_len = strlen (stop_chars); | ||
85 | + stop_chars_len_unsigned = strlen (stop_chars); | ||
86 | + else | ||
87 | + stop_chars_len_unsigned = (gsize) stop_chars_len; | ||
88 | |||
89 | bstream = G_BUFFERED_INPUT_STREAM (stream); | ||
90 | |||
91 | checked = 0; | ||
92 | |||
93 | - while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1) | ||
94 | + while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1) | ||
95 | { | ||
96 | if (g_buffered_input_stream_get_available (bstream) == | ||
97 | g_buffered_input_stream_get_buffer_size (bstream)) | ||
98 | -- | ||
99 | GitLab | ||
100 | |||
101 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch new file mode 100644 index 0000000000..f183939c45 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch | |||
@@ -0,0 +1,76 @@ | |||
1 | From 2aaf593a9eb96d84fe3be740aca2810a97d95592 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 13:50:37 +0000 | ||
4 | Subject: [PATCH 07/11] gwin32: Use gsize internally in g_wcsdup() | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | This allows it to handle strings up to length `G_MAXSIZE` — previously | ||
10 | it would overflow with such strings. | ||
11 | |||
12 | Update the several copies of it identically. | ||
13 | |||
14 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
15 | Helps: #2319 | ||
16 | |||
17 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
18 | CVE: CVE-2021-27219 | ||
19 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
20 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
21 | |||
22 | --- | ||
23 | gio/gwin32registrykey.c | 34 ++++++++++++++++++++++++++-------- | ||
24 | 2 files changed, 38 insertions(+), 16 deletions(-) | ||
25 | |||
26 | diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c | ||
27 | index 548a94188..2eb67daf8 100644 | ||
28 | --- a/gio/gwin32registrykey.c | ||
29 | +++ b/gio/gwin32registrykey.c | ||
30 | @@ -127,16 +127,34 @@ typedef enum | ||
31 | G_WIN32_REGISTRY_UPDATED_PATH = 1, | ||
32 | } GWin32RegistryKeyUpdateFlag; | ||
33 | |||
34 | +static gsize | ||
35 | +g_utf16_len (const gunichar2 *str) | ||
36 | +{ | ||
37 | + gsize result; | ||
38 | + | ||
39 | + for (result = 0; str[0] != 0; str++, result++) | ||
40 | + ; | ||
41 | + | ||
42 | + return result; | ||
43 | +} | ||
44 | + | ||
45 | static gunichar2 * | ||
46 | -g_wcsdup (const gunichar2 *str, | ||
47 | - gssize str_size) | ||
48 | +g_wcsdup (const gunichar2 *str, gssize str_len) | ||
49 | { | ||
50 | - if (str_size == -1) | ||
51 | - { | ||
52 | - str_size = wcslen (str) + 1; | ||
53 | - str_size *= sizeof (gunichar2); | ||
54 | - } | ||
55 | - return g_memdup (str, str_size); | ||
56 | + gsize str_len_unsigned; | ||
57 | + gsize str_size; | ||
58 | + | ||
59 | + g_return_val_if_fail (str != NULL, NULL); | ||
60 | + | ||
61 | + if (str_len < 0) | ||
62 | + str_len_unsigned = g_utf16_len (str); | ||
63 | + else | ||
64 | + str_len_unsigned = (gsize) str_len; | ||
65 | + | ||
66 | + g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); | ||
67 | + str_size = (str_len_unsigned + 1) * sizeof (gunichar2); | ||
68 | + | ||
69 | + return g_memdup2 (str, str_size); | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | -- | ||
74 | GitLab | ||
75 | |||
76 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch new file mode 100644 index 0000000000..ffafc35c07 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch | |||
@@ -0,0 +1,101 @@ | |||
1 | From ba8ca443051f93a74c0d03d62e70402036f967a5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 13:58:32 +0000 | ||
4 | Subject: [PATCH 08/11] gkeyfilesettingsbackend: Handle long keys when | ||
5 | converting paths | ||
6 | |||
7 | Previously, the code in `convert_path()` could not handle keys longer | ||
8 | than `G_MAXINT`, and would overflow if that was exceeded. | ||
9 | |||
10 | Convert the code to use `gsize` and `g_memdup2()` throughout, and | ||
11 | change from identifying the position of the final slash in the string | ||
12 | using a signed offset `i`, to using a pointer to the character (and | ||
13 | `strrchr()`). This allows the slash to be at any position in a | ||
14 | `G_MAXSIZE`-long string, without sacrificing a bit of the offset for | ||
15 | indicating whether a slash was found. | ||
16 | |||
17 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
18 | Helps: #2319 | ||
19 | |||
20 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
21 | CVE: CVE-2021-27219 | ||
22 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
23 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
24 | |||
25 | --- | ||
26 | gio/gkeyfilesettingsbackend.c | 21 ++++++++++----------- | ||
27 | 1 file changed, 10 insertions(+), 11 deletions(-) | ||
28 | |||
29 | diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c | ||
30 | index cd5765afd..25b057672 100644 | ||
31 | --- a/gio/gkeyfilesettingsbackend.c | ||
32 | +++ b/gio/gkeyfilesettingsbackend.c | ||
33 | @@ -33,6 +33,7 @@ | ||
34 | #include "gfilemonitor.h" | ||
35 | #include "gsimplepermission.h" | ||
36 | #include "gsettingsbackendinternal.h" | ||
37 | +#include "gstrfuncsprivate.h" | ||
38 | #include "giomodule-priv.h" | ||
39 | #include "gportalsupport.h" | ||
40 | |||
41 | @@ -145,8 +146,8 @@ convert_path (GKeyfileSettingsBackend *kfsb, | ||
42 | gchar **group, | ||
43 | gchar **basename) | ||
44 | { | ||
45 | - gint key_len = strlen (key); | ||
46 | - gint i; | ||
47 | + gsize key_len = strlen (key); | ||
48 | + const gchar *last_slash; | ||
49 | |||
50 | if (key_len < kfsb->prefix_len || | ||
51 | memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0) | ||
52 | @@ -155,38 +156,36 @@ convert_path (GKeyfileSettingsBackend *kfsb, | ||
53 | key_len -= kfsb->prefix_len; | ||
54 | key += kfsb->prefix_len; | ||
55 | |||
56 | - for (i = key_len; i >= 0; i--) | ||
57 | - if (key[i] == '/') | ||
58 | - break; | ||
59 | + last_slash = strrchr (key, '/'); | ||
60 | |||
61 | if (kfsb->root_group) | ||
62 | { | ||
63 | /* if a root_group was specified, make sure the user hasn't given | ||
64 | * a path that ghosts that group name | ||
65 | */ | ||
66 | - if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0) | ||
67 | + if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0) | ||
68 | return FALSE; | ||
69 | } | ||
70 | else | ||
71 | { | ||
72 | /* if no root_group was given, ensure that the user gave a path */ | ||
73 | - if (i == -1) | ||
74 | + if (last_slash == NULL) | ||
75 | return FALSE; | ||
76 | } | ||
77 | |||
78 | if (group) | ||
79 | { | ||
80 | - if (i >= 0) | ||
81 | + if (last_slash != NULL) | ||
82 | { | ||
83 | - *group = g_memdup (key, i + 1); | ||
84 | - (*group)[i] = '\0'; | ||
85 | + *group = g_memdup2 (key, (last_slash - key) + 1); | ||
86 | + (*group)[(last_slash - key)] = '\0'; | ||
87 | } | ||
88 | else | ||
89 | *group = g_strdup (kfsb->root_group); | ||
90 | } | ||
91 | |||
92 | if (basename) | ||
93 | - *basename = g_memdup (key + i + 1, key_len - i); | ||
94 | + *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); | ||
95 | |||
96 | return TRUE; | ||
97 | } | ||
98 | -- | ||
99 | GitLab | ||
100 | |||
101 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch new file mode 100644 index 0000000000..8efb7c720f --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch | |||
@@ -0,0 +1,100 @@ | |||
1 | From 65ec7f4d6e8832c481f6e00e2eb007b9a60024ce Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 14:00:53 +0000 | ||
4 | Subject: [PATCH 09/11] =?UTF-8?q?gsocket:=20Use=20gsize=20to=20track=20nat?= | ||
5 | =?UTF-8?q?ive=20sockaddr=E2=80=99s=20size?= | ||
6 | MIME-Version: 1.0 | ||
7 | Content-Type: text/plain; charset=UTF-8 | ||
8 | Content-Transfer-Encoding: 8bit | ||
9 | |||
10 | Don’t use an `int`, that’s potentially too small. In practical terms, | ||
11 | this is not a problem, since no socket address is going to be that big. | ||
12 | |||
13 | By making these changes we can use `g_memdup2()` without warnings, | ||
14 | though. Fewer warnings is good. | ||
15 | |||
16 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
17 | Helps: #2319 | ||
18 | |||
19 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
20 | CVE: CVE-2021-27219 | ||
21 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
22 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
23 | |||
24 | --- | ||
25 | gio/gsocket.c | 16 ++++++++++------ | ||
26 | 1 file changed, 10 insertions(+), 6 deletions(-) | ||
27 | |||
28 | --- a/gio/gsocket.c | ||
29 | +++ b/gio/gsocket.c | ||
30 | @@ -75,6 +75,7 @@ | ||
31 | #include "gcredentialsprivate.h" | ||
32 | #include "glibintl.h" | ||
33 | #include "gioprivate.h" | ||
34 | +#include "gstrfuncsprivate.h" | ||
35 | |||
36 | #ifdef G_OS_WIN32 | ||
37 | /* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */ | ||
38 | @@ -174,7 +175,7 @@ static gboolean g_socket_datagram_ba | ||
39 | GError **error); | ||
40 | |||
41 | static GSocketAddress * | ||
42 | -cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len); | ||
43 | +cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len); | ||
44 | |||
45 | static gssize | ||
46 | g_socket_receive_message_with_timeout (GSocket *socket, | ||
47 | @@ -260,7 +261,7 @@ struct _GSocketPrivate | ||
48 | struct { | ||
49 | GSocketAddress *addr; | ||
50 | struct sockaddr *native; | ||
51 | - gint native_len; | ||
52 | + gsize native_len; | ||
53 | guint64 last_used; | ||
54 | } recv_addr_cache[RECV_ADDR_CACHE_SIZE]; | ||
55 | }; | ||
56 | @@ -5259,14 +5260,14 @@ g_socket_send_messages_with_timeout (GSo | ||
57 | } | ||
58 | |||
59 | static GSocketAddress * | ||
60 | -cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) | ||
61 | +cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len) | ||
62 | { | ||
63 | GSocketAddress *saddr; | ||
64 | gint i; | ||
65 | guint64 oldest_time = G_MAXUINT64; | ||
66 | gint oldest_index = 0; | ||
67 | |||
68 | - if (native_len <= 0) | ||
69 | + if (native_len == 0) | ||
70 | return NULL; | ||
71 | |||
72 | saddr = NULL; | ||
73 | @@ -5274,7 +5275,7 @@ cache_recv_address (GSocket *socket, str | ||
74 | { | ||
75 | GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr; | ||
76 | gpointer tmp_native = socket->priv->recv_addr_cache[i].native; | ||
77 | - gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len; | ||
78 | + gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len; | ||
79 | |||
80 | if (!tmp) | ||
81 | continue; | ||
82 | @@ -5304,7 +5305,7 @@ cache_recv_address (GSocket *socket, str | ||
83 | g_free (socket->priv->recv_addr_cache[oldest_index].native); | ||
84 | } | ||
85 | |||
86 | - socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len); | ||
87 | + socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len); | ||
88 | socket->priv->recv_addr_cache[oldest_index].native_len = native_len; | ||
89 | socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr); | ||
90 | socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time (); | ||
91 | @@ -5452,6 +5453,9 @@ g_socket_receive_message_with_timeout (G | ||
92 | /* do it */ | ||
93 | while (1) | ||
94 | { | ||
95 | + /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */ | ||
96 | + G_STATIC_ASSERT (sizeof addr <= G_MAXINT); | ||
97 | + | ||
98 | addrlen = sizeof addr; | ||
99 | if (address) | ||
100 | result = WSARecvFrom (socket->priv->fd, | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch new file mode 100644 index 0000000000..63fda0b600 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch | |||
@@ -0,0 +1,59 @@ | |||
1 | From 777b95a88f006d39d9fe6d3321db17e7b0d4b9a4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 14:07:39 +0000 | ||
4 | Subject: [PATCH 10/11] gtlspassword: Forbid very long TLS passwords | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | The public API `g_tls_password_set_value_full()` (and the vfunc it | ||
10 | invokes) can only accept a `gssize` length. Ensure that nul-terminated | ||
11 | strings passed to `g_tls_password_set_value()` can’t exceed that length. | ||
12 | Use `g_memdup2()` to avoid an overflow if they’re longer than | ||
13 | `G_MAXUINT` similarly. | ||
14 | |||
15 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
16 | Helps: #2319 | ||
17 | |||
18 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
19 | CVE: CVE-2021-27219 | ||
20 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
21 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
22 | |||
23 | --- | ||
24 | gio/gtlspassword.c | 10 ++++++++-- | ||
25 | 1 file changed, 8 insertions(+), 2 deletions(-) | ||
26 | |||
27 | diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c | ||
28 | index 1e437a7b6..dbcec41a8 100644 | ||
29 | --- a/gio/gtlspassword.c | ||
30 | +++ b/gio/gtlspassword.c | ||
31 | @@ -23,6 +23,7 @@ | ||
32 | #include "glibintl.h" | ||
33 | |||
34 | #include "gioenumtypes.h" | ||
35 | +#include "gstrfuncsprivate.h" | ||
36 | #include "gtlspassword.h" | ||
37 | |||
38 | #include <string.h> | ||
39 | @@ -287,9 +288,14 @@ g_tls_password_set_value (GTlsPassword *password, | ||
40 | g_return_if_fail (G_IS_TLS_PASSWORD (password)); | ||
41 | |||
42 | if (length < 0) | ||
43 | - length = strlen ((gchar *)value); | ||
44 | + { | ||
45 | + /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ | ||
46 | + gsize length_unsigned = strlen ((gchar *) value); | ||
47 | + g_return_if_fail (length_unsigned > G_MAXSSIZE); | ||
48 | + length = (gssize) length_unsigned; | ||
49 | + } | ||
50 | |||
51 | - g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free); | ||
52 | + g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | -- | ||
57 | GitLab | ||
58 | |||
59 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch new file mode 100644 index 0000000000..a620a49269 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch | |||
@@ -0,0 +1,63 @@ | |||
1 | From ecdf91400e9a538695a0895b95ad7e8abcdf1749 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Thu, 4 Feb 2021 14:09:40 +0000 | ||
4 | Subject: [PATCH 11/11] giochannel: Forbid very long line terminator strings | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | The public API `GIOChannel.line_term_len` is only a `guint`. Ensure that | ||
10 | nul-terminated strings passed to `g_io_channel_set_line_term()` can’t | ||
11 | exceed that length. Use `g_memdup2()` to avoid a warning (`g_memdup()` | ||
12 | is due to be deprecated), but not to avoid a bug, since it’s also | ||
13 | limited to `G_MAXUINT`. | ||
14 | |||
15 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
16 | Helps: #2319 | ||
17 | |||
18 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
19 | CVE: CVE-2021-27219 | ||
20 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
21 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
22 | |||
23 | --- | ||
24 | glib/giochannel.c | 17 +++++++++++++---- | ||
25 | 1 file changed, 13 insertions(+), 4 deletions(-) | ||
26 | |||
27 | diff --git a/glib/giochannel.c b/glib/giochannel.c | ||
28 | index c6a89d6e0..4dec20f77 100644 | ||
29 | --- a/glib/giochannel.c | ||
30 | +++ b/glib/giochannel.c | ||
31 | @@ -887,16 +887,25 @@ g_io_channel_set_line_term (GIOChannel *channel, | ||
32 | const gchar *line_term, | ||
33 | gint length) | ||
34 | { | ||
35 | + guint length_unsigned; | ||
36 | + | ||
37 | g_return_if_fail (channel != NULL); | ||
38 | g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */ | ||
39 | |||
40 | if (line_term == NULL) | ||
41 | - length = 0; | ||
42 | - else if (length < 0) | ||
43 | - length = strlen (line_term); | ||
44 | + length_unsigned = 0; | ||
45 | + else if (length >= 0) | ||
46 | + length_unsigned = (guint) length; | ||
47 | + else | ||
48 | + { | ||
49 | + /* FIXME: We’re constrained by line_term_len being a guint here */ | ||
50 | + gsize length_size = strlen (line_term); | ||
51 | + g_return_if_fail (length_size > G_MAXUINT); | ||
52 | + length_unsigned = (guint) length_size; | ||
53 | + } | ||
54 | |||
55 | g_free (channel->line_term); | ||
56 | - channel->line_term = line_term ? g_memdup (line_term, length) : NULL; | ||
57 | + channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL; | ||
58 | channel->line_term_len = length; | ||
59 | } | ||
60 | |||
61 | -- | ||
62 | GitLab | ||
63 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch new file mode 100644 index 0000000000..3047062f54 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch | |||
@@ -0,0 +1,36 @@ | |||
1 | From f8273b9aded135fe07094faebd527e43851aaf6e Mon Sep 17 00:00:00 2001 | ||
2 | From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com> | ||
3 | Date: Sun, 7 Feb 2021 23:32:40 +0100 | ||
4 | Subject: [PATCH 1/5] giochannel: Fix length_size bounds check | ||
5 | |||
6 | The inverted condition is an obvious error introduced by ecdf91400e9a. | ||
7 | |||
8 | Fixes https://gitlab.gnome.org/GNOME/glib/-/issues/2323 | ||
9 | |||
10 | (cherry picked from commit a149bf2f9030168051942124536e303af8ba6176) | ||
11 | |||
12 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
13 | CVE: CVE-2021-27219 | ||
14 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
15 | |||
16 | --- | ||
17 | glib/giochannel.c | 2 +- | ||
18 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
19 | |||
20 | diff --git a/glib/giochannel.c b/glib/giochannel.c | ||
21 | index 4dec20f77..c3f3102ff 100644 | ||
22 | --- a/glib/giochannel.c | ||
23 | +++ b/glib/giochannel.c | ||
24 | @@ -896,7 +896,7 @@ g_io_channel_set_line_term (GIOChannel *channel, | ||
25 | { | ||
26 | /* FIXME: We’re constrained by line_term_len being a guint here */ | ||
27 | gsize length_size = strlen (line_term); | ||
28 | - g_return_if_fail (length_size > G_MAXUINT); | ||
29 | + g_return_if_fail (length_size <= G_MAXUINT); | ||
30 | length_unsigned = (guint) length_size; | ||
31 | } | ||
32 | |||
33 | -- | ||
34 | GitLab | ||
35 | |||
36 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch new file mode 100644 index 0000000000..2ba26075df --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch | |||
@@ -0,0 +1,38 @@ | |||
1 | From e069c50467712e6d607822afd6b6c15c2c343dff Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon McVittie <smcv@collabora.com> | ||
3 | Date: Mon, 8 Feb 2021 10:34:50 +0000 | ||
4 | Subject: [PATCH 2/5] giochannel: Don't store negative line_term_len in | ||
5 | GIOChannel struct | ||
6 | |||
7 | Adding test coverage indicated that this was another bug in 0cc11f74. | ||
8 | |||
9 | Fixes: 0cc11f74 "giochannel: Forbid very long line terminator strings" | ||
10 | Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2323 | ||
11 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
12 | (cherry picked from commit 5dc8b0014c03e7491d93b90275ab442e888a9628) | ||
13 | |||
14 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
15 | CVE: CVE-2021-27219 | ||
16 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
17 | |||
18 | --- | ||
19 | glib/giochannel.c | 2 +- | ||
20 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
21 | |||
22 | diff --git a/glib/giochannel.c b/glib/giochannel.c | ||
23 | index c3f3102ff..19bb06ba6 100644 | ||
24 | --- a/glib/giochannel.c | ||
25 | +++ b/glib/giochannel.c | ||
26 | @@ -902,7 +902,7 @@ g_io_channel_set_line_term (GIOChannel *channel, | ||
27 | |||
28 | g_free (channel->line_term); | ||
29 | channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL; | ||
30 | - channel->line_term_len = length; | ||
31 | + channel->line_term_len = length_unsigned; | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | -- | ||
36 | GitLab | ||
37 | |||
38 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch new file mode 100644 index 0000000000..2c388b4bbb --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch | |||
@@ -0,0 +1,38 @@ | |||
1 | From 4506d1859a863087598c8d122740bae25b65b099 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon McVittie <smcv@collabora.com> | ||
3 | Date: Mon, 8 Feb 2021 10:04:48 +0000 | ||
4 | Subject: [PATCH 4/5] gtlspassword: Fix inverted assertion | ||
5 | |||
6 | The intention here was to assert that the length of the password fits | ||
7 | in a gssize. Passwords more than half the size of virtual memory are | ||
8 | probably excessive. | ||
9 | |||
10 | Fixes: a8b204ff "gtlspassword: Forbid very long TLS passwords" | ||
11 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
12 | (cherry picked from commit 61bb52ec42de1082bfb06ce1c737fc295bfe60b8) | ||
13 | |||
14 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
15 | CVE: CVE-2021-27219 | ||
16 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
17 | |||
18 | --- | ||
19 | gio/gtlspassword.c | 2 +- | ||
20 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
21 | |||
22 | diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c | ||
23 | index dbcec41a8..bd86a6dfe 100644 | ||
24 | --- a/gio/gtlspassword.c | ||
25 | +++ b/gio/gtlspassword.c | ||
26 | @@ -291,7 +291,7 @@ g_tls_password_set_value (GTlsPassword *password, | ||
27 | { | ||
28 | /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ | ||
29 | gsize length_unsigned = strlen ((gchar *) value); | ||
30 | - g_return_if_fail (length_unsigned > G_MAXSSIZE); | ||
31 | + g_return_if_fail (length_unsigned <= G_MAXSSIZE); | ||
32 | length = (gssize) length_unsigned; | ||
33 | } | ||
34 | |||
35 | -- | ||
36 | GitLab | ||
37 | |||
38 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch new file mode 100644 index 0000000000..356e986fe0 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch | |||
@@ -0,0 +1,100 @@ | |||
1 | From 3d1550354c3c6a8491c39881752d51cb7515f2c2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Simon McVittie <smcv@collabora.com> | ||
3 | Date: Mon, 8 Feb 2021 10:22:39 +0000 | ||
4 | Subject: [PATCH 5/5] tls-interaction: Add test coverage for various ways to | ||
5 | set the password | ||
6 | |||
7 | Signed-off-by: Simon McVittie <smcv@collabora.com> | ||
8 | (cherry picked from commit df4501316ca3903072400504a5ea76498db19538) | ||
9 | |||
10 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
11 | CVE: CVE-2021-27219 | ||
12 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
13 | |||
14 | --- | ||
15 | gio/tests/tls-interaction.c | 55 +++++++++++++++++++++++++++++++++++++ | ||
16 | 1 file changed, 55 insertions(+) | ||
17 | |||
18 | diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c | ||
19 | index 4f0737d7e..5661e8e0d 100644 | ||
20 | --- a/gio/tests/tls-interaction.c | ||
21 | +++ b/gio/tests/tls-interaction.c | ||
22 | @@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction, | ||
23 | } | ||
24 | |||
25 | |||
26 | +/* Return a copy of @str that is allocated in a silly way, to exercise | ||
27 | + * custom free-functions. The returned pointer points to a copy of @str | ||
28 | + * in a buffer of the form "BEFORE \0 str \0 AFTER". */ | ||
29 | +static guchar * | ||
30 | +special_dup (const char *str) | ||
31 | +{ | ||
32 | + GString *buf = g_string_new ("BEFORE"); | ||
33 | + guchar *ret; | ||
34 | + | ||
35 | + g_string_append_c (buf, '\0'); | ||
36 | + g_string_append (buf, str); | ||
37 | + g_string_append_c (buf, '\0'); | ||
38 | + g_string_append (buf, "AFTER"); | ||
39 | + ret = (guchar *) g_string_free (buf, FALSE); | ||
40 | + return ret + strlen ("BEFORE") + 1; | ||
41 | +} | ||
42 | + | ||
43 | + | ||
44 | +/* Free a copy of @str that was made with special_dup(), after asserting | ||
45 | + * that it has not been corrupted. */ | ||
46 | +static void | ||
47 | +special_free (gpointer p) | ||
48 | +{ | ||
49 | + gchar *s = p; | ||
50 | + gchar *buf = s - strlen ("BEFORE") - 1; | ||
51 | + | ||
52 | + g_assert_cmpstr (buf, ==, "BEFORE"); | ||
53 | + g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER"); | ||
54 | + g_free (buf); | ||
55 | +} | ||
56 | + | ||
57 | + | ||
58 | static GTlsInteractionResult | ||
59 | test_interaction_ask_password_sync_success (GTlsInteraction *interaction, | ||
60 | GTlsPassword *password, | ||
61 | @@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, | ||
62 | GError **error) | ||
63 | { | ||
64 | TestInteraction *self; | ||
65 | + const guchar *value; | ||
66 | + gsize len; | ||
67 | |||
68 | g_assert (TEST_IS_INTERACTION (interaction)); | ||
69 | self = TEST_INTERACTION (interaction); | ||
70 | @@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, | ||
71 | g_assert (error != NULL); | ||
72 | g_assert (*error == NULL); | ||
73 | |||
74 | + /* Exercise different ways to set the value */ | ||
75 | + g_tls_password_set_value (password, (const guchar *) "foo", 4); | ||
76 | + len = 0; | ||
77 | + value = g_tls_password_get_value (password, &len); | ||
78 | + g_assert_cmpmem (value, len, "foo", 4); | ||
79 | + | ||
80 | + g_tls_password_set_value (password, (const guchar *) "bar", -1); | ||
81 | + len = 0; | ||
82 | + value = g_tls_password_get_value (password, &len); | ||
83 | + g_assert_cmpmem (value, len, "bar", 3); | ||
84 | + | ||
85 | + g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free); | ||
86 | + len = 0; | ||
87 | + value = g_tls_password_get_value (password, &len); | ||
88 | + g_assert_cmpmem (value, len, "baa", 4); | ||
89 | + | ||
90 | + g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free); | ||
91 | + len = 0; | ||
92 | + value = g_tls_password_get_value (password, &len); | ||
93 | + g_assert_cmpmem (value, len, "baz", 3); | ||
94 | + | ||
95 | /* Don't do this in real life. Include a null terminator for testing */ | ||
96 | g_tls_password_set_value (password, (const guchar *)"the password", 13); | ||
97 | return G_TLS_INTERACTION_HANDLED; | ||
98 | -- | ||
99 | GitLab | ||
100 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch new file mode 100644 index 0000000000..dd43689aae --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch | |||
@@ -0,0 +1,49 @@ | |||
1 | From cb9ee701ef46c1819eed4e2a4dc181682bdfc176 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 10 Feb 2021 21:16:39 +0000 | ||
4 | Subject: [PATCH 1/3] gkeyfilesettingsbackend: Fix basename handling when group | ||
5 | is unset | ||
6 | |||
7 | Fix an effective regression in commit | ||
8 | 7781a9cbd2fd0aa84bee0f4eee88470640ff6706, which happens when | ||
9 | `convert_path()` is called with a `key` which contains no slashes. In | ||
10 | that case, the `key` is entirely the `basename`. | ||
11 | |||
12 | Prior to commit 7781a9cb, the code worked through a fluke of `i == -1` | ||
13 | cancelling out with the various additions in the `g_memdup()` call, and | ||
14 | effectively resulting in `g_strdup (key)`. | ||
15 | |||
16 | Spotted by Guido Berhoerster. | ||
17 | |||
18 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
19 | |||
20 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
21 | CVE: CVE-2021-27219 | ||
22 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
23 | |||
24 | --- | ||
25 | gio/gkeyfilesettingsbackend.c | 7 ++++++- | ||
26 | 1 file changed, 6 insertions(+), 1 deletion(-) | ||
27 | |||
28 | diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c | ||
29 | index 25b057672..861c3a661 100644 | ||
30 | --- a/gio/gkeyfilesettingsbackend.c | ||
31 | +++ b/gio/gkeyfilesettingsbackend.c | ||
32 | @@ -185,7 +185,12 @@ convert_path (GKeyfileSettingsBackend *kfsb, | ||
33 | } | ||
34 | |||
35 | if (basename) | ||
36 | - *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); | ||
37 | + { | ||
38 | + if (last_slash != NULL) | ||
39 | + *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); | ||
40 | + else | ||
41 | + *basename = g_strdup (key); | ||
42 | + } | ||
43 | |||
44 | return TRUE; | ||
45 | } | ||
46 | -- | ||
47 | GitLab | ||
48 | |||
49 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch new file mode 100644 index 0000000000..04503641c3 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch | |||
@@ -0,0 +1,43 @@ | |||
1 | From 31e0d403ba635dbbacbfbff74295e5db02558d76 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 10 Feb 2021 21:19:30 +0000 | ||
4 | Subject: [PATCH 2/3] gkeyfilesettingsbackend: Disallow empty key or group | ||
5 | names | ||
6 | |||
7 | These should never have been allowed; they will result in precondition | ||
8 | failures from the `GKeyFile` later on in the code. | ||
9 | |||
10 | A test will be added for this shortly. | ||
11 | |||
12 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
13 | |||
14 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
15 | CVE: CVE-2021-27219 | ||
16 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
17 | |||
18 | --- | ||
19 | gio/gkeyfilesettingsbackend.c | 7 +++++++ | ||
20 | 1 file changed, 7 insertions(+) | ||
21 | |||
22 | diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c | ||
23 | index 861c3a661..de216e615 100644 | ||
24 | --- a/gio/gkeyfilesettingsbackend.c | ||
25 | +++ b/gio/gkeyfilesettingsbackend.c | ||
26 | @@ -158,6 +158,13 @@ convert_path (GKeyfileSettingsBackend *kfsb, | ||
27 | |||
28 | last_slash = strrchr (key, '/'); | ||
29 | |||
30 | + /* Disallow empty group names or key names */ | ||
31 | + if (key_len == 0 || | ||
32 | + (last_slash != NULL && | ||
33 | + (*(last_slash + 1) == '\0' || | ||
34 | + last_slash == key))) | ||
35 | + return FALSE; | ||
36 | + | ||
37 | if (kfsb->root_group) | ||
38 | { | ||
39 | /* if a root_group was specified, make sure the user hasn't given | ||
40 | -- | ||
41 | GitLab | ||
42 | |||
43 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch new file mode 100644 index 0000000000..65f59287a8 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch | |||
@@ -0,0 +1,232 @@ | |||
1 | Backport of: | ||
2 | |||
3 | From 221c26685354dea2b2732df94404e8e5e77a1591 Mon Sep 17 00:00:00 2001 | ||
4 | From: Philip Withnall <pwithnall@endlessos.org> | ||
5 | Date: Wed, 10 Feb 2021 21:21:36 +0000 | ||
6 | Subject: [PATCH 3/3] tests: Add tests for key name handling in the keyfile | ||
7 | backend | ||
8 | |||
9 | This tests the two recent commits. | ||
10 | |||
11 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
12 | |||
13 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
14 | CVE: CVE-2021-27219 | ||
15 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
16 | |||
17 | --- | ||
18 | gio/tests/gsettings.c | 170 +++++++++++++++++++++++++++++++++++++++++- | ||
19 | 1 file changed, 169 insertions(+), 1 deletion(-) | ||
20 | |||
21 | --- a/gio/tests/gsettings.c | ||
22 | +++ b/gio/tests/gsettings.c | ||
23 | @@ -1,3 +1,4 @@ | ||
24 | +#include <errno.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <locale.h> | ||
27 | #include <libintl.h> | ||
28 | @@ -1740,6 +1741,14 @@ key_changed_cb (GSettings *settings, con | ||
29 | (*b) = TRUE; | ||
30 | } | ||
31 | |||
32 | +typedef struct | ||
33 | +{ | ||
34 | + const gchar *path; | ||
35 | + const gchar *root_group; | ||
36 | + const gchar *keyfile_group; | ||
37 | + const gchar *root_path; | ||
38 | +} KeyfileTestData; | ||
39 | + | ||
40 | /* | ||
41 | * Test that using a keyfile works | ||
42 | */ | ||
43 | @@ -1834,7 +1843,11 @@ test_keyfile (Fixture *fixture, | ||
44 | g_free (str); | ||
45 | |||
46 | g_settings_set (settings, "farewell", "s", "cheerio"); | ||
47 | - | ||
48 | + | ||
49 | + /* Check that empty keys/groups are not allowed. */ | ||
50 | + g_assert_false (g_settings_is_writable (settings, "")); | ||
51 | + g_assert_false (g_settings_is_writable (settings, "/")); | ||
52 | + | ||
53 | /* When executing as root, changing the mode of the keyfile will have | ||
54 | * no effect on the writability of the settings. | ||
55 | */ | ||
56 | @@ -1866,6 +1879,149 @@ test_keyfile (Fixture *fixture, | ||
57 | g_free (keyfile_path); | ||
58 | } | ||
59 | |||
60 | +/* | ||
61 | + * Test that using a keyfile works with a schema with no path set. | ||
62 | + */ | ||
63 | +static void | ||
64 | +test_keyfile_no_path (Fixture *fixture, | ||
65 | + gconstpointer user_data) | ||
66 | +{ | ||
67 | + const KeyfileTestData *test_data = user_data; | ||
68 | + GSettingsBackend *kf_backend; | ||
69 | + GSettings *settings; | ||
70 | + GKeyFile *keyfile; | ||
71 | + gboolean writable; | ||
72 | + gchar *key = NULL; | ||
73 | + GError *error = NULL; | ||
74 | + gchar *keyfile_path = NULL, *store_path = NULL; | ||
75 | + | ||
76 | + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); | ||
77 | + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); | ||
78 | + kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group); | ||
79 | + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path); | ||
80 | + g_object_unref (kf_backend); | ||
81 | + | ||
82 | + g_settings_reset (settings, "test-boolean"); | ||
83 | + g_assert_true (g_settings_get_boolean (settings, "test-boolean")); | ||
84 | + | ||
85 | + writable = g_settings_is_writable (settings, "test-boolean"); | ||
86 | + g_assert_true (writable); | ||
87 | + g_settings_set (settings, "test-boolean", "b", FALSE); | ||
88 | + | ||
89 | + g_assert_false (g_settings_get_boolean (settings, "test-boolean")); | ||
90 | + | ||
91 | + g_settings_delay (settings); | ||
92 | + g_settings_set (settings, "test-boolean", "b", TRUE); | ||
93 | + g_settings_apply (settings); | ||
94 | + | ||
95 | + keyfile = g_key_file_new (); | ||
96 | + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); | ||
97 | + | ||
98 | + g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL)); | ||
99 | + | ||
100 | + g_key_file_free (keyfile); | ||
101 | + | ||
102 | + g_settings_reset (settings, "test-boolean"); | ||
103 | + g_settings_apply (settings); | ||
104 | + keyfile = g_key_file_new (); | ||
105 | + g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); | ||
106 | + | ||
107 | + g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error)); | ||
108 | + g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); | ||
109 | + g_clear_error (&error); | ||
110 | + | ||
111 | + /* Check that empty keys/groups are not allowed. */ | ||
112 | + g_assert_false (g_settings_is_writable (settings, "")); | ||
113 | + g_assert_false (g_settings_is_writable (settings, "/")); | ||
114 | + | ||
115 | + /* Keys which ghost the root group name are not allowed. This can only be | ||
116 | + * tested when the path is `/` as otherwise it acts as a prefix and prevents | ||
117 | + * any ghosting. */ | ||
118 | + if (g_str_equal (test_data->path, "/")) | ||
119 | + { | ||
120 | + key = g_strdup_printf ("%s/%s", test_data->root_group, ""); | ||
121 | + g_assert_false (g_settings_is_writable (settings, key)); | ||
122 | + g_free (key); | ||
123 | + | ||
124 | + key = g_strdup_printf ("%s/%s", test_data->root_group, "/"); | ||
125 | + g_assert_false (g_settings_is_writable (settings, key)); | ||
126 | + g_free (key); | ||
127 | + | ||
128 | + key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean"); | ||
129 | + g_assert_false (g_settings_is_writable (settings, key)); | ||
130 | + g_free (key); | ||
131 | + } | ||
132 | + | ||
133 | + g_key_file_free (keyfile); | ||
134 | + g_object_unref (settings); | ||
135 | + | ||
136 | + /* Clean up the temporary directory. */ | ||
137 | + g_assert_cmpint (g_chmod (keyfile_path, 0777) == 0 ? 0 : errno, ==, 0); | ||
138 | + g_assert_cmpint (g_remove (store_path) == 0 ? 0 : errno, ==, 0); | ||
139 | + g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); | ||
140 | + g_free (store_path); | ||
141 | + g_free (keyfile_path); | ||
142 | +} | ||
143 | + | ||
144 | +/* | ||
145 | + * Test that a keyfile rejects writes to keys outside its root path. | ||
146 | + */ | ||
147 | +static void | ||
148 | +test_keyfile_outside_root_path (Fixture *fixture, | ||
149 | + gconstpointer user_data) | ||
150 | +{ | ||
151 | + GSettingsBackend *kf_backend; | ||
152 | + GSettings *settings; | ||
153 | + gchar *keyfile_path = NULL, *store_path = NULL; | ||
154 | + | ||
155 | + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); | ||
156 | + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); | ||
157 | + kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root"); | ||
158 | + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/"); | ||
159 | + g_object_unref (kf_backend); | ||
160 | + | ||
161 | + g_assert_false (g_settings_is_writable (settings, "test-boolean")); | ||
162 | + | ||
163 | + g_object_unref (settings); | ||
164 | + | ||
165 | + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so | ||
166 | + * don’t error on failure. */ | ||
167 | + g_remove (store_path); | ||
168 | + g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); | ||
169 | + g_free (store_path); | ||
170 | + g_free (keyfile_path); | ||
171 | +} | ||
172 | + | ||
173 | +/* | ||
174 | + * Test that a keyfile rejects writes to keys in the root if no root group is set. | ||
175 | + */ | ||
176 | +static void | ||
177 | +test_keyfile_no_root_group (Fixture *fixture, | ||
178 | + gconstpointer user_data) | ||
179 | +{ | ||
180 | + GSettingsBackend *kf_backend; | ||
181 | + GSettings *settings; | ||
182 | + gchar *keyfile_path = NULL, *store_path = NULL; | ||
183 | + | ||
184 | + keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); | ||
185 | + store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); | ||
186 | + kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL); | ||
187 | + settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/"); | ||
188 | + g_object_unref (kf_backend); | ||
189 | + | ||
190 | + g_assert_false (g_settings_is_writable (settings, "test-boolean")); | ||
191 | + g_assert_true (g_settings_is_writable (settings, "child/test-boolean")); | ||
192 | + | ||
193 | + g_object_unref (settings); | ||
194 | + | ||
195 | + /* Clean up the temporary directory. The keyfile probably doesn’t exist, so | ||
196 | + * don’t error on failure. */ | ||
197 | + g_remove (store_path); | ||
198 | + g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); | ||
199 | + g_free (store_path); | ||
200 | + g_free (keyfile_path); | ||
201 | +} | ||
202 | + | ||
203 | /* Test that getting child schemas works | ||
204 | */ | ||
205 | static void | ||
206 | @@ -2844,6 +3000,14 @@ main (int argc, char *argv[]) | ||
207 | gchar *override_text; | ||
208 | gchar *enums; | ||
209 | gint result; | ||
210 | + const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" }; | ||
211 | + const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" }; | ||
212 | + const KeyfileTestData keyfile_test_data_long_path = { | ||
213 | + "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/", | ||
214 | + "root", | ||
215 | + "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch", | ||
216 | + "/" | ||
217 | + }; | ||
218 | |||
219 | /* Meson build sets this */ | ||
220 | #ifdef TEST_LOCALE_PATH | ||
221 | @@ -2967,6 +3131,11 @@ main (int argc, char *argv[]) | ||
222 | } | ||
223 | |||
224 | g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown); | ||
225 | + g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown); | ||
226 | + g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown); | ||
227 | + g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown); | ||
228 | + g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown); | ||
229 | + g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown); | ||
230 | g_test_add_func ("/gsettings/child-schema", test_child_schema); | ||
231 | g_test_add_func ("/gsettings/strinfo", test_strinfo); | ||
232 | g_test_add_func ("/gsettings/enums", test_enums); | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch new file mode 100644 index 0000000000..c89ca20726 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch | |||
@@ -0,0 +1,27 @@ | |||
1 | From 78420a75aeb70569a8cd79fa0fea7b786b6f785f Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 24 Feb 2021 17:33:38 +0000 | ||
4 | Subject: [PATCH 1/5] glocalfileoutputstream: Fix a typo in a comment | ||
5 | |||
6 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
7 | |||
8 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
9 | CVE: CVE-2021-28153 | ||
10 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
11 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
12 | |||
13 | --- | ||
14 | gio/glocalfileoutputstream.c | 2 +- | ||
15 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
16 | |||
17 | --- a/gio/glocalfileoutputstream.c | ||
18 | +++ b/gio/glocalfileoutputstream.c | ||
19 | @@ -851,7 +851,7 @@ handle_overwrite_open (const char *fi | ||
20 | mode = mode_from_flags_or_info (flags, reference_info); | ||
21 | |||
22 | /* We only need read access to the original file if we are creating a backup. | ||
23 | - * We also add O_CREATE to avoid a race if the file was just removed */ | ||
24 | + * We also add O_CREAT to avoid a race if the file was just removed */ | ||
25 | if (create_backup || readable) | ||
26 | open_flags = O_RDWR | O_CREAT | O_BINARY; | ||
27 | else | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch new file mode 100644 index 0000000000..8a35bab4de --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch | |||
@@ -0,0 +1,42 @@ | |||
1 | From 32d3d02a50e7dcec5f4cf7908e7ac88d575d8fc5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 24 Feb 2021 17:34:32 +0000 | ||
4 | Subject: [PATCH 2/5] tests: Stop using g_test_bug_base() in file tests | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | Since a following commit is going to add a new test which references | ||
10 | Gitlab, so it’s best to move the URI bases inside the test cases. | ||
11 | |||
12 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
13 | |||
14 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
15 | CVE: CVE-2021-28153 | ||
16 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
17 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
18 | |||
19 | --- | ||
20 | gio/tests/file.c | 4 +--- | ||
21 | 1 file changed, 1 insertion(+), 3 deletions(-) | ||
22 | |||
23 | --- a/gio/tests/file.c | ||
24 | +++ b/gio/tests/file.c | ||
25 | @@ -685,7 +685,7 @@ test_replace_cancel (void) | ||
26 | guint count; | ||
27 | GError *error = NULL; | ||
28 | |||
29 | - g_test_bug ("629301"); | ||
30 | + g_test_bug ("https://bugzilla.gnome.org/629301"); | ||
31 | |||
32 | path = g_dir_make_tmp ("g_file_replace_cancel_XXXXXX", &error); | ||
33 | g_assert_no_error (error); | ||
34 | @@ -1784,8 +1784,6 @@ main (int argc, char *argv[]) | ||
35 | { | ||
36 | g_test_init (&argc, &argv, NULL); | ||
37 | |||
38 | - g_test_bug_base ("http://bugzilla.gnome.org/"); | ||
39 | - | ||
40 | g_test_add_func ("/file/basic", test_basic); | ||
41 | g_test_add_func ("/file/build-filename", test_build_filename); | ||
42 | g_test_add_func ("/file/parent", test_parent); | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch new file mode 100644 index 0000000000..a82febd26e --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch | |||
@@ -0,0 +1,57 @@ | |||
1 | Backport of: | ||
2 | |||
3 | From ce0eb088a68171eed3ac217cb92a72e36eb57d1b Mon Sep 17 00:00:00 2001 | ||
4 | From: Philip Withnall <pwithnall@endlessos.org> | ||
5 | Date: Wed, 10 Mar 2021 16:05:55 +0000 | ||
6 | Subject: [PATCH 3/5] glocalfileoutputstream: Factor out a flag check | ||
7 | |||
8 | This clarifies the code a little. It introduces no functional changes. | ||
9 | |||
10 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
11 | |||
12 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
13 | CVE: CVE-2021-28153 | ||
14 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
15 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
16 | |||
17 | --- | ||
18 | gio/glocalfileoutputstream.c | 7 ++++--- | ||
19 | 1 file changed, 4 insertions(+), 3 deletions(-) | ||
20 | |||
21 | --- a/gio/glocalfileoutputstream.c | ||
22 | +++ b/gio/glocalfileoutputstream.c | ||
23 | @@ -847,6 +847,7 @@ handle_overwrite_open (const char *fi | ||
24 | int res; | ||
25 | int mode; | ||
26 | int errsv; | ||
27 | + gboolean replace_destination_set = (flags & G_FILE_CREATE_REPLACE_DESTINATION); | ||
28 | |||
29 | mode = mode_from_flags_or_info (flags, reference_info); | ||
30 | |||
31 | @@ -954,7 +955,7 @@ handle_overwrite_open (const char *fi | ||
32 | * to a backup file and rewrite the contents of the file. | ||
33 | */ | ||
34 | |||
35 | - if ((flags & G_FILE_CREATE_REPLACE_DESTINATION) || | ||
36 | + if (replace_destination_set || | ||
37 | (!(original_stat.st_nlink > 1) && !is_symlink)) | ||
38 | { | ||
39 | char *dirname, *tmp_filename; | ||
40 | @@ -973,7 +974,7 @@ handle_overwrite_open (const char *fi | ||
41 | |||
42 | /* try to keep permissions (unless replacing) */ | ||
43 | |||
44 | - if ( ! (flags & G_FILE_CREATE_REPLACE_DESTINATION) && | ||
45 | + if (!replace_destination_set && | ||
46 | ( | ||
47 | #ifdef HAVE_FCHOWN | ||
48 | fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 || | ||
49 | @@ -1112,7 +1113,7 @@ handle_overwrite_open (const char *fi | ||
50 | } | ||
51 | } | ||
52 | |||
53 | - if (flags & G_FILE_CREATE_REPLACE_DESTINATION) | ||
54 | + if (replace_destination_set) | ||
55 | { | ||
56 | g_close (fd, NULL); | ||
57 | |||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch new file mode 100644 index 0000000000..5b106e8474 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch | |||
@@ -0,0 +1,265 @@ | |||
1 | Backport of: | ||
2 | |||
3 | From 317b3b587058a05dca95d56dac26568c5b098d33 Mon Sep 17 00:00:00 2001 | ||
4 | From: Philip Withnall <pwithnall@endlessos.org> | ||
5 | Date: Wed, 24 Feb 2021 17:36:07 +0000 | ||
6 | Subject: [PATCH 4/5] glocalfileoutputstream: Fix CREATE_REPLACE_DESTINATION | ||
7 | with symlinks | ||
8 | MIME-Version: 1.0 | ||
9 | Content-Type: text/plain; charset=UTF-8 | ||
10 | Content-Transfer-Encoding: 8bit | ||
11 | |||
12 | The `G_FILE_CREATE_REPLACE_DESTINATION` flag is equivalent to unlinking | ||
13 | the destination file and re-creating it from scratch. That did | ||
14 | previously work, but in the process the code would call `open(O_CREAT)` | ||
15 | on the file. If the file was a dangling symlink, this would create the | ||
16 | destination file (empty). That’s not an intended side-effect, and has | ||
17 | security implications if the symlink is controlled by a lower-privileged | ||
18 | process. | ||
19 | |||
20 | Fix that by not opening the destination file if it’s a symlink, and | ||
21 | adjusting the rest of the code to cope with | ||
22 | - the fact that `fd == -1` is not an error iff `is_symlink` is true, | ||
23 | - and that `original_stat` will contain the `lstat()` results for the | ||
24 | symlink now, rather than the `stat()` results for its target (again, | ||
25 | iff `is_symlink` is true). | ||
26 | |||
27 | This means that the target of the dangling symlink is no longer created, | ||
28 | which was the bug. The symlink itself continues to be replaced (as | ||
29 | before) with the new file — this is the intended behaviour of | ||
30 | `g_file_replace()`. | ||
31 | |||
32 | The behaviour for non-symlink cases, or cases where the symlink was not | ||
33 | dangling, should be unchanged. | ||
34 | |||
35 | Includes a unit test. | ||
36 | |||
37 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
38 | |||
39 | Fixes: #2325 | ||
40 | |||
41 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
42 | CVE: CVE-2021-28153 | ||
43 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
44 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
45 | |||
46 | --- | ||
47 | gio/glocalfileoutputstream.c | 77 ++++++++++++++++++------- | ||
48 | gio/tests/file.c | 108 +++++++++++++++++++++++++++++++++++ | ||
49 | 2 files changed, 163 insertions(+), 22 deletions(-) | ||
50 | |||
51 | --- a/gio/glocalfileoutputstream.c | ||
52 | +++ b/gio/glocalfileoutputstream.c | ||
53 | @@ -875,16 +875,22 @@ handle_overwrite_open (const char *fi | ||
54 | /* Could be a symlink, or it could be a regular ELOOP error, | ||
55 | * but then the next open will fail too. */ | ||
56 | is_symlink = TRUE; | ||
57 | - fd = g_open (filename, open_flags, mode); | ||
58 | + if (!replace_destination_set) | ||
59 | + fd = g_open (filename, open_flags, mode); | ||
60 | } | ||
61 | -#else | ||
62 | - fd = g_open (filename, open_flags, mode); | ||
63 | - errsv = errno; | ||
64 | +#else /* if !O_NOFOLLOW */ | ||
65 | /* This is racy, but we do it as soon as possible to minimize the race */ | ||
66 | is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK); | ||
67 | + | ||
68 | + if (!is_symlink || !replace_destination_set) | ||
69 | + { | ||
70 | + fd = g_open (filename, open_flags, mode); | ||
71 | + errsv = errno; | ||
72 | + } | ||
73 | #endif | ||
74 | |||
75 | - if (fd == -1) | ||
76 | + if (fd == -1 && | ||
77 | + (!is_symlink || !replace_destination_set)) | ||
78 | { | ||
79 | char *display_name = g_filename_display_name (filename); | ||
80 | g_set_error (error, G_IO_ERROR, | ||
81 | @@ -898,7 +904,14 @@ handle_overwrite_open (const char *fi | ||
82 | #ifdef G_OS_WIN32 | ||
83 | res = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &original_stat); | ||
84 | #else | ||
85 | - res = fstat (fd, &original_stat); | ||
86 | + if (!is_symlink) | ||
87 | + { | ||
88 | + res = fstat (fd, &original_stat); | ||
89 | + } | ||
90 | + else | ||
91 | + { | ||
92 | + res = lstat (filename, &original_stat); | ||
93 | + } | ||
94 | #endif | ||
95 | errsv = errno; | ||
96 | |||
97 | @@ -917,16 +930,27 @@ handle_overwrite_open (const char *fi | ||
98 | if (!S_ISREG (original_stat.st_mode)) | ||
99 | { | ||
100 | if (S_ISDIR (original_stat.st_mode)) | ||
101 | - g_set_error_literal (error, | ||
102 | - G_IO_ERROR, | ||
103 | - G_IO_ERROR_IS_DIRECTORY, | ||
104 | - _("Target file is a directory")); | ||
105 | - else | ||
106 | - g_set_error_literal (error, | ||
107 | + { | ||
108 | + g_set_error_literal (error, | ||
109 | + G_IO_ERROR, | ||
110 | + G_IO_ERROR_IS_DIRECTORY, | ||
111 | + _("Target file is a directory")); | ||
112 | + goto err_out; | ||
113 | + } | ||
114 | + else if (!is_symlink || | ||
115 | +#ifdef S_ISLNK | ||
116 | + !S_ISLNK (original_stat.st_mode) | ||
117 | +#else | ||
118 | + FALSE | ||
119 | +#endif | ||
120 | + ) | ||
121 | + { | ||
122 | + g_set_error_literal (error, | ||
123 | G_IO_ERROR, | ||
124 | G_IO_ERROR_NOT_REGULAR_FILE, | ||
125 | _("Target file is not a regular file")); | ||
126 | - goto err_out; | ||
127 | + goto err_out; | ||
128 | + } | ||
129 | } | ||
130 | |||
131 | if (etag != NULL) | ||
132 | @@ -1007,7 +1031,8 @@ handle_overwrite_open (const char *fi | ||
133 | } | ||
134 | } | ||
135 | |||
136 | - g_close (fd, NULL); | ||
137 | + if (fd >= 0) | ||
138 | + g_close (fd, NULL); | ||
139 | *temp_filename = tmp_filename; | ||
140 | return tmpfd; | ||
141 | } | ||
142 | --- a/gio/tests/file.c | ||
143 | +++ b/gio/tests/file.c | ||
144 | @@ -804,6 +804,113 @@ test_replace_cancel (void) | ||
145 | g_object_unref (tmpdir); | ||
146 | } | ||
147 | |||
148 | +static void | ||
149 | +test_replace_symlink (void) | ||
150 | +{ | ||
151 | +#ifdef G_OS_UNIX | ||
152 | + gchar *tmpdir_path = NULL; | ||
153 | + GFile *tmpdir = NULL, *source_file = NULL, *target_file = NULL; | ||
154 | + GFileOutputStream *stream = NULL; | ||
155 | + const gchar *new_contents = "this is a test message which should be written to source and not target"; | ||
156 | + gsize n_written; | ||
157 | + GFileEnumerator *enumerator = NULL; | ||
158 | + GFileInfo *info = NULL; | ||
159 | + gchar *contents = NULL; | ||
160 | + gsize length = 0; | ||
161 | + GError *local_error = NULL; | ||
162 | + | ||
163 | + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2325"); | ||
164 | + g_test_summary ("Test that G_FILE_CREATE_REPLACE_DESTINATION doesn’t follow symlinks"); | ||
165 | + | ||
166 | + /* Create a fresh, empty working directory. */ | ||
167 | + tmpdir_path = g_dir_make_tmp ("g_file_replace_symlink_XXXXXX", &local_error); | ||
168 | + g_assert_no_error (local_error); | ||
169 | + tmpdir = g_file_new_for_path (tmpdir_path); | ||
170 | + | ||
171 | + g_test_message ("Using temporary directory %s", tmpdir_path); | ||
172 | + g_free (tmpdir_path); | ||
173 | + | ||
174 | + /* Create symlink `source` which points to `target`. */ | ||
175 | + source_file = g_file_get_child (tmpdir, "source"); | ||
176 | + target_file = g_file_get_child (tmpdir, "target"); | ||
177 | + g_file_make_symbolic_link (source_file, "target", NULL, &local_error); | ||
178 | + g_assert_no_error (local_error); | ||
179 | + | ||
180 | + /* Ensure that `target` doesn’t exist */ | ||
181 | + g_assert_false (g_file_query_exists (target_file, NULL)); | ||
182 | + | ||
183 | + /* Replace the `source` symlink with a regular file using | ||
184 | + * %G_FILE_CREATE_REPLACE_DESTINATION, which should replace it *without* | ||
185 | + * following the symlink */ | ||
186 | + stream = g_file_replace (source_file, NULL, FALSE /* no backup */, | ||
187 | + G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error); | ||
188 | + g_assert_no_error (local_error); | ||
189 | + | ||
190 | + g_output_stream_write_all (G_OUTPUT_STREAM (stream), new_contents, strlen (new_contents), | ||
191 | + &n_written, NULL, &local_error); | ||
192 | + g_assert_no_error (local_error); | ||
193 | + g_assert_cmpint (n_written, ==, strlen (new_contents)); | ||
194 | + | ||
195 | + g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, &local_error); | ||
196 | + g_assert_no_error (local_error); | ||
197 | + | ||
198 | + g_clear_object (&stream); | ||
199 | + | ||
200 | + /* At this point, there should still only be one file: `source`. It should | ||
201 | + * now be a regular file. `target` should not exist. */ | ||
202 | + enumerator = g_file_enumerate_children (tmpdir, | ||
203 | + G_FILE_ATTRIBUTE_STANDARD_NAME "," | ||
204 | + G_FILE_ATTRIBUTE_STANDARD_TYPE, | ||
205 | + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error); | ||
206 | + g_assert_no_error (local_error); | ||
207 | + | ||
208 | + info = g_file_enumerator_next_file (enumerator, NULL, &local_error); | ||
209 | + g_assert_no_error (local_error); | ||
210 | + g_assert_nonnull (info); | ||
211 | + | ||
212 | + g_assert_cmpstr (g_file_info_get_name (info), ==, "source"); | ||
213 | + g_assert_cmpint (g_file_info_get_file_type (info), ==, G_FILE_TYPE_REGULAR); | ||
214 | + | ||
215 | + g_clear_object (&info); | ||
216 | + | ||
217 | + info = g_file_enumerator_next_file (enumerator, NULL, &local_error); | ||
218 | + g_assert_no_error (local_error); | ||
219 | + g_assert_null (info); | ||
220 | + | ||
221 | + g_file_enumerator_close (enumerator, NULL, &local_error); | ||
222 | + g_assert_no_error (local_error); | ||
223 | + g_clear_object (&enumerator); | ||
224 | + | ||
225 | + /* Double-check that `target` doesn’t exist */ | ||
226 | + g_assert_false (g_file_query_exists (target_file, NULL)); | ||
227 | + | ||
228 | + /* Check the content of `source`. */ | ||
229 | + g_file_load_contents (source_file, | ||
230 | + NULL, | ||
231 | + &contents, | ||
232 | + &length, | ||
233 | + NULL, | ||
234 | + &local_error); | ||
235 | + g_assert_no_error (local_error); | ||
236 | + g_assert_cmpstr (contents, ==, new_contents); | ||
237 | + g_assert_cmpuint (length, ==, strlen (new_contents)); | ||
238 | + g_free (contents); | ||
239 | + | ||
240 | + /* Tidy up. */ | ||
241 | + g_file_delete (source_file, NULL, &local_error); | ||
242 | + g_assert_no_error (local_error); | ||
243 | + | ||
244 | + g_file_delete (tmpdir, NULL, &local_error); | ||
245 | + g_assert_no_error (local_error); | ||
246 | + | ||
247 | + g_clear_object (&target_file); | ||
248 | + g_clear_object (&source_file); | ||
249 | + g_clear_object (&tmpdir); | ||
250 | +#else /* if !G_OS_UNIX */ | ||
251 | + g_test_skip ("Symlink replacement tests can only be run on Unix") | ||
252 | +#endif | ||
253 | +} | ||
254 | + | ||
255 | static void | ||
256 | on_file_deleted (GObject *object, | ||
257 | GAsyncResult *result, | ||
258 | @@ -1752,6 +1859,7 @@ main (int argc, char *argv[]) | ||
259 | g_test_add_data_func ("/file/async-create-delete/4096", GINT_TO_POINTER (4096), test_create_delete); | ||
260 | g_test_add_func ("/file/replace-load", test_replace_load); | ||
261 | g_test_add_func ("/file/replace-cancel", test_replace_cancel); | ||
262 | + g_test_add_func ("/file/replace-symlink", test_replace_symlink); | ||
263 | g_test_add_func ("/file/async-delete", test_async_delete); | ||
264 | #ifdef G_OS_UNIX | ||
265 | g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode); | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch new file mode 100644 index 0000000000..2334147f7d --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch | |||
@@ -0,0 +1,55 @@ | |||
1 | From 6c6439261bc7a8a0627519848a7222b3e1bd4ffe Mon Sep 17 00:00:00 2001 | ||
2 | From: Philip Withnall <pwithnall@endlessos.org> | ||
3 | Date: Wed, 24 Feb 2021 17:42:24 +0000 | ||
4 | Subject: [PATCH 5/5] glocalfileoutputstream: Add a missing O_CLOEXEC flag to | ||
5 | replace() | ||
6 | |||
7 | Signed-off-by: Philip Withnall <pwithnall@endlessos.org> | ||
8 | |||
9 | Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz] | ||
10 | CVE: CVE-2021-28153 | ||
11 | Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com> | ||
12 | Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> | ||
13 | |||
14 | --- | ||
15 | gio/glocalfileoutputstream.c | 15 ++++++++++++--- | ||
16 | 1 file changed, 12 insertions(+), 3 deletions(-) | ||
17 | |||
18 | --- a/gio/glocalfileoutputstream.c | ||
19 | +++ b/gio/glocalfileoutputstream.c | ||
20 | @@ -58,6 +58,12 @@ | ||
21 | #define O_BINARY 0 | ||
22 | #endif | ||
23 | |||
24 | +#ifndef O_CLOEXEC | ||
25 | +#define O_CLOEXEC 0 | ||
26 | +#else | ||
27 | +#define HAVE_O_CLOEXEC 1 | ||
28 | +#endif | ||
29 | + | ||
30 | struct _GLocalFileOutputStreamPrivate { | ||
31 | char *tmp_filename; | ||
32 | char *original_filename; | ||
33 | @@ -1223,7 +1229,7 @@ _g_local_file_output_stream_replace (con | ||
34 | sync_on_close = FALSE; | ||
35 | |||
36 | /* If the file doesn't exist, create it */ | ||
37 | - open_flags = O_CREAT | O_EXCL | O_BINARY; | ||
38 | + open_flags = O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC; | ||
39 | if (readable) | ||
40 | open_flags |= O_RDWR; | ||
41 | else | ||
42 | @@ -1253,8 +1259,11 @@ _g_local_file_output_stream_replace (con | ||
43 | set_error_from_open_errno (filename, error); | ||
44 | return NULL; | ||
45 | } | ||
46 | - | ||
47 | - | ||
48 | +#if !defined(HAVE_O_CLOEXEC) && defined(F_SETFD) | ||
49 | + else | ||
50 | + fcntl (fd, F_SETFD, FD_CLOEXEC); | ||
51 | +#endif | ||
52 | + | ||
53 | stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL); | ||
54 | stream->priv->fd = fd; | ||
55 | stream->priv->sync_on_close = sync_on_close; | ||
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch new file mode 100644 index 0000000000..ce90586290 --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch | |||
@@ -0,0 +1,290 @@ | |||
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 1a006b9f38..60a6b843c1 100644 --- a/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb +++ b/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb | |||
@@ -18,6 +18,44 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \ | |||
18 | file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ | 18 | file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ |
19 | file://tzdata-update.patch \ | 19 | file://tzdata-update.patch \ |
20 | file://CVE-2020-35457.patch \ | 20 | file://CVE-2020-35457.patch \ |
21 | file://CVE-2021-27218.patch \ | ||
22 | file://CVE-2021-27219-01.patch \ | ||
23 | file://CVE-2021-27219-02.patch \ | ||
24 | file://CVE-2021-27219-03.patch \ | ||
25 | file://CVE-2021-27219-04.patch \ | ||
26 | file://CVE-2021-27219-05.patch \ | ||
27 | file://CVE-2021-27219-06.patch \ | ||
28 | file://CVE-2021-27219-07.patch \ | ||
29 | file://CVE-2021-27219-08.patch \ | ||
30 | file://CVE-2021-27219-09.patch \ | ||
31 | file://CVE-2021-27219-10.patch \ | ||
32 | file://CVE-2021-27219-11.patch \ | ||
33 | file://CVE-2021-27219-reg1-1.patch \ | ||
34 | file://CVE-2021-27219-reg1-2.patch \ | ||
35 | file://CVE-2021-27219-reg1-4.patch \ | ||
36 | file://CVE-2021-27219-reg1-5.patch \ | ||
37 | file://CVE-2021-27219-reg2-1.patch \ | ||
38 | file://CVE-2021-27219-reg2-2.patch \ | ||
39 | file://CVE-2021-27219-reg2-3.patch \ | ||
40 | file://CVE-2021-28153-1.patch \ | ||
41 | file://CVE-2021-28153-2.patch \ | ||
42 | file://CVE-2021-28153-3.patch \ | ||
43 | file://CVE-2021-28153-4.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 \ | ||
21 | " | 59 | " |
22 | 60 | ||
23 | SRC_URI_append_class-native = " file://relocate-modules.patch" | 61 | SRC_URI_append_class-native = " file://relocate-modules.patch" |
diff --git a/meta/recipes-core/glib-2.0/glib.inc b/meta/recipes-core/glib-2.0/glib.inc index c3ddf18387..1849a6e05c 100644 --- a/meta/recipes-core/glib-2.0/glib.inc +++ b/meta/recipes-core/glib-2.0/glib.inc | |||
@@ -4,7 +4,7 @@ HOMEPAGE = "https://developer.gnome.org/glib/" | |||
4 | 4 | ||
5 | # pcre is under BSD; | 5 | # pcre is under BSD; |
6 | # docs/reference/COPYING is with a 'public domain'-like license! | 6 | # docs/reference/COPYING is with a 'public domain'-like license! |
7 | LICENSE = "LGPLv2.1+ & BSD & PD" | 7 | LICENSE = "LGPLv2.1+ & BSD-3-Clause & PD" |
8 | LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \ | 8 | LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \ |
9 | file://glib/glib.h;beginline=4;endline=17;md5=b88abb7f3ad09607e71cb9d530155906 \ | 9 | file://glib/glib.h;beginline=4;endline=17;md5=b88abb7f3ad09607e71cb9d530155906 \ |
10 | file://gmodule/COPYING;md5=4fbd65380cdd255951079008b364516c \ | 10 | file://gmodule/COPYING;md5=4fbd65380cdd255951079008b364516c \ |