File libpcap-CVE-2023-7256.patch of Package libpcap.35577
From 2aa69b04d8173b18a0e3492e0c8f2f7fabdf642d Mon Sep 17 00:00:00 2001
From: Guy Harris <gharris@sonic.net>
Date: Thu, 28 Sep 2023 00:37:57 -0700
Subject: [PATCH] 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.
---
pcap-rpcap.c | 48 ++++++++++++++++++++--------------------
rpcapd/daemon.c | 8 +++++--
rpcapd/rpcapd.c | 8 +++++--
sockutils.c | 58 ++++++++++++++++++++++++++++---------------------
sockutils.h | 5 ++---
5 files changed, 72 insertions(+), 55 deletions(-)
Index: libpcap-1.8.1/pcap-rpcap.c
===================================================================
--- libpcap-1.8.1.orig/pcap-rpcap.c
+++ libpcap-1.8.1/pcap-rpcap.c
@@ -761,15 +761,17 @@ int pcap_opensource_remote(pcap_t *fp, s
if ((ctrlport == NULL) || (ctrlport[0] == 0))
{
/* the user chose not to specify the port */
- if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
- return -1;
+ addrinfo = sock_initaddress(host, RPCAP_DEFAULT_NETPORT,
+ &hints, errbuf, PCAP_ERRBUF_SIZE);
}
else
{
/* the user chose not to specify the port */
- if (sock_initaddress(host, ctrlport, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
- return -1;
+ addrinfo = sock_initaddress(host, port, &hints,
+ errbuf, PCAP_ERRBUF_SIZE);
}
+ if (addrinfo == NULL)
+ return -1;
if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
goto error;
@@ -999,8 +1001,10 @@ int pcap_startcapture_remote(pcap_t *fp)
hints.ai_flags = AI_PASSIVE; /* Data connection is opened by the server toward the client */
/* Let's the server pick up a free network port for us */
- if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
- goto error;
+ addrinfo = sock_initaddress(NULL, "0", &hints, fp->errbuf,
+ PCAP_ERRBUF_SIZE);
+ if (addrinfo == NULL)
+ goto error;
if ((sockdata = sock_open(addrinfo, SOCKOPEN_SERVER,
1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
@@ -1135,8 +1139,10 @@ int pcap_startcapture_remote(pcap_t *fp)
pcap_snprintf(portdata, PCAP_BUF_SIZE, "%d", ntohs(startcapreply.portdata));
/* Let's the server pick up a free network port for us */
- if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
- goto error;
+ addrinfo = sock_initaddress(host, portstring, &hints,
+ fp->errbuf, PCAP_ERRBUF_SIZE);
+ if (addrinfo == NULL)
+ goto error;
if ((sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
goto error;
@@ -2082,7 +2088,6 @@ SOCKET rpcap_remoteact_getsock(const cha
{
struct activehosts *temp; /* temp var needed to scan the host list chain */
struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
- int retval;
/* retrieve the network address corresponding to 'host' */
addrinfo = NULL;
@@ -2090,8 +2095,9 @@ SOCKET rpcap_remoteact_getsock(const cha
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
- retval = getaddrinfo(host, "0", &hints, &addrinfo);
- if (retval != 0)
+ addrinfo = sock_initaddress(host, "0", &hints, errbuf,
+ PCAP_ERRBUF_SIZE);
+ if (addrinfo == NULL)
{
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
*isactive = 0;
Index: libpcap-1.8.1/sockutils.c
===================================================================
--- libpcap-1.8.1.orig/sockutils.c
+++ libpcap-1.8.1/sockutils.c
@@ -473,15 +473,19 @@ int sock_close(SOCKET sock, char *errbuf
* of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
* the programmer to look at that function in order to set the 'hints' variable appropriately.
*/
-int sock_initaddress(const char *host, const char *port,
- struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
+struct addrinfo *sock_initaddress(const char *host, const char *port,
+ struct addrinfo *hints, char *errbuf, int errbuflen)
{
+ struct addrinfo *addrinfo;
int retval;
- retval = getaddrinfo(host, port, hints, addrinfo);
+ retval = getaddrinfo(host, port == NULL ? "0", hints, &addrinfo);
if (retval != 0)
{
/*
+ * That call failed.
+ * Determine whether the problem is that the host is bad.
+ *
* if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
* error routines (errno) in UNIX; Winsock suggests using the GetLastError() instead.
*/
@@ -493,7 +497,7 @@ int sock_initaddress(const char *host, c
pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
#endif
}
- return -1;
+ return NULL;
}
/*
* \warning SOCKET: I should check all the accept() in order to bind to all addresses in case
@@ -508,26 +512,28 @@ int sock_initaddress(const char *host, c
* ignore all addresses that are neither? (What, no IPX
* support? :-))
*/
- if (((*addrinfo)->ai_family != PF_INET) &&
- ((*addrinfo)->ai_family != PF_INET6))
+ if ((addrinfo->ai_family != PF_INET) &&
+ (addrinfo->ai_family != PF_INET6))
{
if (errbuf)
pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
- return -1;
+ freeaddrinfo(addrinfo);
+ return NULL;
}
/*
* You can't do multicast (or broadcast) TCP.
*/
- if (((*addrinfo)->ai_socktype == SOCK_STREAM) &&
- (sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
+ if ((addrinfo->ai_socktype == SOCK_STREAM) &&
+ (sock_ismcastaddr(addrinfo->ai_addr) == 0))
{
if (errbuf)
pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
- return -1;
+ freeaddrinfo(addrinfo);
+ return NULL;
}
- return 0;
+ return addrinfo;
}
/*
@@ -1200,7 +1206,6 @@ int sock_getascii_addrport(const struct
*/
int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen)
{
- int retval;
struct addrinfo *addrinfo;
struct addrinfo hints;
@@ -1208,7 +1213,9 @@ int sock_present2network(const char *add
hints.ai_family = addr_family;
- if ((retval = sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1)
+ addrinfo = sock_initaddress(address, "22222" /* fake port */, &hints,
+ errbuf, errbuflen);
+ if (addrinfo == NULL)
return 0;
if (addrinfo->ai_family == PF_INET)
Index: libpcap-1.8.1/sockutils.h
===================================================================
--- libpcap-1.8.1.orig/sockutils.h
+++ libpcap-1.8.1/sockutils.h
@@ -207,9 +207,8 @@ int sock_init(char *errbuf, int errbufle
void sock_cleanup(void);
/* It is 'public' because there are calls (like accept() ) which are not managed from inside the sockutils files */
void sock_geterror(const char *caller, char *errbuf, int errbufsize);
-int sock_initaddress(const char *address, const char *port,
- struct addrinfo *hints, struct addrinfo **addrinfo,
- char *errbuf, int errbuflen);
+struct addrinfo *sock_initaddress(const char *address, const char *port,
+ struct addrinfo *hints, char *errbuf, int errbuflen);
int sock_recv(SOCKET socket, void *buffer, size_t size, int receiveall,
char *errbuf, int errbuflen);
SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen);
Index: libpcap-1.8.1/pcap-new.c
===================================================================
--- libpcap-1.8.1.orig/pcap-new.c
+++ libpcap-1.8.1/pcap-new.c
@@ -372,14 +372,16 @@ int pcap_findalldevs_ex(char *source, st
if (port[0] == 0)
{
/* the user chose not to specify the port */
- if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
- return -1;
+ addrinfo = sock_initaddress(host, RPCAP_DEFAULT_NETPORT,
+ &hints, errbuf, PCAP_ERRBUF_SIZE);
}
else
{
- if (sock_initaddress(host, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
- return -1;
+ addrinfo = sock_initaddress(host, port, &hints,
+ errbuf, PCAP_ERRBUF_SIZE);
}
+ if (addrinfo == NULL)
+ return -1;
if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
goto error;
@@ -1025,21 +1027,19 @@ SOCKET pcap_remoteact_accept(const char
/* Do the work */
if ((port == NULL) || (port[0] == 0))
{
- if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
- {
- SOCK_ASSERT(errbuf, 1);
- return -2;
- }
+ addrinfo = sock_initaddress(address,
+ RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, errbuf,
+ PCAP_ERRBUF_SIZE);
}
else
{
- if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
- {
- SOCK_ASSERT(errbuf, 1);
- return -2;
- }
+ addrinfo = sock_initaddress(address, port, &hints, errbuf,
+ PCAP_ERRBUF_SIZE);
}
-
+ if (addrinfo == NULL)
+ {
+ return (SOCKET)-2;
+ }
if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == -1)
{
@@ -1135,7 +1135,6 @@ int pcap_remoteact_close(const char *hos
{
struct activehosts *temp, *prev; /* temp var needed to scan the host list chain */
struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
- int retval;
temp = activeHosts;
prev = NULL;
@@ -1146,12 +1145,12 @@ int pcap_remoteact_close(const char *hos
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
- retval = getaddrinfo(host, "0", &hints, &addrinfo);
- if (retval != 0)
- {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
- return -1;
- }
+ addrinfo = sock_initaddress(host, "0", &hints, errbuf,
+ PCAP_ERRBUF_SIZE);
+ if (addrinfo == NULL)
+ {
+ return -1;
+ }
while (temp)
{