git: 88b04633c29e - main - libpcap: fix resource leaks and set error messages

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Mon, 22 Dec 2025 02:23:52 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=88b04633c29e3a8fd2ac88febd1aedf409ce6925

commit 88b04633c29e3a8fd2ac88febd1aedf409ce6925
Author:     Guy Harris <gharris@sonic.net>
AuthorDate: 2025-12-22 01:26:32 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-12-22 02:23:28 +0000

    libpcap: fix resource leaks and set error messages
    
    In finddevs_bpf() close the BPF device descriptor and free the device list
    buffer before returning.
    
    For ioctl() and malloc() errors, use pcapint_fmt_errmsg_for_errno() to
    generate an error message.
    
    Fix some comments.
    
    (cherry picked from commit 6870404f35da32d63a0a8789edb010842dd6b208)
---
 contrib/libpcap/pcap-bpf.c | 44 +++++++++++++++++++++++++++++++++++++-------
 1 file changed, 37 insertions(+), 7 deletions(-)

diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c
index 83a363eee0bd..9ca8df156219 100644
--- a/contrib/libpcap/pcap-bpf.c
+++ b/contrib/libpcap/pcap-bpf.c
@@ -45,7 +45,7 @@
 
 #if defined(__FreeBSD__) && __FreeBSD_version < 1600006
 /*
- * Add support for capturing on FreeBSD usbusN interfaces.
+ * Add support for creating FreeBSD usbusN interfaces as necessary.
  */
 static const char usbus_prefix[] = "usbus";
 #define USBUS_PREFIX_LEN	(sizeof(usbus_prefix) - 1)
@@ -2039,8 +2039,8 @@ pcap_activate_bpf(pcap_t *p)
 
 #if defined(__FreeBSD__) && __FreeBSD_version < 1600006
 	/*
-	 * If this is legacy FreeBSD, and the device name begins with "usbus",
-	 * try to create the interface if it's not available.
+	 * If this is FreeBSD 15 or earlier, and the device name begins
+	 * with "usbus", try to create the interface if it's not available.
 	 */
 	if (strncmp(p->opt.device, usbus_prefix, USBUS_PREFIX_LEN) == 0) {
 		/*
@@ -2879,18 +2879,48 @@ finddevs_bpf(pcap_if_list_t *devlistp, char *errbuf)
 	const char *name;
 	int fd;
 
-	if ((fd = bpf_open(errbuf)) < 0)
+	if ((fd = bpf_open(errbuf)) < 0) {
+		/*
+		 * XXX - this just means we won't have permission to
+		 * open any BPF devices, an thus we don't have
+		 * permission to capture on network interfaces.
+		 */
 		return (-1);
+	}
 
 	memset(&bi, 0, sizeof(bi));
-	if (ioctl(fd, BIOCGETIFLIST, (caddr_t)&bi) != 0 || bi.bi_size == 0)
+	if (ioctl(fd, BIOCGETIFLIST, (caddr_t)&bi) != 0) {
+		pcapint_fmt_errmsg_for_errno(errbuf,
+		    PCAP_ERRBUF_SIZE, errno, "BIOCGETIFLIST to get buffer size");
+		close(fd);
 		return (-1);
+	}
+	if (bi.bi_size == 0) {
+		/*
+		 * There are no devices attached to BPF.
+		 * This means that, in practice, whatever network
+		 * interfaces we found don't support packet capture
+		 * or injection.
+		 */
+		close(fd);
+		return (0);
+	}
 
-	if ((bi.bi_ubuf = malloc(bi.bi_size)) == NULL)
+	if ((bi.bi_ubuf = malloc(bi.bi_size)) == NULL) {
+		pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+		    "malloc");
+		close(fd);
 		return (-1);
+	}
 
-	if (ioctl(fd, BIOCGETIFLIST, (caddr_t)&bi) != 0)
+	if (ioctl(fd, BIOCGETIFLIST, (caddr_t)&bi) != 0) {
+		pcapint_fmt_errmsg_for_errno(errbuf,
+		    PCAP_ERRBUF_SIZE, errno, "BIOCGETIFLIST to attached devics");
+		free(bi.bi_ubuf);
+		close(fd);
 		return (-1);
+	}
+	close(fd);
 
 	for (name = bi.bi_ubuf; bi.bi_count > 0;
 	    bi.bi_count--, name += strlen(name) + 1)