git: 0a8166023b3d - stable/14 - rpcinfo: Fix buffer overflows

Mark Johnston <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a7353c0.4664f.2f8c5568__2990.19027022354$1785943020$gmane$org@gitrepo.freebsd.org>
The branch stable/14 has been updated by markj:

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

commit 0a8166023b3da09444f60f7a01a644900cd1f74f
Author:     Mark Johnston <[email protected]>
AuthorDate: 2026-07-27 18:59:08 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2026-08-05 15:15:14 +0000

    rpcinfo: Fix buffer overflows
    
    Several functions were using sprintf() to write RPC server-controlled
    data to a stack buffer.  Adopt some minimal changes from NetBSD to avoid
    the potential overflows.
    
    Security:       CVE-2026-16277
    Security:       CVE-2026-16461
    Reviewed by:    khorben
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D58441
    
    (cherry picked from commit 152ba2d3c5ff00382260a48653855072d524cfb8)
---
 usr.bin/rpcinfo/rpcinfo.c | 117 ++++++++++++++++++++++++++--------------------
 1 file changed, 67 insertions(+), 50 deletions(-)

diff --git a/usr.bin/rpcinfo/rpcinfo.c b/usr.bin/rpcinfo/rpcinfo.c
index 6945c1de481f..a153b90d39c9 100644
--- a/usr.bin/rpcinfo/rpcinfo.c
+++ b/usr.bin/rpcinfo/rpcinfo.c
@@ -766,24 +766,22 @@ rpcbdump(int dumptype, char *netid, int argc, char **argv)
 			    list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
 			    list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
 			    if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
-				list->rpcb_map.r_netid = "udp";
+				list->rpcb_map.r_netid = strdup("udp");
 			    else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
-				list->rpcb_map.r_netid = "tcp";
+				list->rpcb_map.r_netid = strdup("tcp");
 			    else {
-#define	MAXLONG_AS_STRING	"2147483648"
-				list->rpcb_map.r_netid =
-					malloc(strlen(MAXLONG_AS_STRING) + 1);
-				if (list->rpcb_map.r_netid == NULL)
-					goto error;
-				sprintf(list->rpcb_map.r_netid, "%6ld",
-					pmaphead->pml_map.pm_prot);
+				(void)asprintf(&list->rpcb_map.r_netid, "%6ld",
+				    pmaphead->pml_map.pm_prot);
 			    }
+			    if (list->rpcb_map.r_netid == NULL)
+				    goto error;
 			    list->rpcb_map.r_owner = UNKNOWN;
 			    low = pmaphead->pml_map.pm_port & 0xff;
 			    high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
-			    list->rpcb_map.r_addr = strdup("0.0.0.0.XXX.XXX");
-			    sprintf(&list->rpcb_map.r_addr[8], "%d.%d",
-				high, low);
+			    (void)asprintf(&list->rpcb_map.r_addr,
+				"0.0.0.0.%d.%d", high, low);
+			    if (list->rpcb_map.r_addr == NULL)
+				    goto error;
 			    prev = list;
 			}
 		    }
@@ -846,10 +844,11 @@ failed:
 
 			printf("%10ld  ", rs->prog);
 			for (vl = rs->vlist; vl; vl = vl->next) {
-				sprintf(p, "%d", vl->vers);
+				if ((size_t)(p - buf) >= sizeof(buf))
+					break;
+				(void)snprintf(p, sizeof(buf) - (p - buf),
+				    "%d%s", vl->vers, vl->next ? "," : "");
 				p = p + strlen(p);
-				if (vl->next)
-					sprintf(p++, ",");
 			}
 			printf("%-10s", buf);
 			buf[0] = '\0';
@@ -955,11 +954,11 @@ rpcbaddrlist(char *netid, int argc, char **argv)
 			re = &head->rpcb_entry_map;
 			printf("%10u%3u    ",
 				parms.r_prog, parms.r_vers);
-			sprintf(buf, "%s/%s/%s ",
-				re->r_nc_protofmly, re->r_nc_proto,
-				re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
-				re->r_nc_semantics == NC_TPI_COTS ? "cots" :
-						"cots_ord");
+			(void)snprintf(buf, sizeof(buf), "%s/%s/%s ",
+			    re->r_nc_protofmly, re->r_nc_proto,
+			    re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
+			    re->r_nc_semantics == NC_TPI_COTS ? "cots" :
+			    "cots_ord");
 			printf("%-24s", buf);
 			printf("%-24s", re->r_maddr);
 			rpc = getrpcbynumber(parms.r_prog);
@@ -1032,37 +1031,41 @@ rpcbgetstat(int argc, char **argv)
 		fieldbuf[0] = '\0';
 		switch (i) {
 		case PMAPPROC_SET:
-			sprintf(fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/",
+			    inf[RPCBVERS_2_STAT].setinfo);
 			break;
 		case PMAPPROC_UNSET:
-			sprintf(fieldbuf, "%d/",
-				inf[RPCBVERS_2_STAT].unsetinfo);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/",
+			    inf[RPCBVERS_2_STAT].unsetinfo);
 			break;
 		case PMAPPROC_GETPORT:
 			cnt = 0;
 			for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa;
 				pa = pa->next)
 				cnt += pa->success;
-			sprintf(fieldbuf, "%d/", cnt);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/", cnt);
 			break;
 		case PMAPPROC_CALLIT:
 			cnt = 0;
 			for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr;
 				pr = pr->next)
 				cnt += pr->success;
-			sprintf(fieldbuf, "%d/", cnt);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/", cnt);
 			break;
 		default: break;  /* For the remaining ones */
 		}
 		cp = &fieldbuf[0] + strlen(fieldbuf);
-		sprintf(cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
+		(void)snprintf(cp, sizeof(fieldbuf) - (cp - fieldbuf), "%d",
+		    inf[RPCBVERS_2_STAT].info[i]);
 		flen = strlen(fieldbuf);
 		printf("%s%s", pmaphdr[i],
 			spaces((TABSTOP * (1 + flen / TABSTOP))
 			- strlen(pmaphdr[i])));
-		sprintf(lp, "%s%s", fieldbuf,
-			spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
-			- flen)));
+		if ((size_t)(lp - linebuf) >= sizeof(linebuf))
+			break;
+		(void)snprintf(lp, sizeof(linebuf) - (lp - linebuf), "%s%s",
+		    fieldbuf, spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) -
+		    flen)));
 		lp += (flen + cnt);
 	}
 	printf("\n%s\n\n", linebuf);
@@ -1085,37 +1088,41 @@ rpcbgetstat(int argc, char **argv)
 		fieldbuf[0] = '\0';
 		switch (i) {
 		case RPCBPROC_SET:
-			sprintf(fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/",
+			    inf[RPCBVERS_3_STAT].setinfo);
 			break;
 		case RPCBPROC_UNSET:
-			sprintf(fieldbuf, "%d/",
-				inf[RPCBVERS_3_STAT].unsetinfo);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/",
+			    inf[RPCBVERS_3_STAT].unsetinfo);
 			break;
 		case RPCBPROC_GETADDR:
 			cnt = 0;
 			for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa;
 				pa = pa->next)
 				cnt += pa->success;
-			sprintf(fieldbuf, "%d/", cnt);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/", cnt);
 			break;
 		case RPCBPROC_CALLIT:
 			cnt = 0;
 			for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr;
 				pr = pr->next)
 				cnt += pr->success;
-			sprintf(fieldbuf, "%d/", cnt);
+			(void)snprintf(fieldbuf, sizeof(fieldbuf), "%d/", cnt);
 			break;
 		default: break;  /* For the remaining ones */
 		}
 		cp = &fieldbuf[0] + strlen(fieldbuf);
-		sprintf(cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
+		(void)snprintf(cp, sizeof(fieldbuf) - (cp - fieldbuf),
+		    "%d", inf[RPCBVERS_3_STAT].info[i]);
 		flen = strlen(fieldbuf);
 		printf("%s%s", rpcb3hdr[i],
 			spaces((TABSTOP * (1 + flen / TABSTOP))
 			- strlen(rpcb3hdr[i])));
-		sprintf(lp, "%s%s", fieldbuf,
-			spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
-			- flen)));
+		if ((size_t)(lp - linebuf) >= sizeof(linebuf))
+			break;
+		(void)snprintf(lp, sizeof(linebuf) - (lp - linebuf), "%s%s",
+		    fieldbuf, spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) -
+		    flen)));
 		lp += (flen + cnt);
 	}
 	printf("\n%s\n\n", linebuf);
@@ -1140,26 +1147,28 @@ rpcbgetstat(int argc, char **argv)
 			fieldbuf[0] = '\0';
 			switch (i) {
 			case RPCBPROC_SET:
-				sprintf(fieldbuf, "%d/",
-					inf[RPCBVERS_4_STAT].setinfo);
+				(void)snprintf(fieldbuf, sizeof(fieldbuf),
+				    "%d/", inf[RPCBVERS_4_STAT].setinfo);
 				break;
 			case RPCBPROC_UNSET:
-				sprintf(fieldbuf, "%d/",
-					inf[RPCBVERS_4_STAT].unsetinfo);
+				(void)snprintf(fieldbuf, sizeof(fieldbuf),
+				    "%d/", inf[RPCBVERS_4_STAT].unsetinfo);
 				break;
 			case RPCBPROC_GETADDR:
 				cnt = 0;
 				for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa;
 					pa = pa->next)
 					cnt += pa->success;
-				sprintf(fieldbuf, "%d/", cnt);
+				(void)snprintf(fieldbuf, sizeof(fieldbuf),
+				    "%d/", cnt);
 				break;
 			case RPCBPROC_CALLIT:
 				cnt = 0;
 				for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr;
 					pr = pr->next)
 					cnt += pr->success;
-				sprintf(fieldbuf, "%d/", cnt);
+				(void)snprintf(fieldbuf, sizeof(fieldbuf),
+				    "%d/", cnt);
 				break;
 			default: break;  /* For the remaining ones */
 			}
@@ -1170,17 +1179,25 @@ rpcbgetstat(int argc, char **argv)
 			 * RPCB_GETADDRLIST successes in RPCB_GETADDR.
 			 */
 			if (i != RPCBPROC_GETADDR)
-			    sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i]);
+				(void)snprintf(cp,
+				    sizeof(fieldbuf) - (cp - fieldbuf),
+				    "%d", inf[RPCBVERS_4_STAT].info[i]);
 			else
-			    sprintf(cp, "%d", inf[RPCBVERS_4_STAT].info[i] +
-			    inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
+				(void)snprintf(cp,
+				    sizeof(fieldbuf) - (cp - fieldbuf),
+				    "%d", inf[RPCBVERS_4_STAT].info[i] +
+				    inf[RPCBVERS_4_STAT].
+				    info[RPCBPROC_GETADDRLIST]);
 			flen = strlen(fieldbuf);
 			printf("%s%s", rpcb4hdr[i],
 				spaces((TABSTOP * (1 + flen / TABSTOP))
 				- strlen(rpcb4hdr[i])));
-			sprintf(lp, "%s%s", fieldbuf,
-				spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP))
-				- flen)));
+			if ((size_t)(lp - linebuf) >= sizeof(linebuf))
+				break;
+			(void)snprintf(lp, sizeof(linebuf) - (lp - linebuf),
+			    "%s%s", fieldbuf,
+			    spaces(cnt = ((TABSTOP * (1 + flen / TABSTOP)) -
+			    flen)));
 			lp += (flen + cnt);
 		}
 		printf("\n%s\n", linebuf);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.