diff options
author | Thomas Haller <thaller@redhat.com> | 2019-09-21 15:27:49 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-12-05 12:36:13 +0100 |
commit | 9618f1bb4b5e16f95c7d19556356b990486966b7 (patch) | |
tree | 1ad81f9188bc19834382b330d4c288bf8843fbdb | |
parent | e7cf22be3ed1e2f0a403a7809e2f791cb01af404 (diff) | |
download | NetworkManager-9618f1bb4b5e16f95c7d19556356b990486966b7.tar.gz |
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).
-rw-r--r-- | src/initrd/nmi-dt-reader.c | 30 |
1 files 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 * |