diff options
| author | F. Aragon <paco@voltanet.io> | 2018-07-03 20:07:25 +0200 | 
|---|---|---|
| committer | F. Aragon <paco@voltanet.io> | 2018-07-04 00:01:22 +0200 | 
| commit | 4149ef7c0f0876a2b9fdfe34afc1ecd9036b2382 (patch) | |
| tree | 22341ea9b9bcd5bb71483cf5559f7906233690d5 /ldpd/pfkey.c | |
| parent | 7f04893904881c2822a3736d004358a0dad9f959 (diff) | |
ldpd: buffer underflow, thread safety (PVS-Studio)
This commit fixes two issues:
- memcpy() using containers of different sizes when using addr2sa(), mixing
  'struct sockaddr_storage' and 'union sockunion'.
- addr2sa() function not being thread safe (using a local static variable as
  container.
Signed-off-by: F. Aragon <paco@voltanet.io>
Diffstat (limited to 'ldpd/pfkey.c')
| -rw-r--r-- | ldpd/pfkey.c | 38 | 
1 files changed, 20 insertions, 18 deletions
diff --git a/ldpd/pfkey.c b/ldpd/pfkey.c index a1a79dabfd..906737217c 100644 --- a/ldpd/pfkey.c +++ b/ldpd/pfkey.c @@ -64,17 +64,17 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,  	ssize_t			n;  	int			len = 0;  	int			iov_cnt; -	struct sockaddr_storage	ssrc, sdst, smask, dmask; -	struct sockaddr		*saptr; +	struct sockaddr_storage	smask, dmask; +	union sockunion		su_src, su_dst;  	if (!pid)  		pid = getpid();  	/* we need clean sockaddr... no ports set */ -	memset(&ssrc, 0, sizeof(ssrc));  	memset(&smask, 0, sizeof(smask)); -	if ((saptr = addr2sa(af, src, 0))) -		memcpy(&ssrc, saptr, sizeof(ssrc)); + +	addr2sa(af, src, 0, &su_src); +  	switch (af) {  	case AF_INET:  		memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8); @@ -86,13 +86,13 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,  	default:  		return (-1);  	} -	smask.ss_family = ssrc.ss_family; -	smask.ss_len = ssrc.ss_len; +	smask.ss_family = su_src.sa.sa_family; +	smask.ss_len = sockaddr_len(&su_src.sa); -	memset(&sdst, 0, sizeof(sdst));  	memset(&dmask, 0, sizeof(dmask)); -	if ((saptr = addr2sa(af, dst, 0))) -		memcpy(&sdst, saptr, sizeof(sdst)); + +	addr2sa(af, dst, 0, &su_dst); +  	switch (af) {  	case AF_INET:  		memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8); @@ -104,8 +104,8 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,  	default:  		return (-1);  	} -	dmask.ss_family = sdst.ss_family; -	dmask.ss_len = sdst.ss_len; +	dmask.ss_family = su_dst.sa.sa_family; +	dmask.ss_len = sockaddr_len(&su_dst.sa);  	memset(&smsg, 0, sizeof(smsg));  	smsg.sadb_msg_version = PF_KEY_V2; @@ -138,11 +138,13 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,  	memset(&sa_src, 0, sizeof(sa_src));  	sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; -	sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8; +	sa_src.sadb_address_len = +		(sizeof(sa_src) + ROUNDUP(sockaddr_len(&su_src.sa))) / 8;  	memset(&sa_dst, 0, sizeof(sa_dst));  	sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; -	sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8; +	sa_dst.sadb_address_len = +		(sizeof(sa_dst) + ROUNDUP(sockaddr_len(&su_dst.sa))) / 8;  	sa.sadb_sa_auth = aalg;  	sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */ @@ -195,8 +197,8 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,  	iov[iov_cnt].iov_base = &sa_dst;  	iov[iov_cnt].iov_len = sizeof(sa_dst);  	iov_cnt++; -	iov[iov_cnt].iov_base = &sdst; -	iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len); +	iov[iov_cnt].iov_base = &su_dst; +	iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_dst.sa));  	smsg.sadb_msg_len += sa_dst.sadb_address_len;  	iov_cnt++; @@ -204,8 +206,8 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,  	iov[iov_cnt].iov_base = &sa_src;  	iov[iov_cnt].iov_len = sizeof(sa_src);  	iov_cnt++; -	iov[iov_cnt].iov_base = &ssrc; -	iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len); +	iov[iov_cnt].iov_base = &su_src; +	iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_src.sa));  	smsg.sadb_msg_len += sa_src.sadb_address_len;  	iov_cnt++;  | 
