From 7a8f42fb20013a1493d8cae1c43436f85e656f2d Mon Sep 17 00:00:00 2001
From: Zephkeks <zephyrofficialdiscord@gmail.com>
Date: Tue, 13 May 2025 11:04:17 +0200
Subject: [PATCH] CVE-2025-46836: interface.c: Stack-based Buffer Overflow in
 get_name()

Coordinated as GHSA-pfwf-h6m3-63wf

CVE: CVE-2025-46836
Upstream-Status: Backport [https://sourceforge.net/p/net-tools/code/ci/7a8f42fb20013a1493d8cae1c43436f85e656f2d/]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
 lib/interface.c | 63 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 39 insertions(+), 24 deletions(-)

diff --git a/lib/interface.c b/lib/interface.c
index 71d4163..a054f12 100644
--- a/lib/interface.c
+++ b/lib/interface.c
@@ -211,32 +211,47 @@ out:
 }
 
 static const char *get_name(char *name, const char *p)
+/* Safe version — guarantees at most IFNAMSIZ‑1 bytes are copied
+   and the destination buffer is always NUL‑terminated.             */
 {
-    while (isspace(*p))
-	p++;
-    while (*p) {
-	if (isspace(*p))
-	    break;
-	if (*p == ':') {	/* could be an alias */
-		const char *dot = p++;
- 		while (*p && isdigit(*p)) p++;
-		if (*p == ':') {
-			/* Yes it is, backup and copy it. */
-			p = dot;
-			*name++ = *p++;
-			while (*p && isdigit(*p)) {
-				*name++ = *p++;
-			}
-		} else {
-			/* No, it isn't */
-			p = dot;
-	    }
-	    p++;
-	    break;
-	}
-	*name++ = *p++;
+    char       *dst = name;                 /* current write ptr          */
+    const char *end = name + IFNAMSIZ - 1;  /* last byte we may write     */
+
+    /* Skip leading white‑space. */
+    while (isspace((unsigned char)*p))
+        ++p;
+
+    /* Copy until white‑space, end of string, or buffer full. */
+    while (*p && !isspace((unsigned char)*p) && dst < end) {
+        if (*p == ':') {                    /* possible alias veth0:123:  */
+            const char *dot = p;            /* remember the colon         */
+            ++p;
+            while (*p && isdigit((unsigned char)*p))
+                ++p;
+
+            if (*p == ':') {                /* confirmed alias            */
+                p = dot;                    /* rewind and copy it all     */
+
+                /* copy the colon */
+                if (dst < end)
+                    *dst++ = *p++;
+
+                /* copy the digits */
+                while (*p && isdigit((unsigned char)*p) && dst < end)
+                    *dst++ = *p++;
+
+                if (*p == ':')              /* consume trailing colon     */
+                    ++p;
+            } else {              /* if so treat as normal */
+                p = dot;
+            }
+            break;                          /* interface name ends here   */
+        }
+
+        *dst++ = *p++;                      /* ordinary character copy    */
     }
-    *name++ = '\0';
+
+    *dst = '\0';                            /* always NUL‑terminate       */
     return p;
 }
 
