summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch')
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p1.patch316
1 files changed, 316 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