From 9618f1bb4b5e16f95c7d19556356b990486966b7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Sat, 21 Sep 2019 15:27:49 +0200 Subject: [PATCH] initrd: fix out-of-bounds read when detecting address family in dt_get_ipaddr_property() The @family argument is an input and output argument. Initially, the family is set to AF_UNSPEC, in which case the family gets detected based on the IP address. However, we call dt_get_ipaddr_property() multiple times to parse the netmask, the gateway and the IP address. That means, after the first successfull call, the @family is set to AF_INET or AF_INET6. Note that the previous code (in the switch block) would only check that the family is set to AF_UNSPEC, but it would not check that the @family matches the expected binary address length @len. Later, we then might call nm_ip_address_new_binary() with a family and a binary address of unexpected length. Also drop the error checking for nm_ip_address_new_binary(). nm_ip_address_new_binary() can only fail if the prefix length is larger than 32/128. The function has no way to validate the input arguments beyond that and can thus not fail (short of undefined behavior). --- src/initrd/nmi-dt-reader.c | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/initrd/nmi-dt-reader.c b/src/initrd/nmi-dt-reader.c index 3290689d9c..bc574395fc 100644 --- a/src/initrd/nmi-dt-reader.c +++ b/src/initrd/nmi-dt-reader.c @@ -51,40 +51,24 @@ dt_get_ipaddr_property (const char *base, const char *prop, int *family) { - NMIPAddress *addr; gs_free char *buf = NULL; size_t len; - gs_free_error GError *error = NULL; + int f; if (!dt_get_property (base, dev, prop, &buf, &len)) return NULL; - switch (len) { - case 4: - if (*family == AF_UNSPEC) - *family = AF_INET; - break; - case 16: - if (*family == AF_UNSPEC) - *family = AF_INET6; - break; - default: - break; - } - - if (*family == AF_UNSPEC) { + f = nm_utils_addr_family_from_size (len); + if ( f == AF_UNSPEC + || ( *family != AF_UNSPEC + && *family != f)) { _LOGW (LOGD_CORE, "%s: Address %s has unrecognized length (%zd)", dev, prop, len); return NULL; } - addr = nm_ip_address_new_binary (*family, buf, 0, &error); - if (!addr) { - _LOGW (LOGD_CORE, "%s: Address %s is malformed: %s", - dev, prop, error->message); - } - - return addr; + *family = f; + return nm_ip_address_new_binary (f, buf, 0, NULL); } static char *