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);

Reply via email to