Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Jul 2026 23:11:01 +0000
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 152ba2d3c5ff - main - rpcinfo: Fix buffer overflows
Message-ID:  <6a67e585.32420.40b05ea7@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by markj:

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

commit 152ba2d3c5ff00382260a48653855072d524cfb8
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-07-27 18:59:08 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-07-27 23:03:16 +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
---
 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 5156dd2db4e0..70d632fb9227 100644
--- a/usr.bin/rpcinfo/rpcinfo.c
+++ b/usr.bin/rpcinfo/rpcinfo.c
@@ -760,24 +760,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;
 			}
 		    }
@@ -840,10 +838,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';
@@ -949,11 +948,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);
@@ -1026,37 +1025,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);
@@ -1079,37 +1082,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);
@@ -1134,26 +1141,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 */
 			}
@@ -1164,17 +1173,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);


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a67e585.32420.40b05ea7>