Skip to content

Commit 262e4f3

Browse files
committed
Have sock_initaddress() return the list of addrinfo structures or NULL.
Its return address is currently 0 for success and -1 for failure, with a pointer to the first element of the list of struct addrinfos returned through a pointer on success; change it to return that pointer on success and NULL on failure. That way, we don't have to worry about what happens to the pointer pointeed to by the argument in question on failure; we know that we got NULL back if no struct addrinfos were found because getaddrinfo() failed. Thus, we know that we have something to free iff sock_initaddress() returned a pointer to that something rather than returning NULL. This avoids a double-free in some cases. This is apparently CVE-2023-40400.
1 parent 2352738 commit 262e4f3

File tree

5 files changed

+75
-58
lines changed

5 files changed

+75
-58
lines changed

pcap-rpcap.c

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,17 +1024,16 @@ rpcap_remoteact_getsock(const char *host, int *error, char *errbuf)
10241024
{
10251025
struct activehosts *temp; /* temp var needed to scan the host list chain */
10261026
struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
1027-
int retval;
10281027

10291028
/* retrieve the network address corresponding to 'host' */
10301029
addrinfo = NULL;
10311030
memset(&hints, 0, sizeof(struct addrinfo));
10321031
hints.ai_family = PF_UNSPEC;
10331032
hints.ai_socktype = SOCK_STREAM;
10341033

1035-
retval = sock_initaddress(host, NULL, &hints, &addrinfo, errbuf,
1034+
addrinfo = sock_initaddress(host, NULL, &hints, errbuf,
10361035
PCAP_ERRBUF_SIZE);
1037-
if (retval != 0)
1036+
if (addrinfo == NULL)
10381037
{
10391038
*error = 1;
10401039
return NULL;
@@ -1186,7 +1185,9 @@ static int pcap_startcapture_remote(pcap_t *fp)
11861185
hints.ai_flags = AI_PASSIVE; /* Data connection is opened by the server toward the client */
11871186

11881187
/* Let's the server pick up a free network port for us */
1189-
if (sock_initaddress(NULL, NULL, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
1188+
addrinfo = sock_initaddress(NULL, NULL, &hints, fp->errbuf,
1189+
PCAP_ERRBUF_SIZE);
1190+
if (addrinfo == NULL)
11901191
goto error_nodiscard;
11911192

11921193
if ((sockdata = sock_open(NULL, addrinfo, SOCKOPEN_SERVER,
@@ -1311,7 +1312,9 @@ static int pcap_startcapture_remote(pcap_t *fp)
13111312
snprintf(portstring, PCAP_BUF_SIZE, "%d", ntohs(startcapreply.portdata));
13121313

13131314
/* Let's the server pick up a free network port for us */
1314-
if (sock_initaddress(host, portstring, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
1315+
addrinfo = sock_initaddress(host, portstring, &hints,
1316+
fp->errbuf, PCAP_ERRBUF_SIZE);
1317+
if (addrinfo == NULL)
13151318
goto error;
13161319

13171320
if ((sockdata = sock_open(host, addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
@@ -2418,16 +2421,16 @@ rpcap_setup_session(const char *source, struct pcap_rmtauth *auth,
24182421
if (port[0] == 0)
24192422
{
24202423
/* the user chose not to specify the port */
2421-
if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT,
2422-
&hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
2423-
return -1;
2424+
addrinfo = sock_initaddress(host, RPCAP_DEFAULT_NETPORT,
2425+
&hints, errbuf, PCAP_ERRBUF_SIZE);
24242426
}
24252427
else
24262428
{
2427-
if (sock_initaddress(host, port, &hints, &addrinfo,
2428-
errbuf, PCAP_ERRBUF_SIZE) == -1)
2429-
return -1;
2429+
addrinfo = sock_initaddress(host, port, &hints,
2430+
errbuf, PCAP_ERRBUF_SIZE);
24302431
}
2432+
if (addrinfo == NULL)
2433+
return -1;
24312434

24322435
if ((*sockctrlp = sock_open(host, addrinfo, SOCKOPEN_CLIENT, 0,
24332436
errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
@@ -3038,19 +3041,19 @@ SOCKET pcap_remoteact_accept_ex(const char *address, const char *port, const cha
30383041
/* Do the work */
30393042
if ((port == NULL) || (port[0] == 0))
30403043
{
3041-
if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
3042-
{
3043-
return (SOCKET)-2;
3044-
}
3044+
addrinfo = sock_initaddress(address,
3045+
RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, errbuf,
3046+
PCAP_ERRBUF_SIZE);
30453047
}
30463048
else
30473049
{
3048-
if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
3049-
{
3050-
return (SOCKET)-2;
3051-
}
3050+
addrinfo = sock_initaddress(address, port, &hints, errbuf,
3051+
PCAP_ERRBUF_SIZE);
3052+
}
3053+
if (addrinfo == NULL)
3054+
{
3055+
return (SOCKET)-2;
30523056
}
3053-
30543057

30553058
if ((sockmain = sock_open(NULL, addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
30563059
{
@@ -3210,7 +3213,6 @@ int pcap_remoteact_close(const char *host, char *errbuf)
32103213
{
32113214
struct activehosts *temp, *prev; /* temp var needed to scan the host list chain */
32123215
struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
3213-
int retval;
32143216

32153217
temp = activeHosts;
32163218
prev = NULL;
@@ -3221,9 +3223,9 @@ int pcap_remoteact_close(const char *host, char *errbuf)
32213223
hints.ai_family = PF_UNSPEC;
32223224
hints.ai_socktype = SOCK_STREAM;
32233225

3224-
retval = sock_initaddress(host, NULL, &hints, &addrinfo, errbuf,
3226+
addrinfo = sock_initaddress(host, NULL, &hints, errbuf,
32253227
PCAP_ERRBUF_SIZE);
3226-
if (retval != 0)
3228+
if (addrinfo == NULL)
32273229
{
32283230
return -1;
32293231
}

rpcapd/daemon.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,9 @@ daemon_msg_startcap_req(uint8_t ver, struct daemon_slpars *pars, uint32_t plen,
20852085
goto error;
20862086
}
20872087

2088-
if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
2088+
addrinfo = sock_initaddress(peerhost, portdata, &hints,
2089+
errmsgbuf, PCAP_ERRBUF_SIZE);
2090+
if (addrinfo == NULL)
20892091
goto error;
20902092

20912093
if ((session->sockdata = sock_open(peerhost, addrinfo, SOCKOPEN_CLIENT, 0, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
@@ -2098,15 +2100,17 @@ daemon_msg_startcap_req(uint8_t ver, struct daemon_slpars *pars, uint32_t plen,
20982100
if (data_port[0] != '\0')
20992101
{
21002102
// Use the specified network port
2101-
if (sock_initaddress(NULL, data_port, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
2102-
goto error;
2103+
addrinfo = sock_initaddress(NULL, data_port, &hints,
2104+
errmsgbuf, PCAP_ERRBUF_SIZE);
21032105
}
21042106
else
21052107
{
21062108
// Make the server socket pick up a free network port for us
2107-
if (sock_initaddress(NULL, NULL, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
2108-
goto error;
2109+
addrinfo = sock_initaddress(NULL, NULL, &hints,
2110+
errmsgbuf, PCAP_ERRBUF_SIZE);
21092111
}
2112+
if (addrinfo == NULL)
2113+
goto error;
21102114

21112115
if ((session->sockdata = sock_open(NULL, addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
21122116
goto error;

rpcapd/rpcapd.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,9 @@ void main_startup(void)
618618
//
619619
// Get a list of sockets on which to listen.
620620
//
621-
if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
621+
addrinfo = sock_initaddress((address[0]) ? address : NULL,
622+
port, &mainhints, errbuf, PCAP_ERRBUF_SIZE);
623+
if (addrinfo == NULL)
622624
{
623625
rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
624626
return;
@@ -1357,7 +1359,9 @@ main_active(void *ptr)
13571359
memset(errbuf, 0, sizeof(errbuf));
13581360

13591361
// Do the work
1360-
if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
1362+
addrinfo = sock_initaddress(activepars->address, activepars->port,
1363+
&hints, errbuf, PCAP_ERRBUF_SIZE);
1364+
if (addrinfo == NULL)
13611365
{
13621366
rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
13631367
return 0;

sockutils.c

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,20 +1069,21 @@ get_gai_errstring(char *errbuf, int errbuflen, const char *prefix, int err,
10691069
* \param errbuflen: length of the buffer that will contains the error. The error message cannot be
10701070
* larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
10711071
*
1072-
* \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
1073-
* in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is
1074-
* returned into the addrinfo parameter.
1072+
* \return a pointer to the first element in a list of addrinfo structures
1073+
* if everything is fine, NULL if some errors occurred. The error message
1074+
* is returned in the 'errbuf' variable.
10751075
*
1076-
* \warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when
1077-
* it is no longer needed.
1076+
* \warning The list of addrinfo structures returned has to be deleted by
1077+
* the programmer by calling freeaddrinfo() when it is no longer needed.
10781078
*
10791079
* \warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same
10801080
* of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
10811081
* the programmer to look at that function in order to set the 'hints' variable appropriately.
10821082
*/
1083-
int sock_initaddress(const char *host, const char *port,
1084-
struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
1083+
struct addrinfo *sock_initaddress(const char *host, const char *port,
1084+
struct addrinfo *hints, char *errbuf, int errbuflen)
10851085
{
1086+
struct addrinfo *addrinfo;
10861087
int retval;
10871088

10881089
/*
@@ -1094,9 +1095,13 @@ int sock_initaddress(const char *host, const char *port,
10941095
* as those messages won't talk about a problem with the port if
10951096
* no port was specified.
10961097
*/
1097-
retval = getaddrinfo(host, port == NULL ? "0" : port, hints, addrinfo);
1098+
retval = getaddrinfo(host, port == NULL ? "0" : port, hints, &addrinfo);
10981099
if (retval != 0)
10991100
{
1101+
/*
1102+
* That call failed.
1103+
* Determine whether the problem is that the host is bad.
1104+
*/
11001105
if (errbuf)
11011106
{
11021107
if (host != NULL && port != NULL) {
@@ -1108,7 +1113,7 @@ int sock_initaddress(const char *host, const char *port,
11081113
int try_retval;
11091114

11101115
try_retval = getaddrinfo(host, NULL, hints,
1111-
addrinfo);
1116+
&addrinfo);
11121117
if (try_retval == 0) {
11131118
/*
11141119
* Worked with just the host,
@@ -1117,28 +1122,31 @@ int sock_initaddress(const char *host, const char *port,
11171122
*
11181123
* Free up the address info first.
11191124
*/
1120-
freeaddrinfo(*addrinfo);
1125+
freeaddrinfo(addrinfo);
11211126
get_gai_errstring(errbuf, errbuflen,
11221127
"", retval, NULL, port);
11231128
} else {
11241129
/*
11251130
* Didn't work with just the host,
11261131
* so assume the problem is
1127-
* with the host.
1132+
* with the host; we assume
1133+
* the original error indicates
1134+
* the underlying problem.
11281135
*/
11291136
get_gai_errstring(errbuf, errbuflen,
11301137
"", retval, host, NULL);
11311138
}
11321139
} else {
11331140
/*
11341141
* Either the host or port was null, so
1135-
* there's nothing to determine.
1142+
* there's nothing to determine; report
1143+
* the error from the original call.
11361144
*/
11371145
get_gai_errstring(errbuf, errbuflen, "",
11381146
retval, host, port);
11391147
}
11401148
}
1141-
return -1;
1149+
return NULL;
11421150
}
11431151
/*
11441152
* \warning SOCKET: I should check all the accept() in order to bind to all addresses in case
@@ -1153,30 +1161,28 @@ int sock_initaddress(const char *host, const char *port,
11531161
* ignore all addresses that are neither? (What, no IPX
11541162
* support? :-))
11551163
*/
1156-
if (((*addrinfo)->ai_family != PF_INET) &&
1157-
((*addrinfo)->ai_family != PF_INET6))
1164+
if ((addrinfo->ai_family != PF_INET) &&
1165+
(addrinfo->ai_family != PF_INET6))
11581166
{
11591167
if (errbuf)
11601168
snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
1161-
freeaddrinfo(*addrinfo);
1162-
*addrinfo = NULL;
1163-
return -1;
1169+
freeaddrinfo(addrinfo);
1170+
return NULL;
11641171
}
11651172

11661173
/*
11671174
* You can't do multicast (or broadcast) TCP.
11681175
*/
1169-
if (((*addrinfo)->ai_socktype == SOCK_STREAM) &&
1170-
(sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
1176+
if ((addrinfo->ai_socktype == SOCK_STREAM) &&
1177+
(sock_ismcastaddr(addrinfo->ai_addr) == 0))
11711178
{
11721179
if (errbuf)
11731180
snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
1174-
freeaddrinfo(*addrinfo);
1175-
*addrinfo = NULL;
1176-
return -1;
1181+
freeaddrinfo(addrinfo);
1182+
return NULL;
11771183
}
11781184

1179-
return 0;
1185+
return addrinfo;
11801186
}
11811187

11821188
/*
@@ -2089,7 +2095,9 @@ int sock_present2network(const char *address, struct sockaddr_storage *sockaddr,
20892095

20902096
hints.ai_family = addr_family;
20912097

2092-
if (sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen) == -1)
2098+
addrinfo = sock_initaddress(address, "22222" /* fake port */, &hints,
2099+
errbuf, errbuflen);
2100+
if (addrinfo == NULL)
20932101
return 0;
20942102

20952103
if (addrinfo->ai_family == PF_INET)

sockutils.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@ void sock_fmterrmsg(char *errbuf, size_t errbuflen, int errcode,
138138
PCAP_FORMAT_STRING(const char *fmt), ...) PCAP_PRINTFLIKE(4, 5);
139139
void sock_geterrmsg(char *errbuf, size_t errbuflen,
140140
PCAP_FORMAT_STRING(const char *fmt), ...) PCAP_PRINTFLIKE(3, 4);
141-
int sock_initaddress(const char *address, const char *port,
142-
struct addrinfo *hints, struct addrinfo **addrinfo,
143-
char *errbuf, int errbuflen);
141+
struct addrinfo *sock_initaddress(const char *address, const char *port,
142+
struct addrinfo *hints, char *errbuf, int errbuflen);
144143
int sock_recv(SOCKET sock, SSL *, void *buffer, size_t size, int receiveall,
145144
char *errbuf, int errbuflen);
146145
int sock_recv_dgram(SOCKET sock, SSL *, void *buffer, size_t size,

0 commit comments

Comments
 (0)