Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Feb 2026 17:56:11 +0000
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Cc:        Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav <des@FreeBSD.org>
Subject:   git: e4781e4e6d88 - releng/15.0 - blocklistd: Fix multiple bugs
Message-ID:  <698b713b.264d7.6229df2d@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch releng/15.0 has been updated by markj:

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

commit e4781e4e6d88f73d6fe266eb520c240a343fafcf
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-02-07 14:38:34 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-02-09 17:54:29 +0000

    blocklistd: Fix multiple bugs
    
    * Fix file descriptor leak in the server
    
    * Fix race between parent and child in popenve()
    
    * Don't assume fdopen() can't fail
    
    Approved by:    so
    Security:       FreeBSD-SA-26:03.blocklistd
    Security:       CVE-2026-2261
---
 contrib/blocklist/bin/blacklistd.c |  8 +++--
 contrib/blocklist/bin/blocklistd.c |  8 +++--
 contrib/blocklist/port/popenve.c   | 61 ++++++++++++++++++++------------------
 3 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/contrib/blocklist/bin/blacklistd.c b/contrib/blocklist/bin/blacklistd.c
index cb6ce6578d9c..6021e70f214c 100644
--- a/contrib/blocklist/bin/blacklistd.c
+++ b/contrib/blocklist/bin/blacklistd.c
@@ -191,7 +191,7 @@ process(bl_t bl)
 	}
 
 	if (getremoteaddress(bi, &rss, &rsl) == -1)
-		return;
+		goto out;
 
 	if (debug || bi->bi_msg[0]) {
 		sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss);
@@ -204,12 +204,12 @@ process(bl_t bl)
 
 	if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) {
 		(*lfun)(LOG_DEBUG, "no rule matched");
-		return;
+		goto out;
 	}
 
 
 	if (state_get(state, &c, &dbi) == -1)
-		return;
+		goto out;
 
 	if (debug) {
 		char b1[128], b2[128];
@@ -269,6 +269,8 @@ process(bl_t bl)
 	state_put(state, &c, &dbi);
 
 out:
+	close(bi->bi_fd);
+
 	if (debug) {
 		char b1[128], b2[128];
 		(*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d "
diff --git a/contrib/blocklist/bin/blocklistd.c b/contrib/blocklist/bin/blocklistd.c
index 47c145c7aae1..ffa2ff2d74a6 100644
--- a/contrib/blocklist/bin/blocklistd.c
+++ b/contrib/blocklist/bin/blocklistd.c
@@ -191,7 +191,7 @@ process(bl_t bl)
 	}
 
 	if (getremoteaddress(bi, &rss, &rsl) == -1)
-		return;
+		goto out;
 
 	if (debug || bi->bi_msg[0]) {
 		sockaddr_snprintf(rbuf, sizeof(rbuf), "%a:%p", (void *)&rss);
@@ -204,12 +204,12 @@ process(bl_t bl)
 
 	if (conf_find(bi->bi_fd, bi->bi_uid, &rss, &c) == NULL) {
 		(*lfun)(LOG_DEBUG, "no rule matched");
-		return;
+		goto out;
 	}
 
 
 	if (state_get(state, &c, &dbi) == -1)
-		return;
+		goto out;
 
 	if (debug) {
 		char b1[128], b2[128];
@@ -269,6 +269,8 @@ process(bl_t bl)
 	state_put(state, &c, &dbi);
 
 out:
+	close(bi->bi_fd);
+
 	if (debug) {
 		char b1[128], b2[128];
 		(*lfun)(LOG_DEBUG, "%s: final db state for %s: count=%d/%d "
diff --git a/contrib/blocklist/port/popenve.c b/contrib/blocklist/port/popenve.c
index bdff8cdc1de4..e80058a8599a 100644
--- a/contrib/blocklist/port/popenve.c
+++ b/contrib/blocklist/port/popenve.c
@@ -111,11 +111,25 @@ pdes_get(int *pdes, const char **type)
 #endif
 	}
 
-	if ((cur = malloc(sizeof(*cur))) != NULL)
-		return cur;
+	if ((cur = malloc(sizeof(*cur))) != NULL) {
+		if (**type == 'r') {
+			cur->fp = fdopen(pdes[0], *type);
+#ifdef _REENTRANT
+			cur->fd = pdes[0];
+#endif
+		} else {
+			cur->fp = fdopen(pdes[1], *type);
+#ifdef _REENTRANT
+			cur->fd = pdes[1];
+#endif
+		}
+		if (cur->fp != NULL)
+			return cur;
+	}
 	serrno = errno;
 	(void)close(pdes[0]);
 	(void)close(pdes[1]);
+	free(cur);
 	errno = serrno;
 	return NULL;
 }
@@ -125,16 +139,6 @@ pdes_child(int *pdes, const char *type)
 {
 	struct pid *old;
 
-	/* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
-	   from previous popen() calls that remain open in the 
-	   parent process are closed in the new child process. */
-	for (old = pidlist; old; old = old->next)
-#ifdef _REENTRANT
-		(void)close(old->fd); /* don't allow a flush */
-#else
-		(void)close(fileno(old->fp)); /* don't allow a flush */
-#endif
-
 	if (type[0] == 'r') {
 		(void)close(pdes[0]);
 		if (pdes[1] != STDOUT_FILENO) {
@@ -150,31 +154,30 @@ pdes_child(int *pdes, const char *type)
 			(void)close(pdes[0]);
 		}
 	}
+
+	/* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
+	   from previous popen() calls that remain open in the
+	   parent process are closed in the new child process. */
+	for (old = pidlist; old; old = old->next) {
+#ifdef _REENTRANT
+		(void)close(old->fd); /* don't allow a flush */
+#else
+		(void)close(fileno(old->fp)); /* don't allow a flush */
+#endif
+	}
 }
 
 static void
 pdes_parent(int *pdes, struct pid *cur, pid_t pid, const char *type)
 {
-	FILE *iop;
-
-	/* Parent; assume fdopen can't fail. */
-	if (*type == 'r') {
-		iop = fdopen(pdes[0], type);
-#ifdef _REENTRANT
-		cur->fd = pdes[0];
-#endif
+	/* Parent */
+	if (*type == 'r')
 		(void)close(pdes[1]);
-	} else {
-		iop = fdopen(pdes[1], type);
-#ifdef _REENTRANT
-		cur->fd = pdes[1];
-#endif
+	else
 		(void)close(pdes[0]);
-	}
 
 	/* Link into list of file descriptors. */
-	cur->fp = iop;
-	cur->pid =  pid;
+	cur->pid = pid;
 	cur->next = pidlist;
 	pidlist = cur;
 }
@@ -200,7 +203,7 @@ popenve(const char *cmd, char *const *argv, char *const *envp, const char *type)
 #ifdef _REENTRANT
 	(void)rwlock_rdlock(&pidlist_lock);
 #endif
-	switch (pid = vfork()) {
+	switch (pid = fork()) {
 	case -1:			/* Error. */
 		serrno = errno;
 #ifdef _REENTRANT


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?698b713b.264d7.6229df2d>