mirror of
https://github.com/libuv/libuv
synced 2025-03-28 21:13:16 +00:00
unix: handle out of memory in iface name copy (#4724)
Allocate storage upfront, that way we can never run out of memory halfway through processing the interface list. Fixes: https://github.com/libuv/libuv/issues/4723
This commit is contained in:
parent
436c04048e
commit
16d6a0b49d
@ -1120,6 +1120,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
struct ifreq *ifr, *p, flg;
|
struct ifreq *ifr, *p, flg;
|
||||||
struct in6_ifreq if6;
|
struct in6_ifreq if6;
|
||||||
struct sockaddr_dl* sa_addr;
|
struct sockaddr_dl* sa_addr;
|
||||||
|
size_t namelen;
|
||||||
|
char* name;
|
||||||
|
|
||||||
ifc.ifc_req = NULL;
|
ifc.ifc_req = NULL;
|
||||||
sock6fd = -1;
|
sock6fd = -1;
|
||||||
@ -1156,6 +1158,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
#define ADDR_SIZE(p) MAX((p).sa_len, sizeof(p))
|
||||||
|
|
||||||
/* Count all up and running ipv4/ipv6 addresses */
|
/* Count all up and running ipv4/ipv6 addresses */
|
||||||
|
namelen = 0;
|
||||||
ifr = ifc.ifc_req;
|
ifr = ifc.ifc_req;
|
||||||
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) {
|
||||||
p = ifr;
|
p = ifr;
|
||||||
@ -1175,6 +1178,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
if (!(flg.ifr_flags & IFF_UP && flg.ifr_flags & IFF_RUNNING))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
namelen += strlen(ent->ifa_name) + 1;
|
||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,8 +1186,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Alloc the return interface structs */
|
/* Alloc the return interface structs */
|
||||||
*addresses = uv__calloc(*count, sizeof(**addresses));
|
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||||
if (!(*addresses)) {
|
if (*addresses == NULL) {
|
||||||
r = UV_ENOMEM;
|
r = UV_ENOMEM;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -1210,7 +1214,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
|
|
||||||
/* All conditions above must match count loop */
|
/* All conditions above must match count loop */
|
||||||
|
|
||||||
address->name = uv__strdup(p->ifr_name);
|
namelen = strlen(p->ifr_name) + 1;
|
||||||
|
address->name = memcpy(name, p->ifr_name, namelen);
|
||||||
|
name += namelen;
|
||||||
|
|
||||||
if (inet6)
|
if (inet6)
|
||||||
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr);
|
||||||
@ -1282,13 +1288,7 @@ cleanup:
|
|||||||
|
|
||||||
|
|
||||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||||
int count) {
|
int count) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; ++i) {
|
|
||||||
uv__free(addresses[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(addresses);
|
uv__free(addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,13 +65,13 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO(bnoordhuis) share with linux.c */
|
||||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||||
|
uv_interface_address_t* address;
|
||||||
struct ifaddrs* addrs;
|
struct ifaddrs* addrs;
|
||||||
struct ifaddrs* ent;
|
struct ifaddrs* ent;
|
||||||
uv_interface_address_t* address;
|
size_t namelen;
|
||||||
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
|
char* name;
|
||||||
int i;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
*addresses = NULL;
|
*addresses = NULL;
|
||||||
@ -80,9 +80,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
/* Count the number of interfaces */
|
/* Count the number of interfaces */
|
||||||
|
namelen = 0;
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||||
continue;
|
continue;
|
||||||
|
namelen += strlen(ent->ifa_name) + 1;
|
||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,20 +94,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the memory is initiallized to zero using calloc() */
|
/* Make sure the memory is initiallized to zero using calloc() */
|
||||||
*addresses = uv__calloc(*count, sizeof(**addresses));
|
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||||
|
|
||||||
if (*addresses == NULL) {
|
if (*addresses == NULL) {
|
||||||
freeifaddrs(addrs);
|
freeifaddrs(addrs);
|
||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = (char*) &(*addresses)[*count];
|
||||||
address = *addresses;
|
address = *addresses;
|
||||||
|
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
address->name = uv__strdup(ent->ifa_name);
|
namelen = strlen(ent->ifa_name) + 1;
|
||||||
|
address->name = memcpy(name, ent->ifa_name, namelen);
|
||||||
|
name += namelen;
|
||||||
|
|
||||||
if (ent->ifa_addr->sa_family == AF_INET6) {
|
if (ent->ifa_addr->sa_family == AF_INET6) {
|
||||||
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
||||||
@ -129,6 +133,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
|
#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__)
|
||||||
/* Fill in physical addresses for each interface */
|
/* Fill in physical addresses for each interface */
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
|
int i;
|
||||||
|
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -151,13 +157,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO(bnoordhuis) share with linux.c */
|
||||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||||
int count) {
|
int count) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
uv__free(addresses[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(addresses);
|
uv__free(addresses);
|
||||||
}
|
}
|
||||||
|
@ -403,6 +403,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
return UV_ENOSYS;
|
return UV_ENOSYS;
|
||||||
|
|
||||||
/* The first loop to get the size of the array to be allocated */
|
/* The first loop to get the size of the array to be allocated */
|
||||||
|
namelen = 0;
|
||||||
for (cur = ifap; cur; cur = cur->ifa_next) {
|
for (cur = ifap; cur; cur = cur->ifa_next) {
|
||||||
if (!(cur->ifa_addr->sa_family == AF_INET6 ||
|
if (!(cur->ifa_addr->sa_family == AF_INET6 ||
|
||||||
cur->ifa_addr->sa_family == AF_INET))
|
cur->ifa_addr->sa_family == AF_INET))
|
||||||
@ -411,6 +412,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
|
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
namelen += strlen(cur->ifa_name) + 1;
|
||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,11 +422,13 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Alloc the return interface structs */
|
/* Alloc the return interface structs */
|
||||||
*addresses = uv__calloc(*count, sizeof(**addresses));
|
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||||
if (*addresses == NULL) {
|
if (*addresses == NULL) {
|
||||||
Qp2freeifaddrs(ifap);
|
Qp2freeifaddrs(ifap);
|
||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = (char*) &(*addresses)[*count];
|
||||||
address = *addresses;
|
address = *addresses;
|
||||||
|
|
||||||
/* The second loop to fill in the array */
|
/* The second loop to fill in the array */
|
||||||
@ -436,7 +440,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
|
if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
address->name = uv__strdup(cur->ifa_name);
|
namelen = strlen(cur->ifa_name) + 1;
|
||||||
|
address->name = memcpy(name, cur->ifa_name, namelen);
|
||||||
|
name += namelen;
|
||||||
|
|
||||||
inet6 = (cur->ifa_addr->sa_family == AF_INET6);
|
inet6 = (cur->ifa_addr->sa_family == AF_INET6);
|
||||||
|
|
||||||
@ -497,13 +503,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
|
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||||
int i;
|
int count) {
|
||||||
|
|
||||||
for (i = 0; i < count; ++i) {
|
|
||||||
uv__free(addresses[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(addresses);
|
uv__free(addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1954,11 +1954,15 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) {
|
|||||||
return !exclude_type;
|
return !exclude_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO(bnoordhuis) share with bsd-ifaddrs.c */
|
||||||
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
||||||
struct ifaddrs *addrs, *ent;
|
|
||||||
uv_interface_address_t* address;
|
uv_interface_address_t* address;
|
||||||
|
struct sockaddr_ll* sll;
|
||||||
|
struct ifaddrs* addrs;
|
||||||
|
struct ifaddrs* ent;
|
||||||
|
size_t namelen;
|
||||||
|
char* name;
|
||||||
int i;
|
int i;
|
||||||
struct sockaddr_ll *sll;
|
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
*addresses = NULL;
|
*addresses = NULL;
|
||||||
@ -1967,10 +1971,12 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
/* Count the number of interfaces */
|
/* Count the number of interfaces */
|
||||||
|
namelen = 0;
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
namelen += strlen(ent->ifa_name) + 1;
|
||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1980,19 +1986,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the memory is initiallized to zero using calloc() */
|
/* Make sure the memory is initiallized to zero using calloc() */
|
||||||
*addresses = uv__calloc(*count, sizeof(**addresses));
|
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||||
if (!(*addresses)) {
|
if (*addresses == NULL) {
|
||||||
freeifaddrs(addrs);
|
freeifaddrs(addrs);
|
||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = (char*) &(*addresses)[*count];
|
||||||
address = *addresses;
|
address = *addresses;
|
||||||
|
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFADDR))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
address->name = uv__strdup(ent->ifa_name);
|
namelen = strlen(ent->ifa_name) + 1;
|
||||||
|
address->name = memcpy(name, ent->ifa_name, namelen);
|
||||||
|
name += namelen;
|
||||||
|
|
||||||
if (ent->ifa_addr->sa_family == AF_INET6) {
|
if (ent->ifa_addr->sa_family == AF_INET6) {
|
||||||
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
||||||
@ -2036,14 +2045,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO(bnoordhuis) share with bsd-ifaddrs.c */
|
||||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||||
int count) {
|
int count) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
uv__free(addresses[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(addresses);
|
uv__free(addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,6 +826,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
uv_interface_address_t* address;
|
uv_interface_address_t* address;
|
||||||
struct ifaddrs* addrs;
|
struct ifaddrs* addrs;
|
||||||
struct ifaddrs* ent;
|
struct ifaddrs* ent;
|
||||||
|
size_t namelen;
|
||||||
|
char* name;
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
*addresses = NULL;
|
*addresses = NULL;
|
||||||
@ -834,9 +836,11 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
return UV__ERR(errno);
|
return UV__ERR(errno);
|
||||||
|
|
||||||
/* Count the number of interfaces */
|
/* Count the number of interfaces */
|
||||||
|
namelen = 0;
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent))
|
if (uv__ifaddr_exclude(ent))
|
||||||
continue;
|
continue;
|
||||||
|
namelen += strlen(ent->ifa_name) + 1;
|
||||||
(*count)++;
|
(*count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,19 +849,22 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*addresses = uv__malloc(*count * sizeof(**addresses));
|
*addresses = uv__calloc(1, *count * sizeof(**addresses) + namelen);
|
||||||
if (!(*addresses)) {
|
if (*addresses == NULL) {
|
||||||
freeifaddrs(addrs);
|
freeifaddrs(addrs);
|
||||||
return UV_ENOMEM;
|
return UV_ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = (char*) &(*addresses)[*count];
|
||||||
address = *addresses;
|
address = *addresses;
|
||||||
|
|
||||||
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
for (ent = addrs; ent != NULL; ent = ent->ifa_next) {
|
||||||
if (uv__ifaddr_exclude(ent))
|
if (uv__ifaddr_exclude(ent))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
address->name = uv__strdup(ent->ifa_name);
|
namelen = strlen(ent->ifa_name) + 1;
|
||||||
|
address->name = memcpy(name, ent->ifa_name, namelen);
|
||||||
|
name += namelen;
|
||||||
|
|
||||||
if (ent->ifa_addr->sa_family == AF_INET6) {
|
if (ent->ifa_addr->sa_family == AF_INET6) {
|
||||||
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
address->address.address6 = *((struct sockaddr_in6*) ent->ifa_addr);
|
||||||
@ -885,13 +892,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
|
|||||||
#endif /* SUNOS_NO_IFADDRS */
|
#endif /* SUNOS_NO_IFADDRS */
|
||||||
|
|
||||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||||
int count) {
|
int count) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
uv__free(addresses[i].name);
|
|
||||||
}
|
|
||||||
|
|
||||||
uv__free(addresses);
|
uv__free(addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user