From 92b8161578a546fe3dc86701a471938cfbd520fd Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 11 Jun 2018 13:19:40 +0200 Subject: [PATCH] libnm: avoid allocating GBytes in _nm_utils_dhcp_duid_valid() In a lot of cases, we don't require the GBytes out-argument. This is the case when called from NMSettingIP6Config's verify(). Avoid allocating the GBytes instance and also don't heap allocate the temporary buffer in that case. Also, being called from NMSettingIP6Config's verify(), at which point the string value contains untrusted data. Of course, we do very badly in general protecting against the user creating huge settings, which could trick NetworkManage to allocate large amounts of memory (and being killed by glib's out of memory handling). We should handle such cases better in general, but just avoid it here. Since we know that the buffer must hold at most 128+2 bytes, we can stack allocate it. Later, in case we really need to return the value, we can create a GBytes instance of the right size. --- libnm-core/nm-utils.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 861b283e45..eb705cbe0a 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -4448,11 +4448,10 @@ _nm_utils_inet6_is_token (const struct in6_addr *in6addr) gboolean _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin) { + guint8 duid_arr[128 + 2]; gsize duid_len; - gs_unref_bytes GBytes *duid_bin = NULL; - if (out_duid_bin) - *out_duid_bin = NULL; + NM_SET_OUT (out_duid_bin, NULL); if (!duid) return FALSE; @@ -4466,20 +4465,16 @@ _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin) return TRUE; } - duid_bin = nm_utils_hexstr2bin (duid); - if (!duid_bin) - return FALSE; + if (_str2bin (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) { + /* MAX DUID length is 128 octects + the type code (2 octects). */ + if ( duid_len > 2 + && duid_len <= (128 + 2)) { + NM_SET_OUT (out_duid_bin, g_bytes_new (duid_arr, duid_len)); + return TRUE; + } + } - duid_len = g_bytes_get_size (duid_bin); - /* MAX DUID lenght is 128 octects + the type code (2 octects). */ - if ( duid_len <= 2 - || duid_len > (128 + 2)) - return FALSE; - - if (out_duid_bin) - *out_duid_bin = g_steal_pointer (&duid_bin); - - return TRUE; + return FALSE; } /**