diff options
| author | Armin Kuster <akuster@mvista.com> | 2019-07-02 09:13:51 -0700 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2019-07-27 18:05:18 +0100 |
| commit | a51a3b1c82f80e8f7ff24c5090c21961640debf5 (patch) | |
| tree | 692bb909b5a1f3eff3b96dce550937dc0e9b7603 | |
| parent | e2f3997a84d0d700b0570a0f5d6f17ceffd955c4 (diff) | |
| download | poky-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>
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 @@ | |||
| 1 | From c1e32b90576af11556c8a9178e43902f3394a4b0 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Patrick Griffis <pgriffis@igalia.com> | ||
| 3 | Date: Mon, 29 Oct 2018 09:53:07 -0400 | ||
| 4 | Subject: [PATCH] gsocketclient: Improve handling of slow initial connections | ||
| 5 | |||
| 6 | Currently a new connection will not be attempted until the previous | ||
| 7 | one has timed out and as the current API only exposes a single | ||
| 8 | timeout value in practice it often means that it will wait 30 seconds | ||
| 9 | (or forever with 0 (the default)) on each connection. | ||
| 10 | |||
| 11 | This is unacceptable so we are now trying to follow the behavior | ||
| 12 | RFC 8305 recommends by making multiple connection attempts if | ||
| 13 | the connection takes longer than 250ms. The first connection | ||
| 14 | to make it to completion then wins. | ||
| 15 | |||
| 16 | Upstream-Status: Backport | ||
| 17 | CVE: CVE-2019-9633 patch 1 | ||
| 18 | Affects: < 2.59.2 | ||
| 19 | Signed-off-by: Armin Kuster <akuster@mvista.com> | ||
| 20 | |||
| 21 | --- | ||
| 22 | gio/gsocketclient.c | 176 ++++++++++++++++++++++++++++++++++++++++++++-------- | ||
| 23 | 1 file changed, 151 insertions(+), 25 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c | ||
| 26 | index 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 | -- | ||
| 315 | 2.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 @@ | |||
| 1 | From d553d92d6e9f53cbe5a34166fcb919ba652c6a8e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Patrick Griffis <pgriffis@igalia.com> | ||
| 3 | Date: Tue, 29 Jan 2019 10:07:06 -0500 | ||
| 4 | Subject: [PATCH] gsocketclient: Fix criticals | ||
| 5 | |||
| 6 | This ensures the parent GTask is kept alive as long as an enumeration | ||
| 7 | is running and trying to connect. | ||
| 8 | |||
| 9 | Closes #1646 | ||
| 10 | Closes #1649 | ||
| 11 | |||
| 12 | Upstream-Status: Backport | ||
| 13 | CVE: CVE-2019-9633 patch 2 | ||
| 14 | Affects: < 2.59.2 | ||
| 15 | Signed-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 | |||
| 22 | Index: 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 | ||
| 20 | SRC_URI_append_class-native = " file://relocate-modules.patch" | 22 | SRC_URI_append_class-native = " file://relocate-modules.patch" |
