summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Kuster <akuster@mvista.com>2019-07-02 09:13:51 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-07-27 18:05:18 +0100
commita51a3b1c82f80e8f7ff24c5090c21961640debf5 (patch)
tree692bb909b5a1f3eff3b96dce550937dc0e9b7603
parente2f3997a84d0d700b0570a0f5d6f17ceffd955c4 (diff)
downloadpoky-a51a3b1c82f80e8f7ff24c5090c21961640debf5.tar.gz
glib: Security fix for CVE-2019-9633
Source: gnome.org MR: 98802 Type: Security Fix Disposition: Backport from https://gitlab.gnome.org/GNOME/glib/commit/d553d92d6e9f53cbe5a34166fcb919ba652c6a8e ChangeID: b73c332f27f47ddc1b1cfd7424f24778acc0c318 Description: includes supporting patch. Fixes CVE-2019-9633 (From OE-Core rev: 3ebf0fc043b6c9b6c2381dab893b54ebcb8ac13d) Signed-off-by: Armin Kuster <akuster@mvista.com> Signed-off-by: Armin Kuster <akuster808@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch316
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p2.patch231
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0_2.58.0.bb2
3 files changed, 549 insertions, 0 deletions
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch
new file mode 100644
index 0000000000..f95716aecf
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch
@@ -0,0 +1,316 @@
1From c1e32b90576af11556c8a9178e43902f3394a4b0 Mon Sep 17 00:00:00 2001
2From: Patrick Griffis <pgriffis@igalia.com>
3Date: Mon, 29 Oct 2018 09:53:07 -0400
4Subject: [PATCH] gsocketclient: Improve handling of slow initial connections
5
6Currently a new connection will not be attempted until the previous
7one has timed out and as the current API only exposes a single
8timeout value in practice it often means that it will wait 30 seconds
9(or forever with 0 (the default)) on each connection.
10
11This is unacceptable so we are now trying to follow the behavior
12RFC 8305 recommends by making multiple connection attempts if
13the connection takes longer than 250ms. The first connection
14to make it to completion then wins.
15
16Upstream-Status: Backport
17CVE: CVE-2019-9633 patch 1
18Affects: < 2.59.2
19Signed-off-by: Armin Kuster <akuster@mvista.com>
20
21---
22 gio/gsocketclient.c | 176 ++++++++++++++++++++++++++++++++++++++++++++--------
23 1 file changed, 151 insertions(+), 25 deletions(-)
24
25diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c
26index ddd1497..5c6513c 100644
27--- a/gio/gsocketclient.c
28+++ b/gio/gsocketclient.c
29@@ -2,6 +2,7 @@
30 *
31 * Copyright © 2008, 2009 codethink
32 * Copyright © 2009 Red Hat, Inc
33+ * Copyright © 2018 Igalia S.L.
34 *
35 * This library is free software; you can redistribute it and/or
36 * modify it under the terms of the GNU Lesser General Public
37@@ -49,6 +50,10 @@
38 #include <gio/ginetaddress.h>
39 #include "glibintl.h"
40
41+/* As recommended by RFC 8305 this is the time it waits
42+ * on a connection before starting another concurrent attempt.
43+ */
44+#define HAPPY_EYEBALLS_CONNECTION_ATTEMPT_TIMEOUT_MS 250
45
46 /**
47 * SECTION:gsocketclient
48@@ -1328,28 +1333,82 @@ typedef struct
49 GSocketConnectable *connectable;
50 GSocketAddressEnumerator *enumerator;
51 GProxyAddress *proxy_addr;
52- GSocketAddress *current_addr;
53- GSocket *current_socket;
54+ GSocket *socket;
55 GIOStream *connection;
56
57+ GSList *connection_attempts;
58 GError *last_error;
59 } GSocketClientAsyncConnectData;
60
61+static void connection_attempt_unref (gpointer attempt);
62+
63 static void
64 g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data)
65 {
66 g_clear_object (&data->connectable);
67 g_clear_object (&data->enumerator);
68 g_clear_object (&data->proxy_addr);
69- g_clear_object (&data->current_addr);
70- g_clear_object (&data->current_socket);
71+ g_clear_object (&data->socket);
72 g_clear_object (&data->connection);
73+ g_slist_free_full (data->connection_attempts, connection_attempt_unref);
74
75 g_clear_error (&data->last_error);
76
77 g_slice_free (GSocketClientAsyncConnectData, data);
78 }
79
80+typedef struct
81+{
82+ GSocketAddress *address;
83+ GSocket *socket;
84+ GIOStream *connection;
85+ GSocketClientAsyncConnectData *data; /* unowned */
86+ GSource *timeout_source;
87+ GCancellable *cancellable;
88+ grefcount ref;
89+} ConnectionAttempt;
90+
91+static ConnectionAttempt *
92+connection_attempt_new (void)
93+{
94+ ConnectionAttempt *attempt = g_new0 (ConnectionAttempt, 1);
95+ g_ref_count_init (&attempt->ref);
96+ return attempt;
97+}
98+
99+static ConnectionAttempt *
100+connection_attempt_ref (ConnectionAttempt *attempt)
101+{
102+ g_ref_count_inc (&attempt->ref);
103+ return attempt;
104+}
105+
106+static void
107+connection_attempt_unref (gpointer pointer)
108+{
109+ ConnectionAttempt *attempt = pointer;
110+ if (g_ref_count_dec (&attempt->ref))
111+ {
112+ g_clear_object (&attempt->address);
113+ g_clear_object (&attempt->socket);
114+ g_clear_object (&attempt->connection);
115+ g_clear_object (&attempt->cancellable);
116+ if (attempt->timeout_source)
117+ {
118+ g_source_destroy (attempt->timeout_source);
119+ g_source_unref (attempt->timeout_source);
120+ }
121+ g_free (attempt);
122+ }
123+}
124+
125+static void
126+connection_attempt_remove (ConnectionAttempt *attempt)
127+{
128+ attempt->data->connection_attempts = g_slist_remove (attempt->data->connection_attempts, attempt);
129+ connection_attempt_unref (attempt);
130+}
131+
132 static void
133 g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
134 {
135@@ -1359,8 +1418,7 @@ g_socket_client_async_connect_complete (GSocketClientAsyncConnectData *data)
136 {
137 GSocketConnection *wrapper_connection;
138
139- wrapper_connection = g_tcp_wrapper_connection_new (data->connection,
140- data->current_socket);
141+ wrapper_connection = g_tcp_wrapper_connection_new (data->connection, data->socket);
142 g_object_unref (data->connection);
143 data->connection = (GIOStream *)wrapper_connection;
144 }
145@@ -1389,8 +1447,7 @@ static void
146 enumerator_next_async (GSocketClientAsyncConnectData *data)
147 {
148 /* We need to cleanup the state */
149- g_clear_object (&data->current_socket);
150- g_clear_object (&data->current_addr);
151+ g_clear_object (&data->socket);
152 g_clear_object (&data->proxy_addr);
153 g_clear_object (&data->connection);
154
155@@ -1485,34 +1542,68 @@ g_socket_client_connected_callback (GObject *source,
156 GAsyncResult *result,
157 gpointer user_data)
158 {
159- GSocketClientAsyncConnectData *data = user_data;
160+ ConnectionAttempt *attempt = user_data;
161+ GSocketClientAsyncConnectData *data = attempt->data;
162+ GSList *l;
163 GError *error = NULL;
164 GProxy *proxy;
165 const gchar *protocol;
166
167- if (g_task_return_error_if_cancelled (data->task))
168+ /* data is NULL once the task is completed */
169+ if (data && g_task_return_error_if_cancelled (data->task))
170 {
171 g_object_unref (data->task);
172+ connection_attempt_unref (attempt);
173 return;
174 }
175
176+ if (attempt->timeout_source)
177+ {
178+ g_source_destroy (attempt->timeout_source);
179+ g_clear_pointer (&attempt->timeout_source, g_source_unref);
180+ }
181+
182 if (!g_socket_connection_connect_finish (G_SOCKET_CONNECTION (source),
183 result, &error))
184 {
185- clarify_connect_error (error, data->connectable,
186- data->current_addr);
187- set_last_error (data, error);
188+ if (!g_cancellable_is_cancelled (attempt->cancellable))
189+ {
190+ clarify_connect_error (error, data->connectable, attempt->address);
191+ set_last_error (data, error);
192+ }
193+ else
194+ g_clear_error (&error);
195+
196+ if (data)
197+ {
198+ connection_attempt_remove (attempt);
199+ enumerator_next_async (data);
200+ }
201+ else
202+ connection_attempt_unref (attempt);
203
204- /* try next one */
205- enumerator_next_async (data);
206 return;
207 }
208
209+ data->socket = g_steal_pointer (&attempt->socket);
210+ data->connection = g_steal_pointer (&attempt->connection);
211+
212+ for (l = data->connection_attempts; l; l = g_slist_next (l))
213+ {
214+ ConnectionAttempt *attempt_entry = l->data;
215+ g_cancellable_cancel (attempt_entry->cancellable);
216+ attempt_entry->data = NULL;
217+ connection_attempt_unref (attempt_entry);
218+ }
219+ g_slist_free (data->connection_attempts);
220+ data->connection_attempts = NULL;
221+ connection_attempt_unref (attempt);
222+
223 g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, NULL);
224 g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTED, data->connectable, data->connection);
225
226 /* wrong, but backward compatible */
227- g_socket_set_blocking (data->current_socket, TRUE);
228+ g_socket_set_blocking (data->socket, TRUE);
229
230 if (!data->proxy_addr)
231 {
232@@ -1565,6 +1656,26 @@ g_socket_client_connected_callback (GObject *source,
233 }
234 }
235
236+static gboolean
237+on_connection_attempt_timeout (gpointer data)
238+{
239+ ConnectionAttempt *attempt = data;
240+
241+ enumerator_next_async (attempt->data);
242+
243+ g_clear_pointer (&attempt->timeout_source, g_source_unref);
244+ return G_SOURCE_REMOVE;
245+}
246+
247+static void
248+on_connection_cancelled (GCancellable *cancellable,
249+ gpointer data)
250+{
251+ GCancellable *attempt_cancellable = data;
252+
253+ g_cancellable_cancel (attempt_cancellable);
254+}
255+
256 static void
257 g_socket_client_enumerator_callback (GObject *object,
258 GAsyncResult *result,
259@@ -1573,6 +1684,7 @@ g_socket_client_enumerator_callback (GObject *object,
260 GSocketClientAsyncConnectData *data = user_data;
261 GSocketAddress *address = NULL;
262 GSocket *socket;
263+ ConnectionAttempt *attempt;
264 GError *error = NULL;
265
266 if (g_task_return_error_if_cancelled (data->task))
267@@ -1585,6 +1697,9 @@ g_socket_client_enumerator_callback (GObject *object,
268 result, &error);
269 if (address == NULL)
270 {
271+ if (data->connection_attempts)
272+ return;
273+
274 g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
275 if (!error)
276 {
277@@ -1621,16 +1736,27 @@ g_socket_client_enumerator_callback (GObject *object,
278 return;
279 }
280
281- data->current_socket = socket;
282- data->current_addr = address;
283- data->connection = (GIOStream *) g_socket_connection_factory_create_connection (socket);
284-
285- g_socket_connection_set_cached_remote_address ((GSocketConnection*)data->connection, address);
286- g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, data->connection);
287- g_socket_connection_connect_async (G_SOCKET_CONNECTION (data->connection),
288+ attempt = connection_attempt_new ();
289+ attempt->data = data;
290+ attempt->socket = socket;
291+ attempt->address = address;
292+ attempt->cancellable = g_cancellable_new ();
293+ attempt->connection = (GIOStream *)g_socket_connection_factory_create_connection (socket);
294+ attempt->timeout_source = g_timeout_source_new (HAPPY_EYEBALLS_CONNECTION_ATTEMPT_TIMEOUT_MS);
295+ g_source_set_callback (attempt->timeout_source, on_connection_attempt_timeout, attempt, NULL);
296+ g_source_attach (attempt->timeout_source, g_main_context_get_thread_default ());
297+ data->connection_attempts = g_slist_append (data->connection_attempts, attempt);
298+
299+ if (g_task_get_cancellable (data->task))
300+ g_cancellable_connect (g_task_get_cancellable (data->task), G_CALLBACK (on_connection_cancelled),
301+ g_object_ref (attempt->cancellable), g_object_unref);
302+
303+ g_socket_connection_set_cached_remote_address ((GSocketConnection *)attempt->connection, address);
304+ g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_CONNECTING, data->connectable, attempt->connection);
305+ g_socket_connection_connect_async (G_SOCKET_CONNECTION (attempt->connection),
306 address,
307- g_task_get_cancellable (data->task),
308- g_socket_client_connected_callback, data);
309+ attempt->cancellable,
310+ g_socket_client_connected_callback, connection_attempt_ref (attempt));
311 }
312
313 /**
314--
3152.7.4
316
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p2.patch
new file mode 100644
index 0000000000..3bb2f5d917
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p2.patch
@@ -0,0 +1,231 @@
1From d553d92d6e9f53cbe5a34166fcb919ba652c6a8e Mon Sep 17 00:00:00 2001
2From: Patrick Griffis <pgriffis@igalia.com>
3Date: Tue, 29 Jan 2019 10:07:06 -0500
4Subject: [PATCH] gsocketclient: Fix criticals
5
6This ensures the parent GTask is kept alive as long as an enumeration
7is running and trying to connect.
8
9Closes #1646
10Closes #1649
11
12Upstream-Status: Backport
13CVE: CVE-2019-9633 patch 2
14Affects: < 2.59.2
15Signed-off-by: Armin Kuster <akuster@mvista.com>
16
17---
18 gio/gsocketclient.c | 74 +++++++++++++++++++++++++++++-------------
19 gio/tests/gsocketclient-slow.c | 55 ++++++++++++++++++++++++++++++-
20 2 files changed, 106 insertions(+), 23 deletions(-)
21
22Index: glib-2.58.0/gio/gsocketclient.c
23===================================================================
24--- glib-2.58.0.orig/gio/gsocketclient.c
25+++ glib-2.58.0/gio/gsocketclient.c
26@@ -1327,7 +1327,7 @@ g_socket_client_connect_to_uri (GSocketC
27
28 typedef struct
29 {
30- GTask *task;
31+ GTask *task; /* unowned */
32 GSocketClient *client;
33
34 GSocketConnectable *connectable;
35@@ -1345,6 +1345,7 @@ static void connection_attempt_unref (gp
36 static void
37 g_socket_client_async_connect_data_free (GSocketClientAsyncConnectData *data)
38 {
39+ data->task = NULL;
40 g_clear_object (&data->connectable);
41 g_clear_object (&data->enumerator);
42 g_clear_object (&data->proxy_addr);
43@@ -1444,13 +1445,19 @@ set_last_error (GSocketClientAsyncConnec
44 }
45
46 static void
47-enumerator_next_async (GSocketClientAsyncConnectData *data)
48+enumerator_next_async (GSocketClientAsyncConnectData *data,
49+ gboolean add_task_ref)
50 {
51 /* We need to cleanup the state */
52 g_clear_object (&data->socket);
53 g_clear_object (&data->proxy_addr);
54 g_clear_object (&data->connection);
55
56+ /* Each enumeration takes a ref. This arg just avoids repeated unrefs when
57+ an enumeration starts another enumeration */
58+ if (add_task_ref)
59+ g_object_ref (data->task);
60+
61 g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_RESOLVING, data->connectable, NULL);
62 g_socket_address_enumerator_next_async (data->enumerator,
63 g_task_get_cancellable (data->task),
64@@ -1478,7 +1485,7 @@ g_socket_client_tls_handshake_callback (
65 else
66 {
67 g_object_unref (object);
68- enumerator_next_async (data);
69+ enumerator_next_async (data, FALSE);
70 }
71 }
72
73@@ -1509,7 +1516,7 @@ g_socket_client_tls_handshake (GSocketCl
74 }
75 else
76 {
77- enumerator_next_async (data);
78+ enumerator_next_async (data, FALSE);
79 }
80 }
81
82@@ -1530,13 +1537,24 @@ g_socket_client_proxy_connect_callback (
83 }
84 else
85 {
86- enumerator_next_async (data);
87+ enumerator_next_async (data, FALSE);
88 return;
89 }
90
91 g_socket_client_tls_handshake (data);
92 }
93
94+static gboolean
95+task_completed_or_cancelled (GTask *task)
96+{
97+ if (g_task_get_completed (task))
98+ return TRUE;
99+ else if (g_task_return_error_if_cancelled (task))
100+ return TRUE;
101+ else
102+ return FALSE;
103+}
104+
105 static void
106 g_socket_client_connected_callback (GObject *source,
107 GAsyncResult *result,
108@@ -1549,8 +1567,7 @@ g_socket_client_connected_callback (GObj
109 GProxy *proxy;
110 const gchar *protocol;
111
112- /* data is NULL once the task is completed */
113- if (data && g_task_return_error_if_cancelled (data->task))
114+ if (g_cancellable_is_cancelled (attempt->cancellable) || task_completed_or_cancelled (data->task))
115 {
116 g_object_unref (data->task);
117 connection_attempt_unref (attempt);
118@@ -1570,17 +1587,15 @@ g_socket_client_connected_callback (GObj
119 {
120 clarify_connect_error (error, data->connectable, attempt->address);
121 set_last_error (data, error);
122+ connection_attempt_remove (attempt);
123+ enumerator_next_async (data, FALSE);
124 }
125 else
126- g_clear_error (&error);
127-
128- if (data)
129 {
130- connection_attempt_remove (attempt);
131- enumerator_next_async (data);
132+ g_clear_error (&error);
133+ g_object_unref (data->task);
134+ connection_attempt_unref (attempt);
135 }
136- else
137- connection_attempt_unref (attempt);
138
139 return;
140 }
141@@ -1592,7 +1607,6 @@ g_socket_client_connected_callback (GObj
142 {
143 ConnectionAttempt *attempt_entry = l->data;
144 g_cancellable_cancel (attempt_entry->cancellable);
145- attempt_entry->data = NULL;
146 connection_attempt_unref (attempt_entry);
147 }
148 g_slist_free (data->connection_attempts);
149@@ -1625,7 +1639,7 @@ g_socket_client_connected_callback (GObj
150 G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
151 _("Proxying over a non-TCP connection is not supported."));
152
153- enumerator_next_async (data);
154+ enumerator_next_async (data, FALSE);
155 }
156 else if (g_hash_table_contains (data->client->priv->app_proxies, protocol))
157 {
158@@ -1652,7 +1666,7 @@ g_socket_client_connected_callback (GObj
159 _("Proxy protocol “%s” is not supported."),
160 protocol);
161
162- enumerator_next_async (data);
163+ enumerator_next_async (data, FALSE);
164 }
165 }
166
167@@ -1661,7 +1675,7 @@ on_connection_attempt_timeout (gpointer
168 {
169 ConnectionAttempt *attempt = data;
170
171- enumerator_next_async (attempt->data);
172+ enumerator_next_async (attempt->data, TRUE);
173
174 g_clear_pointer (&attempt->timeout_source, g_source_unref);
175 return G_SOURCE_REMOVE;
176@@ -1687,7 +1701,7 @@ g_socket_client_enumerator_callback (GOb
177 ConnectionAttempt *attempt;
178 GError *error = NULL;
179
180- if (g_task_return_error_if_cancelled (data->task))
181+ if (task_completed_or_cancelled (data->task))
182 {
183 g_object_unref (data->task);
184 return;
185@@ -1698,7 +1712,10 @@ g_socket_client_enumerator_callback (GOb
186 if (address == NULL)
187 {
188 if (data->connection_attempts)
189- return;
190+ {
191+ g_object_unref (data->task);
192+ return;
193+ }
194
195 g_socket_client_emit_event (data->client, G_SOCKET_CLIENT_COMPLETE, data->connectable, NULL);
196 if (!error)
197@@ -1732,7 +1749,7 @@ g_socket_client_enumerator_callback (GOb
198 if (socket == NULL)
199 {
200 g_object_unref (address);
201- enumerator_next_async (data);
202+ enumerator_next_async (data, FALSE);
203 return;
204 }
205
206@@ -1804,11 +1821,24 @@ g_socket_client_connect_async (GSocketCl
207 else
208 data->enumerator = g_socket_connectable_enumerate (connectable);
209
210+ /* The flow and ownership here isn't quite obvious:
211+ - The task starts an async attempt to connect.
212+ - Each attempt holds a single ref on task.
213+ - Each attempt may create new attempts by timing out (not a failure) so
214+ there are multiple attempts happening in parallel.
215+ - Upon failure an attempt will start a new attempt that steals its ref
216+ until there are no more attempts left and it drops its ref.
217+ - Upon success it will cancel all other attempts and continue on
218+ to the rest of the connection (tls, proxies, etc) which do not
219+ happen in parallel and at the very end drop its ref.
220+ - Upon cancellation an attempt drops its ref.
221+ */
222+
223 data->task = g_task_new (client, cancellable, callback, user_data);
224 g_task_set_source_tag (data->task, g_socket_client_connect_async);
225 g_task_set_task_data (data->task, data, (GDestroyNotify)g_socket_client_async_connect_data_free);
226
227- enumerator_next_async (data);
228+ enumerator_next_async (data, FALSE);
229 }
230
231 /**
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.58.0.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.58.0.bb
index 879bc48aef..f007596968 100644
--- a/meta/recipes-core/glib-2.0/glib-2.0_2.58.0.bb
+++ b/meta/recipes-core/glib-2.0/glib-2.0_2.58.0.bb
@@ -15,6 +15,8 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
15 file://0010-Do-not-hardcode-python-path-into-various-tools.patch \ 15 file://0010-Do-not-hardcode-python-path-into-various-tools.patch \
16 file://date-lt.patch \ 16 file://date-lt.patch \
17 file://CVE-2019-12450.patch \ 17 file://CVE-2019-12450.patch \
18 file://CVE-2019-9633_p1.patch \
19 file://CVE-2019-9633_p2.patch \
18 " 20 "
19 21
20SRC_URI_append_class-native = " file://relocate-modules.patch" 22SRC_URI_append_class-native = " file://relocate-modules.patch"