git: 152ba2d3c5ff - main - rpcinfo: Fix buffer overflows
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 27 Jul 2026 23:11:01 UTC
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);