The branch main has been updated by brooks:

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

commit e17d7ab869bbfe3fa5a7da4b74d9f4fa51a0d69f
Author:     Brooks Davis <[email protected]>
AuthorDate: 2026-01-23 10:35:55 +0000
Commit:     Brooks Davis <[email protected]>
CommitDate: 2026-01-23 10:35:55 +0000

    xdr_string: don't leak strings with xdr_free
    
    Historically (and in a small amount of older software such as OpenAFS),
    developers would attempt to free XDR strings with
    
            xdr_free((xdrproc_t)xdr_string, &string)
    
    This resulted in xdr_free calling xdr_string with only two intentional
    arguments and whatever was left in the third argument register.  If the
    register held a sufficently small number, xdr_string would return FALSE
    and not free the string (no one checks the return values).
    
    Software should instead free strings with:
    
            xdr_free((xdrproc_t)xdr_wrapstring, &string)
    
    Because buggy software exists in the wild, act as though xdr_wrapstring
    was used in the XDR_FREE case and plug these leaks.
    
    Reviewed by:    kib
    MFC after:      3 days
    Effort:         CHERI upstreaming
    Sponsored by:   Innovate UK
    Differential Revision:  https://reviews.freebsd.org/D54825
---
 lib/libc/xdr/xdr.c | 7 +++++++
 sys/xdr/xdr.c      | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/lib/libc/xdr/xdr.c b/lib/libc/xdr/xdr.c
index 59a843405abf..47aafea4bc30 100644
--- a/lib/libc/xdr/xdr.c
+++ b/lib/libc/xdr/xdr.c
@@ -696,6 +696,13 @@ xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
                if (sp == NULL) {
                        return(TRUE);   /* already free */
                }
+               /*
+                * XXX: buggy software may call this without a third
+                * argument via xdr_free().  Ignore maxsize since it may
+                * be invalid.  Otherwise, if it's very small, we might
+                * fail to free the string.
+                */
+               maxsize = RPC_MAXDATASIZE;
                /* FALLTHROUGH */
        case XDR_ENCODE:
                size = strlen(sp);
diff --git a/sys/xdr/xdr.c b/sys/xdr/xdr.c
index 81d238ebf19f..f983a474abdd 100644
--- a/sys/xdr/xdr.c
+++ b/sys/xdr/xdr.c
@@ -620,6 +620,13 @@ xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
                if (sp == NULL) {
                        return(TRUE);   /* already free */
                }
+               /*
+                * XXX: buggy software may call this without a third
+                * argument via xdr_free().  Ignore maxsize since it may
+                * be invalid.  Otherwise, if it's very small, we might
+                * fail to free the string.
+                */
+               maxsize = RPC_MAXDATASIZE;
                /* FALLTHROUGH */
        case XDR_ENCODE:
                size = strlen(sp);

Reply via email to