From fbc43a72791c50ba02c0c500551bf87afdd833b3 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Mon, 26 Jan 2015 17:32:19 +0100 Subject: [PATCH] BNetworkInterfaceAddress: missing initialization * As it doesn't rely on BNetworkAddress anymore, BNetworkInterfaceAddress must now take care of initializing the addresses itself. * Also add some input sanitization and and asserts to ease detecting such problems. * Fixes #11778. --- src/kits/network/NetworkInterfaceAddress.cpp | 71 ++++++++++++++++++-- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/src/kits/network/NetworkInterfaceAddress.cpp b/src/kits/network/NetworkInterfaceAddress.cpp index 8620f470ea..a80d668537 100644 --- a/src/kits/network/NetworkInterfaceAddress.cpp +++ b/src/kits/network/NetworkInterfaceAddress.cpp @@ -6,7 +6,10 @@ #include +#include #include +#include +#include #include #include @@ -48,6 +51,10 @@ do_ifaliasreq(const char* name, int32 option, BNetworkInterfaceAddress& address, request.ifra_index = address.Index(); request.ifra_flags = address.Flags(); + assert(address.Address().sa_len <= sizeof(sockaddr_storage)); + assert(address.Mask().sa_len <= sizeof(sockaddr_storage)); + assert(address.Broadcast().sa_len <= sizeof(sockaddr_storage)); + memcpy(&request.ifra_addr, &address.Address(), address.Address().sa_len); memcpy(&request.ifra_mask, &address.Mask(), @@ -81,6 +88,14 @@ BNetworkInterfaceAddress::BNetworkInterfaceAddress() fIndex(-1), fFlags(0) { + fAddress.ss_family = AF_UNSPEC; + fAddress.ss_len = 2; + + fMask.ss_family = AF_UNSPEC; + fMask.ss_len = 2; + + fBroadcast.ss_family = AF_UNSPEC; + fBroadcast.ss_len = 2; } @@ -100,28 +115,76 @@ BNetworkInterfaceAddress::SetTo(const char* name, int32 index) void BNetworkInterfaceAddress::SetAddress(const sockaddr& address) { - memcpy(&fAddress, &address, address.sa_len); + size_t length = min_c(sizeof(sockaddr_storage), address.sa_len); + switch (address.sa_family) { + case AF_INET: + length = sizeof(sockaddr_in); + break; + case AF_INET6: + length = sizeof(sockaddr_in6); + break; + case AF_LINK: + { + sockaddr_dl& link = (sockaddr_dl&)address; + length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen + + link.sdl_nlen + link.sdl_slen; + break; + } + } + memcpy(&fAddress, &address, length); } void BNetworkInterfaceAddress::SetMask(const sockaddr& mask) { - memcpy(&fMask, &mask, mask.sa_len); + size_t length = min_c(sizeof(sockaddr_storage), mask.sa_len); + switch (mask.sa_family) { + case AF_INET: + length = sizeof(sockaddr_in); + break; + case AF_INET6: + length = sizeof(sockaddr_in6); + break; + case AF_LINK: + { + sockaddr_dl& link = (sockaddr_dl&)mask; + length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen + + link.sdl_nlen + link.sdl_slen; + break; + } + } + memcpy(&fMask, &mask, length); } void BNetworkInterfaceAddress::SetBroadcast(const sockaddr& broadcast) { - memcpy(&fBroadcast, &broadcast, broadcast.sa_len); + size_t length = min_c(sizeof(sockaddr_storage), broadcast.sa_len); + switch (broadcast.sa_family) { + case AF_INET: + length = sizeof(sockaddr_in); + break; + case AF_INET6: + length = sizeof(sockaddr_in6); + break; + case AF_LINK: + { + sockaddr_dl& link = (sockaddr_dl&)broadcast; + length = sizeof(sockaddr_dl) - sizeof(link.sdl_data) + link.sdl_alen + + link.sdl_nlen + link.sdl_slen; + break; + } + } + memcpy(&fBroadcast, &broadcast, length); } void BNetworkInterfaceAddress::SetDestination(const sockaddr& destination) { - memcpy(&fBroadcast, &destination, destination.sa_len); + SetBroadcast(destination); }