Skip to content

Commit ab1d3ec

Browse files
committed
net: Add optional length checking to CService::SetSockAddr
In almost all cases (the only exception is `getifaddrs`), we know the size of the data passed into SetSockAddr, so we can check this to be what is expected.
1 parent 35bf426 commit ab1d3ec

File tree

5 files changed

+15
-13
lines changed

5 files changed

+15
-13
lines changed

src/common/netif.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,16 +169,9 @@ std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
169169

170170
std::optional<CNetAddr> FromSockAddr(const struct sockaddr* addr)
171171
{
172-
// Check valid length. Note that sa_len is not part of POSIX, and exists on MacOS and some BSDs only, so we can't
173-
// do this check in SetSockAddr.
174-
if (!(addr->sa_family == AF_INET && addr->sa_len == sizeof(struct sockaddr_in)) &&
175-
!(addr->sa_family == AF_INET6 && addr->sa_len == sizeof(struct sockaddr_in6))) {
176-
return std::nullopt;
177-
}
178-
179172
// Fill in a CService from the sockaddr, then drop the port part.
180173
CService service;
181-
if (service.SetSockAddr(addr)) {
174+
if (service.SetSockAddr(addr, addr->sa_len)) {
182175
return (CNetAddr)service;
183176
}
184177
return std::nullopt;

src/common/pcp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonc
426426
return MappingError::NETWORK_ERROR;
427427
}
428428
CService internal;
429-
if (!internal.SetSockAddr((struct sockaddr*)&internal_addr)) return MappingError::NETWORK_ERROR;
429+
if (!internal.SetSockAddr((struct sockaddr*)&internal_addr, internal_addrlen)) return MappingError::NETWORK_ERROR;
430430
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "pcp: Internal address after connect: %s\n", internal.ToStringAddr());
431431

432432
// Build request packet. Make sure the packet is zeroed so that reserved fields are zero

src/net.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ static CAddress GetBindAddress(const Sock& sock)
383383
struct sockaddr_storage sockaddr_bind;
384384
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
385385
if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
386-
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
386+
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind, sockaddr_bind_len);
387387
} else {
388388
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
389389
}
@@ -1728,7 +1728,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
17281728
return;
17291729
}
17301730

1731-
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
1731+
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) {
17321732
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n");
17331733
} else {
17341734
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};

src/netaddress.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,13 +807,15 @@ CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, a
807807
assert(addr.sin6_family == AF_INET6);
808808
}
809809

810-
bool CService::SetSockAddr(const struct sockaddr *paddr)
810+
bool CService::SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
811811
{
812812
switch (paddr->sa_family) {
813813
case AF_INET:
814+
if (addrlen != sizeof(struct sockaddr_in)) return false;
814815
*this = CService(*(const struct sockaddr_in*)paddr);
815816
return true;
816817
case AF_INET6:
818+
if (addrlen != sizeof(struct sockaddr_in6)) return false;
817819
*this = CService(*(const struct sockaddr_in6*)paddr);
818820
return true;
819821
default:

src/netaddress.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,14 @@ class CService : public CNetAddr
539539
explicit CService(const struct sockaddr_in& addr);
540540
uint16_t GetPort() const;
541541
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
542-
bool SetSockAddr(const struct sockaddr* paddr);
542+
/**
543+
* Set CService from a network sockaddr.
544+
* @param[in] paddr Pointer to sockaddr structure
545+
* @param[in] addrlen Length of sockaddr structure in bytes. This will be checked to exactly match the length of
546+
* a socket address of the provided family, unless std::nullopt is passed
547+
* @returns true on success
548+
*/
549+
bool SetSockAddr(const struct sockaddr* paddr, socklen_t addrlen);
543550
/**
544551
* Get the address family
545552
* @returns AF_UNSPEC if unspecified

0 commit comments

Comments
 (0)