git: 152ba2d3c5ff - main - rpcinfo: Fix buffer overflows

Mark Johnston <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm
Message-ID <[email protected]>
The branch main has been updated by markj:

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

commit 152ba2d3c5ff00382260a48653855072d524cfb8
Author:     Mark Johnston <[email protected]>
AuthorDate: 2026-07-27 18:59:08 +0000
Commit:     Mark Johnston <[email protected]>
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);
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.