fix CVE-2021-27219
This commit is contained in:
parent
6f63420c41
commit
3fc1c4e523
792
backport-CVE-2021-27219.patch
Normal file
792
backport-CVE-2021-27219.patch
Normal file
@ -0,0 +1,792 @@
|
||||
From f8cf0b8672209e0b829542e194e302f1de169929 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Thu, 4 Feb 2021 13:30:52 +0000
|
||||
Subject: [PATCH 01/11] gstrfuncs: Add g_memdup2() function
|
||||
|
||||
This will replace the existing `g_memdup()` function, which has an
|
||||
unavoidable security flaw of taking its `byte_size` argument as a
|
||||
`guint` rather than as a `gsize`. Most callers will expect it to be a
|
||||
`gsize`, and may pass in large values which could silently be truncated,
|
||||
resulting in an undersize allocation compared to what the caller
|
||||
expects.
|
||||
|
||||
This could lead to a classic buffer overflow vulnerability for many
|
||||
callers of `g_memdup()`.
|
||||
|
||||
`g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`.
|
||||
|
||||
Spotted by Kevin Backhouse of GHSL.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
Helps: GHSL-2021-045
|
||||
Helps: #2319
|
||||
|
||||
Reference:https://gitlab.gnome.org/GNOME/glib/-/commit/20cfc75d148e3be0c026cc7eff3a9cdb72bf5c56
|
||||
|
||||
diff -Naur a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
|
||||
--- a/docs/reference/glib/glib-sections.txt 2021-03-06 09:46:03.657000000 +0800
|
||||
+++ b/docs/reference/glib/glib-sections.txt 2021-03-05 14:58:36.022000000 +0800
|
||||
@@ -1275,6 +1275,7 @@
|
||||
<SUBSECTION>
|
||||
g_memmove
|
||||
g_memdup
|
||||
+g_memdup2
|
||||
|
||||
<SUBSECTION>
|
||||
GMemVTable
|
||||
diff -Naur a/gio/gdatainputstream.c b/gio/gdatainputstream.c
|
||||
--- a/gio/gdatainputstream.c 2021-03-06 09:46:03.661000000 +0800
|
||||
+++ b/gio/gdatainputstream.c 2021-03-05 15:10:26.335000000 +0800
|
||||
@@ -856,7 +856,7 @@
|
||||
scan_for_chars (GDataInputStream *stream,
|
||||
gsize *checked_out,
|
||||
const char *stop_chars,
|
||||
- gssize stop_chars_len)
|
||||
+ gsize stop_chars_len)
|
||||
{
|
||||
GBufferedInputStream *bstream;
|
||||
const char *buffer;
|
||||
@@ -952,7 +952,7 @@
|
||||
gsize checked;
|
||||
|
||||
gchar *stop_chars;
|
||||
- gssize stop_chars_len;
|
||||
+ gsize stop_chars_len;
|
||||
gsize length;
|
||||
} GDataInputStreamReadData;
|
||||
|
||||
@@ -1078,12 +1078,16 @@
|
||||
{
|
||||
GDataInputStreamReadData *data;
|
||||
GTask *task;
|
||||
+ gsize stop_chars_len_unsigned;
|
||||
|
||||
data = g_slice_new0 (GDataInputStreamReadData);
|
||||
- if (stop_chars_len == -1)
|
||||
- stop_chars_len = strlen (stop_chars);
|
||||
- data->stop_chars = g_memdup (stop_chars, stop_chars_len);
|
||||
- data->stop_chars_len = stop_chars_len;
|
||||
+ if (stop_chars_len < 0)
|
||||
+ stop_chars_len_unsigned = strlen (stop_chars);
|
||||
+ else
|
||||
+ stop_chars_len_unsigned = (gsize) stop_chars_len;
|
||||
+
|
||||
+ data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned);
|
||||
+ data->stop_chars_len = stop_chars_len_unsigned;
|
||||
data->last_saw_cr = FALSE;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
@@ -1338,17 +1342,20 @@
|
||||
gssize found_pos;
|
||||
gssize res;
|
||||
char *data_until;
|
||||
+ gsize stop_chars_len_unsigned;
|
||||
|
||||
g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
|
||||
|
||||
if (stop_chars_len < 0)
|
||||
- stop_chars_len = strlen (stop_chars);
|
||||
+ stop_chars_len_unsigned = strlen (stop_chars);
|
||||
+ else
|
||||
+ stop_chars_len_unsigned = (gsize) stop_chars_len;
|
||||
|
||||
bstream = G_BUFFERED_INPUT_STREAM (stream);
|
||||
|
||||
checked = 0;
|
||||
|
||||
- while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1)
|
||||
+ while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1)
|
||||
{
|
||||
if (g_buffered_input_stream_get_available (bstream) ==
|
||||
g_buffered_input_stream_get_buffer_size (bstream))
|
||||
diff -Naur a/gio/gdbusconnection.c b/gio/gdbusconnection.c
|
||||
--- a/gio/gdbusconnection.c 2021-03-06 09:46:03.663000000 +0800
|
||||
+++ b/gio/gdbusconnection.c 2021-03-05 15:14:19.973000000 +0800
|
||||
@@ -3997,7 +3997,7 @@
|
||||
/* Don't waste memory by copying padding - remember to update this
|
||||
* when changing struct _GDBusInterfaceVTable in gdbusconnection.h
|
||||
*/
|
||||
- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
|
||||
+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4014,7 +4014,7 @@
|
||||
/* Don't waste memory by copying padding - remember to update this
|
||||
* when changing struct _GDBusSubtreeVTable in gdbusconnection.h
|
||||
*/
|
||||
- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
|
||||
+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
|
||||
}
|
||||
|
||||
static void
|
||||
diff -Naur a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c
|
||||
--- a/gio/gdbusinterfaceskeleton.c 2021-03-06 09:46:03.663000000 +0800
|
||||
+++ b/gio/gdbusinterfaceskeleton.c 2021-03-05 15:36:52.369000000 +0800
|
||||
@@ -701,7 +701,7 @@
|
||||
* properly before building the hooked_vtable, so we create it
|
||||
* once at the last minute.
|
||||
*/
|
||||
- interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
|
||||
+ interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
|
||||
interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call;
|
||||
}
|
||||
|
||||
diff -Naur a/gio/gfile.c b/gio/gfile.c
|
||||
--- a/gio/gfile.c 2021-03-06 09:46:03.666000000 +0800
|
||||
+++ b/gio/gfile.c 2021-03-05 15:44:25.759000000 +0800
|
||||
@@ -7884,7 +7884,7 @@
|
||||
g_main_context_invoke_full (g_task_get_context (task),
|
||||
g_task_get_priority (task),
|
||||
measure_disk_usage_invoke_progress,
|
||||
- g_memdup (&progress, sizeof progress),
|
||||
+ g_memdup2 (&progress, sizeof progress),
|
||||
g_free);
|
||||
}
|
||||
|
||||
@@ -7902,7 +7902,7 @@
|
||||
data->progress_callback ? measure_disk_usage_progress : NULL, task,
|
||||
&result.disk_usage, &result.num_dirs, &result.num_files,
|
||||
&error))
|
||||
- g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free);
|
||||
+ g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
@@ -7926,7 +7926,7 @@
|
||||
|
||||
task = g_task_new (file, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_file_real_measure_disk_usage_async);
|
||||
- g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free);
|
||||
+ g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
g_task_run_in_thread (task, measure_disk_usage_thread);
|
||||
diff -Naur a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
|
||||
--- a/gio/gkeyfilesettingsbackend.c 2021-03-06 09:46:03.670000000 +0800
|
||||
+++ b/gio/gkeyfilesettingsbackend.c 2021-03-05 17:24:26.933000000 +0800
|
||||
@@ -145,8 +145,8 @@
|
||||
gchar **group,
|
||||
gchar **basename)
|
||||
{
|
||||
- gint key_len = strlen (key);
|
||||
- gint i;
|
||||
+ gsize key_len = strlen (key);
|
||||
+ const gchar *last_slash;
|
||||
|
||||
if (key_len < kfsb->prefix_len ||
|
||||
memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0)
|
||||
@@ -155,38 +155,36 @@
|
||||
key_len -= kfsb->prefix_len;
|
||||
key += kfsb->prefix_len;
|
||||
|
||||
- for (i = key_len; i >= 0; i--)
|
||||
- if (key[i] == '/')
|
||||
- break;
|
||||
+ last_slash = strrchr (key, '/');
|
||||
|
||||
if (kfsb->root_group)
|
||||
{
|
||||
/* if a root_group was specified, make sure the user hasn't given
|
||||
* a path that ghosts that group name
|
||||
*/
|
||||
- if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0)
|
||||
+ if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if no root_group was given, ensure that the user gave a path */
|
||||
- if (i == -1)
|
||||
+ if (last_slash == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (group)
|
||||
{
|
||||
- if (i >= 0)
|
||||
+ if (last_slash != NULL)
|
||||
{
|
||||
- *group = g_memdup (key, i + 1);
|
||||
- (*group)[i] = '\0';
|
||||
+ *group = g_memdup2 (key, (last_slash - key) + 1);
|
||||
+ (*group)[(last_slash - key)] = '\0';
|
||||
}
|
||||
else
|
||||
*group = g_strdup (kfsb->root_group);
|
||||
}
|
||||
|
||||
if (basename)
|
||||
- *basename = g_memdup (key + i + 1, key_len - i);
|
||||
+ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
diff -Naur a/gio/gsettingsschema.c b/gio/gsettingsschema.c
|
||||
--- a/gio/gsettingsschema.c 2021-03-06 09:46:03.675000000 +0800
|
||||
+++ b/gio/gsettingsschema.c 2021-03-05 16:08:24.724000000 +0800
|
||||
@@ -1058,9 +1058,9 @@
|
||||
|
||||
if (g_str_has_suffix (key, "/"))
|
||||
{
|
||||
- gint length = strlen (key);
|
||||
+ gsize length = strlen (key);
|
||||
|
||||
- strv[j] = g_memdup (key, length);
|
||||
+ strv[j] = g_memdup2 (key, length);
|
||||
strv[j][length - 1] = '\0';
|
||||
j++;
|
||||
}
|
||||
diff -Naur a/gio/gsocket.c b/gio/gsocket.c
|
||||
--- a/gio/gsocket.c 2021-03-06 09:46:03.675000000 +0800
|
||||
+++ b/gio/gsocket.c 2021-03-05 16:34:42.236000000 +0800
|
||||
@@ -174,7 +174,7 @@
|
||||
GError **error);
|
||||
|
||||
static GSocketAddress *
|
||||
-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len);
|
||||
+cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len);
|
||||
|
||||
static gssize
|
||||
g_socket_receive_message_with_timeout (GSocket *socket,
|
||||
@@ -260,7 +260,7 @@
|
||||
struct {
|
||||
GSocketAddress *addr;
|
||||
struct sockaddr *native;
|
||||
- gint native_len;
|
||||
+ gsize native_len;
|
||||
guint64 last_used;
|
||||
} recv_addr_cache[RECV_ADDR_CACHE_SIZE];
|
||||
};
|
||||
@@ -5211,14 +5211,14 @@
|
||||
}
|
||||
|
||||
static GSocketAddress *
|
||||
-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len)
|
||||
+cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len)
|
||||
{
|
||||
GSocketAddress *saddr;
|
||||
gint i;
|
||||
guint64 oldest_time = G_MAXUINT64;
|
||||
gint oldest_index = 0;
|
||||
|
||||
- if (native_len <= 0)
|
||||
+ if (native_len == 0)
|
||||
return NULL;
|
||||
|
||||
saddr = NULL;
|
||||
@@ -5226,7 +5226,7 @@
|
||||
{
|
||||
GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr;
|
||||
gpointer tmp_native = socket->priv->recv_addr_cache[i].native;
|
||||
- gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
|
||||
+ gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
|
||||
|
||||
if (!tmp)
|
||||
continue;
|
||||
@@ -5256,7 +5256,7 @@
|
||||
g_free (socket->priv->recv_addr_cache[oldest_index].native);
|
||||
}
|
||||
|
||||
- socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len);
|
||||
+ socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len);
|
||||
socket->priv->recv_addr_cache[oldest_index].native_len = native_len;
|
||||
socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr);
|
||||
socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time ();
|
||||
@@ -5404,6 +5404,9 @@
|
||||
/* do it */
|
||||
while (1)
|
||||
{
|
||||
+ /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */
|
||||
+ G_STATIC_ASSERT (sizeof addr <= G_MAXINT);
|
||||
+
|
||||
addrlen = sizeof addr;
|
||||
if (address)
|
||||
result = WSARecvFrom (socket->priv->fd,
|
||||
diff -Naur a/gio/gtlspassword.c b/gio/gtlspassword.c
|
||||
--- a/gio/gtlspassword.c 2021-03-06 09:46:03.678000000 +0800
|
||||
+++ b/gio/gtlspassword.c 2021-03-05 16:36:55.266000000 +0800
|
||||
@@ -287,9 +287,14 @@
|
||||
g_return_if_fail (G_IS_TLS_PASSWORD (password));
|
||||
|
||||
if (length < 0)
|
||||
- length = strlen ((gchar *)value);
|
||||
+ {
|
||||
+ /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
|
||||
+ gsize length_unsigned = strlen ((gchar *) value);
|
||||
+ g_return_if_fail (length_unsigned > G_MAXSSIZE);
|
||||
+ length = (gssize) length_unsigned;
|
||||
+ }
|
||||
|
||||
- g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free);
|
||||
+ g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
|
||||
}
|
||||
|
||||
/**
|
||||
diff -Naur a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c
|
||||
--- a/gio/gwin32registrykey.c 2021-03-06 09:46:03.680000000 +0800
|
||||
+++ b/gio/gwin32registrykey.c 2021-03-05 16:43:04.459000000 +0800
|
||||
@@ -125,16 +125,34 @@
|
||||
G_WIN32_REGISTRY_UPDATED_PATH = 1,
|
||||
} GWin32RegistryKeyUpdateFlag;
|
||||
|
||||
+static gsize
|
||||
+g_utf16_len (const gunichar2 *str)
|
||||
+{
|
||||
+ gsize result;
|
||||
+
|
||||
+ for (result = 0; str[0] != 0; str++, result++)
|
||||
+ ;
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
static gunichar2 *
|
||||
-g_wcsdup (const gunichar2 *str,
|
||||
- gssize str_size)
|
||||
+g_wcsdup (const gunichar2 *str, gssize str_len)
|
||||
{
|
||||
- if (str_size == -1)
|
||||
- {
|
||||
- str_size = wcslen (str) + 1;
|
||||
- str_size *= sizeof (gunichar2);
|
||||
- }
|
||||
- return g_memdup (str, str_size);
|
||||
+ gsize str_len_unsigned;
|
||||
+ gsize str_size;
|
||||
+
|
||||
+ g_return_val_if_fail (str != NULL, NULL);
|
||||
+
|
||||
+ if (str_len < 0)
|
||||
+ str_len_unsigned = g_utf16_len (str);
|
||||
+ else
|
||||
+ str_len_unsigned = (gsize) str_len;
|
||||
+
|
||||
+ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
|
||||
+ str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
|
||||
+
|
||||
+ return g_memdup2 (str, str_size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +265,7 @@
|
||||
new_iter->value_name_size = iter->value_name_size;
|
||||
|
||||
if (iter->value_data != NULL)
|
||||
- new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size);
|
||||
+ new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size);
|
||||
|
||||
new_iter->value_data_size = iter->value_data_size;
|
||||
|
||||
@@ -268,8 +286,8 @@
|
||||
new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
|
||||
|
||||
if (iter->value_data_expanded_u8 != NULL)
|
||||
- new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8,
|
||||
- iter->value_data_expanded_charsize);
|
||||
+ new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8,
|
||||
+ iter->value_data_expanded_charsize);
|
||||
|
||||
new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
|
||||
|
||||
diff -Naur a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c
|
||||
--- a/gio/tests/async-close-output-stream.c 2021-03-06 09:46:03.682000000 +0800
|
||||
+++ b/gio/tests/async-close-output-stream.c 2021-03-05 16:54:17.745000000 +0800
|
||||
@@ -147,9 +147,9 @@
|
||||
|
||||
data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream));
|
||||
|
||||
- g_assert_cmpint (data->expected_size, >, 0);
|
||||
+ g_assert_cmpuint (data->expected_size, >, 0);
|
||||
|
||||
- data->expected_output = g_memdup (written, (guint)data->expected_size);
|
||||
+ data->expected_output = g_memdup2 (written, data->expected_size);
|
||||
|
||||
/* then recreate the streams and prepare them for the asynchronous close */
|
||||
destroy_streams (data);
|
||||
diff -Naur a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c
|
||||
--- a/gio/tests/gdbus-export.c 2021-03-06 09:46:03.685000000 +0800
|
||||
+++ b/gio/tests/gdbus-export.c 2021-03-05 16:56:17.247000000 +0800
|
||||
@@ -671,7 +671,7 @@
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
- return g_memdup (interfaces, 2 * sizeof (void *));
|
||||
+ return g_memdup2 (interfaces, 2 * sizeof (void *));
|
||||
}
|
||||
|
||||
static const GDBusInterfaceVTable *
|
||||
@@ -727,7 +727,7 @@
|
||||
{
|
||||
const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL };
|
||||
|
||||
- return g_memdup (interfaces, 2 * sizeof (void *));
|
||||
+ return g_memdup2 (interfaces, 2 * sizeof (void *));
|
||||
}
|
||||
|
||||
static const GDBusInterfaceVTable *
|
||||
diff -Naur a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c
|
||||
--- a/gio/win32/gwinhttpfile.c 2021-03-06 09:46:03.693000000 +0800
|
||||
+++ b/gio/win32/gwinhttpfile.c 2021-03-05 16:58:28.076000000 +0800
|
||||
@@ -393,10 +393,10 @@
|
||||
child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
|
||||
child->vfs = winhttp_file->vfs;
|
||||
child->url = winhttp_file->url;
|
||||
- child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
|
||||
- child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
|
||||
- child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
|
||||
- child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
|
||||
+ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2);
|
||||
+ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2);
|
||||
+ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2);
|
||||
+ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2);
|
||||
child->url.lpszUrlPath = wnew_path;
|
||||
child->url.dwUrlPathLength = wcslen (wnew_path);
|
||||
child->url.lpszExtraInfo = NULL;
|
||||
diff -Naur a/glib/gbytes.c b/glib/gbytes.c
|
||||
--- a/glib/gbytes.c 2021-03-06 09:46:03.721000000 +0800
|
||||
+++ b/glib/gbytes.c 2021-03-05 17:29:25.481000000 +0800
|
||||
@@ -95,7 +95,7 @@
|
||||
{
|
||||
g_return_val_if_fail (data != NULL || size == 0, NULL);
|
||||
|
||||
- return g_bytes_new_take (g_memdup (data, size), size);
|
||||
+ return g_bytes_new_take (g_memdup2 (data, size), size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,7 +499,7 @@
|
||||
* Copy: Non g_malloc (or compatible) allocator, or static memory,
|
||||
* so we have to copy, and then unref.
|
||||
*/
|
||||
- result = g_memdup (bytes->data, bytes->size);
|
||||
+ result = g_memdup2 (bytes->data, bytes->size);
|
||||
*size = bytes->size;
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
diff -Naur a/glib/gdir.c b/glib/gdir.c
|
||||
--- a/glib/gdir.c 2021-03-06 09:46:03.696000000 +0800
|
||||
+++ b/glib/gdir.c 2021-03-06 09:11:06.646000000 +0800
|
||||
@@ -112,7 +112,7 @@
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
- return g_memdup (&dir, sizeof dir);
|
||||
+ return g_memdup2 (&dir, sizeof dir);
|
||||
}
|
||||
|
||||
/**
|
||||
diff -Naur a/glib/ghash.c b/glib/ghash.c
|
||||
--- a/glib/ghash.c 2021-03-06 09:46:03.697000000 +0800
|
||||
+++ b/glib/ghash.c 2021-03-06 09:12:58.243000000 +0800
|
||||
@@ -964,7 +964,7 @@
|
||||
if (hash_table->have_big_keys)
|
||||
{
|
||||
if (key != value)
|
||||
- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
|
||||
+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
|
||||
/* Keys and values are both big now, so no need for further checks */
|
||||
return;
|
||||
}
|
||||
@@ -972,7 +972,7 @@
|
||||
{
|
||||
if (key != value)
|
||||
{
|
||||
- hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size);
|
||||
+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size);
|
||||
is_a_set = FALSE;
|
||||
}
|
||||
}
|
||||
@@ -1000,7 +1000,7 @@
|
||||
|
||||
/* Just split if necessary */
|
||||
if (is_a_set && key != value)
|
||||
- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
|
||||
+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
|
||||
|
||||
#endif
|
||||
}
|
||||
diff -Naur a/glib/giochannel.c b/glib/giochannel.c
|
||||
--- a/glib/giochannel.c 2021-03-06 09:46:03.697000000 +0800
|
||||
+++ b/glib/giochannel.c 2021-03-06 09:20:11.237000000 +0800
|
||||
@@ -883,16 +883,25 @@
|
||||
const gchar *line_term,
|
||||
gint length)
|
||||
{
|
||||
+ guint length_unsigned;
|
||||
+
|
||||
g_return_if_fail (channel != NULL);
|
||||
g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
|
||||
|
||||
if (line_term == NULL)
|
||||
- length = 0;
|
||||
- else if (length < 0)
|
||||
- length = strlen (line_term);
|
||||
+ length_unsigned = 0;
|
||||
+ else if (length >= 0)
|
||||
+ length_unsigned = (guint) length;
|
||||
+ else
|
||||
+ {
|
||||
+ /* FIXME: We’re constrained by line_term_len being a guint here */
|
||||
+ gsize length_size = strlen (line_term);
|
||||
+ g_return_if_fail (length_size > G_MAXUINT);
|
||||
+ length_unsigned = (guint) length_size;
|
||||
+ }
|
||||
|
||||
g_free (channel->line_term);
|
||||
- channel->line_term = line_term ? g_memdup (line_term, length) : NULL;
|
||||
+ channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
|
||||
channel->line_term_len = length;
|
||||
}
|
||||
|
||||
diff -Naur a/glib/gstrfuncs.c b/glib/gstrfuncs.c
|
||||
--- a/glib/gstrfuncs.c 2021-03-06 09:46:03.703000000 +0800
|
||||
+++ b/glib/gstrfuncs.c 2021-03-06 09:21:27.836000000 +0800
|
||||
@@ -398,6 +398,38 @@
|
||||
}
|
||||
|
||||
/**
|
||||
+ * g_memdup2:
|
||||
+ * @mem: (nullable): the memory to copy.
|
||||
+ * @byte_size: the number of bytes to copy.
|
||||
+ *
|
||||
+ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
|
||||
+ * from @mem. If @mem is %NULL it returns %NULL.
|
||||
+ *
|
||||
+ * This replaces g_memdup(), which was prone to integer overflows when
|
||||
+ * converting the argument from a #gsize to a #guint.
|
||||
+ *
|
||||
+ * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
|
||||
+ * or %NULL if @mem is %NULL.
|
||||
+ * Since: 2.68
|
||||
+ */
|
||||
+gpointer
|
||||
+g_memdup2 (gconstpointer mem,
|
||||
+ gsize byte_size)
|
||||
+{
|
||||
+ gpointer new_mem;
|
||||
+
|
||||
+ if (mem && byte_size != 0)
|
||||
+ {
|
||||
+ new_mem = g_malloc (byte_size);
|
||||
+ memcpy (new_mem, mem, byte_size);
|
||||
+ }
|
||||
+ else
|
||||
+ new_mem = NULL;
|
||||
+
|
||||
+ return new_mem;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* g_strndup:
|
||||
* @str: the string to duplicate
|
||||
* @n: the maximum number of bytes to copy from @str
|
||||
diff -Naur a/glib/gstrfuncs.h b/glib/gstrfuncs.h
|
||||
--- a/glib/gstrfuncs.h 2021-03-06 09:46:03.703000000 +0800
|
||||
+++ b/glib/gstrfuncs.h 2021-03-06 09:23:07.268000000 +0800
|
||||
@@ -257,6 +257,10 @@
|
||||
gpointer g_memdup (gconstpointer mem,
|
||||
guint byte_size) G_GNUC_ALLOC_SIZE(2);
|
||||
|
||||
+GLIB_AVAILABLE_IN_ALL
|
||||
+gpointer g_memdup2 (gconstpointer mem,
|
||||
+ gsize byte_size) G_GNUC_ALLOC_SIZE(2);
|
||||
+
|
||||
/* NULL terminated string arrays.
|
||||
* g_strsplit(), g_strsplit_set() split up string into max_tokens tokens
|
||||
* at delim and return a newly allocated string array.
|
||||
diff -Naur a/glib/gtestutils.c b/glib/gtestutils.c
|
||||
--- a/glib/gtestutils.c 2021-03-06 09:46:03.704000000 +0800
|
||||
+++ b/glib/gtestutils.c 2021-03-06 09:24:38.454000000 +0800
|
||||
@@ -3801,7 +3801,7 @@
|
||||
if (p <= tbuffer->data->str + mlength)
|
||||
{
|
||||
g_string_erase (tbuffer->data, 0, mlength);
|
||||
- tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg)));
|
||||
+ tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg)));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
diff -Naur a/glib/gvariant.c b/glib/gvariant.c
|
||||
--- a/glib/gvariant.c 2021-03-06 09:46:03.709000000 +0800
|
||||
+++ b/glib/gvariant.c 2021-03-06 09:26:50.164000000 +0800
|
||||
@@ -725,7 +725,7 @@
|
||||
g_variant_ref_sink (value);
|
||||
|
||||
return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
|
||||
- g_memdup (&value, sizeof value),
|
||||
+ g_memdup2 (&value, sizeof value),
|
||||
1, g_variant_is_trusted (value));
|
||||
}
|
||||
|
||||
@@ -1229,7 +1229,7 @@
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- data = g_memdup (elements, n_elements * element_size);
|
||||
+ data = g_memdup2 (elements, n_elements * element_size);
|
||||
value = g_variant_new_from_data (array_type, data,
|
||||
n_elements * element_size,
|
||||
FALSE, g_free, data);
|
||||
@@ -1908,7 +1908,7 @@
|
||||
if (length)
|
||||
*length = size;
|
||||
|
||||
- return g_memdup (original, size + 1);
|
||||
+ return g_memdup2 (original, size + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
diff -Naur a/glib/gvarianttype.c b/glib/gvarianttype.c
|
||||
--- a/glib/gvarianttype.c 2021-03-06 09:46:03.709000000 +0800
|
||||
+++ b/glib/gvarianttype.c 2021-03-06 09:28:03.190000000 +0800
|
||||
@@ -1181,7 +1181,7 @@
|
||||
g_assert (offset < sizeof buffer);
|
||||
buffer[offset++] = ')';
|
||||
|
||||
- return (GVariantType *) g_memdup (buffer, offset);
|
||||
+ return (GVariantType *) g_memdup2 (buffer, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
diff -Naur a/glib/tests/array-test.c b/glib/tests/array-test.c
|
||||
--- a/glib/tests/array-test.c 2021-03-06 09:46:03.712000000 +0800
|
||||
+++ b/glib/tests/array-test.c 2021-03-06 09:28:56.467000000 +0800
|
||||
@@ -1616,7 +1616,7 @@
|
||||
GByteArray *gbarray;
|
||||
guint8 *data;
|
||||
|
||||
- data = g_memdup ("woooweeewow", 11);
|
||||
+ data = g_memdup2 ("woooweeewow", 11);
|
||||
gbarray = g_byte_array_new_take (data, 11);
|
||||
g_assert (gbarray->data == data);
|
||||
g_assert_cmpuint (gbarray->len, ==, 11);
|
||||
diff -Naur a/glib/tests/option-context.c b/glib/tests/option-context.c
|
||||
--- a/glib/tests/option-context.c 2021-03-06 09:46:03.719000000 +0800
|
||||
+++ b/glib/tests/option-context.c 2021-03-06 09:30:07.022000000 +0800
|
||||
@@ -256,7 +256,7 @@
|
||||
static char **
|
||||
copy_stringv (char **argv, int argc)
|
||||
{
|
||||
- return g_memdup (argv, sizeof (char *) * (argc + 1));
|
||||
+ return g_memdup2 (argv, sizeof (char *) * (argc + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2323,7 +2323,7 @@
|
||||
g_option_context_add_group (context, group);
|
||||
|
||||
argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc);
|
||||
- orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *));
|
||||
+ orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *));
|
||||
|
||||
retval = g_option_context_parse (context, &argc, &argv, &error);
|
||||
|
||||
diff -Naur a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c
|
||||
--- a/glib/tests/strfuncs.c 2021-03-06 09:46:03.720000000 +0800
|
||||
+++ b/glib/tests/strfuncs.c 2021-03-06 09:33:09.312000000 +0800
|
||||
@@ -219,6 +219,26 @@
|
||||
g_free (str_dup);
|
||||
}
|
||||
|
||||
+/* Testing g_memdup2() function with various positive and negative cases */
|
||||
+static void
|
||||
+test_memdup2 (void)
|
||||
+{
|
||||
+ gchar *str_dup = NULL;
|
||||
+ const gchar *str = "The quick brown fox jumps over the lazy dog";
|
||||
+
|
||||
+ /* Testing negative cases */
|
||||
+ g_assert_null (g_memdup2 (NULL, 1024));
|
||||
+ g_assert_null (g_memdup2 (str, 0));
|
||||
+ g_assert_null (g_memdup2 (NULL, 0));
|
||||
+
|
||||
+ /* Testing normal usage cases */
|
||||
+ str_dup = g_memdup2 (str, strlen (str) + 1);
|
||||
+ g_assert_nonnull (str_dup);
|
||||
+ g_assert_cmpstr (str, ==, str_dup);
|
||||
+
|
||||
+ g_free (str_dup);
|
||||
+}
|
||||
+
|
||||
/* Testing g_strpcpy() function with various positive and negative cases */
|
||||
static void
|
||||
test_stpcpy (void)
|
||||
@@ -2523,6 +2543,7 @@
|
||||
g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
|
||||
g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
|
||||
g_test_add_func ("/strfuncs/memdup", test_memdup);
|
||||
+ g_test_add_func ("/strfuncs/memdup2", test_memdup2);
|
||||
g_test_add_func ("/strfuncs/stpcpy", test_stpcpy);
|
||||
g_test_add_func ("/strfuncs/str_match_string", test_str_match_string);
|
||||
g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold);
|
||||
diff -Naur a/gobject/gsignal.c b/gobject/gsignal.c
|
||||
--- a/gobject/gsignal.c 2021-03-06 09:46:03.722000000 +0800
|
||||
+++ b/gobject/gsignal.c 2021-03-06 09:36:46.688000000 +0800
|
||||
@@ -1730,7 +1730,7 @@
|
||||
node->single_va_closure_is_valid = FALSE;
|
||||
node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
|
||||
node->n_params = n_params;
|
||||
- node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
|
||||
+ node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
|
||||
node->return_type = return_type;
|
||||
node->class_closure_bsa = NULL;
|
||||
if (accumulator)
|
||||
diff -Naur a/gobject/gtype.c b/gobject/gtype.c
|
||||
--- a/gobject/gtype.c 2021-03-06 09:46:03.724000000 +0800
|
||||
+++ b/gobject/gtype.c 2021-03-06 09:38:47.030000000 +0800
|
||||
@@ -1470,7 +1470,7 @@
|
||||
iholder->next = iface_node_get_holders_L (iface);
|
||||
iface_node_set_holders_W (iface, iholder);
|
||||
iholder->instance_type = NODE_TYPE (node);
|
||||
- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
|
||||
+ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
|
||||
iholder->plugin = plugin;
|
||||
|
||||
/* create an iface entry for this type */
|
||||
@@ -1731,7 +1731,7 @@
|
||||
INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
|
||||
|
||||
check_interface_info_I (iface, instance_type, &tmp_info);
|
||||
- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
|
||||
+ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
|
||||
}
|
||||
|
||||
return iholder; /* we don't modify write lock upon returning NULL */
|
||||
@@ -2016,10 +2016,10 @@
|
||||
IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
|
||||
|
||||
if (pentry)
|
||||
- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
|
||||
+ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
|
||||
}
|
||||
if (!vtable)
|
||||
- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
|
||||
+ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
|
||||
entry->vtable = vtable;
|
||||
vtable->g_type = NODE_TYPE (iface);
|
||||
vtable->g_instance_type = NODE_TYPE (node);
|
||||
diff -Naur a/gobject/gtypemodule.c b/gobject/gtypemodule.c
|
||||
--- a/gobject/gtypemodule.c 2021-03-06 09:46:03.724000000 +0800
|
||||
+++ b/gobject/gtypemodule.c 2021-03-06 09:39:57.337000000 +0800
|
||||
@@ -436,7 +436,7 @@
|
||||
module_type_info->loaded = TRUE;
|
||||
module_type_info->info = *type_info;
|
||||
if (type_info->value_table)
|
||||
- module_type_info->info.value_table = g_memdup (type_info->value_table,
|
||||
+ module_type_info->info.value_table = g_memdup2 (type_info->value_table,
|
||||
sizeof (GTypeValueTable));
|
||||
|
||||
return module_type_info->type;
|
||||
diff -Naur a/gobject/tests/param.c b/gobject/tests/param.c
|
||||
--- a/gobject/tests/param.c 2021-03-06 09:46:03.725000000 +0800
|
||||
+++ b/gobject/tests/param.c 2021-03-06 09:40:28.446000000 +0800
|
||||
@@ -851,7 +851,7 @@
|
||||
test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
|
||||
data.change_this_flag, data.change_this_type,
|
||||
data.use_this_flag, data.use_this_type);
|
||||
- test_data = g_memdup (&data, sizeof (TestParamImplementData));
|
||||
+ test_data = g_memdup2 (&data, sizeof (TestParamImplementData));
|
||||
g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
|
||||
g_free (test_path);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
Name: glib2
|
||||
Version: 2.62.5
|
||||
Release: 3
|
||||
Release: 4
|
||||
Summary: The core library that forms the basis for projects such as GTK+ and GNOME
|
||||
License: LGPLv2+
|
||||
URL: http://www.gtk.org
|
||||
@ -9,6 +9,7 @@ Source0: http://download.gnome.org/sources/glib/2.62/glib-%{version}.tar.
|
||||
Patch9001: fix-accidentally-delete-temp-file-within-dtrace.patch
|
||||
Patch6000: backport-CVE-2020-35457.patch
|
||||
Patch6001: backport-CVE-2021-27218.patch
|
||||
Patch6002: backport-CVE-2021-27219.patch
|
||||
|
||||
BuildRequires: chrpath gcc gcc-c++ gettext gtk-doc perl-interpreter
|
||||
BUildRequires: glibc-devel libattr-devel libselinux-devel meson
|
||||
@ -145,6 +146,12 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
|
||||
%doc %{_datadir}/gtk-doc/html/*
|
||||
|
||||
%changelog
|
||||
* Sat Mar 6 2021 hanhui<hanhui15@huawei.com> - 2.62.5-4
|
||||
- Type:cve
|
||||
- Id:CVE-2021-27219
|
||||
- SUG:NA
|
||||
- DESC:fix CVE-2021-27219
|
||||
|
||||
* Mon Mar 1 2021 jinzhimin<jinzhimin2@huawei.com> - 2.62.5-3
|
||||
- Type:cve
|
||||
- Id:CVE-2021-27218
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user