diff options
Diffstat (limited to 'meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p2.patch')
-rw-r--r-- | meta/recipes-core/glib-2.0/glib-2.0/CVE-2019-9633_p2.patch | 231 |
1 files changed, 231 insertions, 0 deletions
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 | /** | ||