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.
This commit is contained in:
Thomas Haller 2018-06-11 13:19:40 +02:00
parent 988cecb6d3
commit 92b8161578

View file

@ -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;
}
/**