summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-09-21 15:27:49 +0200
committerThomas Haller <thaller@redhat.com>2019-12-05 12:36:13 +0100
commit9618f1bb4b5e16f95c7d19556356b990486966b7 (patch)
tree1ad81f9188bc19834382b330d4c288bf8843fbdb
parente7cf22be3ed1e2f0a403a7809e2f791cb01af404 (diff)
downloadNetworkManager-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.c30
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 *