git: 88c5a4996b90 - releng/15.0 - ifconfig: Fix invalid free() in ifbridge

From: Colin Percival <cperciva_at_FreeBSD.org>
Date: Wed, 05 Nov 2025 19:37:24 UTC
The branch releng/15.0 has been updated by cperciva:

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

commit 88c5a4996b90fb70e5990169170a4e93d19aff23
Author:     Lexi Winter <ivy@FreeBSD.org>
AuthorDate: 2025-11-04 00:53:25 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2025-11-05 19:36:12 +0000

    ifconfig: Fix invalid free() in ifbridge
    
    parse_vlans() does 's = strdup(str)', then calls strsep(&s, ...), then
    attempts to free(s) at the end of the function.  For the success case,
    this is fine (s is NULL, so it's a trivial memory leak), but in the
    error case, we will attempt to free an invalid pointer.
    
    Fix this by storing the original return value from strdup() and freeing
    that instead.
    
    Approved by:    re (cperciva)
    MFC after:      3 seconds
    Reported by:    David Gwynne <dlg@openbsd.org>
    Reviewed by:    zlei, kevans
    Sponsored by:   https://www.patreon.com/bsdivy
    Differential Revision:  https://reviews.freebsd.org/D53545
    
    (cherry picked from commit 0899f7a3b791ed4878e7cb3859636ec980c76832)
    (cherry picked from commit fe2e534433778c038138510ff6a8f07066e72703)
---
 sbin/ifconfig/ifbridge.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
index eff443447c13..8bcf4a638adf 100644
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -811,7 +811,7 @@ unsetbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
 static int
 parse_vlans(ifbvlan_set_t *set, const char *str)
 {
-	char *s, *token;
+	char *s, *free_s, *token;
 
 	/* "none" means the empty vlan set */
 	if (strcmp(str, "none") == 0) {
@@ -829,6 +829,8 @@ parse_vlans(ifbvlan_set_t *set, const char *str)
 
 	if ((s = strdup(str)) == NULL)
 		return (-1);
+	/* Keep the original value of s, since strsep() will modify it */
+	free_s = s;
 
 	while ((token = strsep(&s, ",")) != NULL) {
 		unsigned long first, last;
@@ -856,11 +858,11 @@ parse_vlans(ifbvlan_set_t *set, const char *str)
 			BRVLAN_SET(set, vlan);
 	}
 
-	free(s);
+	free(free_s);
 	return (0);
 
 err:
-	free(s);
+	free(free_s);
 	return (-1);
 }