git: e17d7ab869bb - main - xdr_string: don't leak strings with xdr_free
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 23 Jan 2026 11:07:28 UTC
The branch main has been updated by brooks:
URL: https://cgit.FreeBSD.org/src/commit/?id=e17d7ab869bbfe3fa5a7da4b74d9f4fa51a0d69f
commit e17d7ab869bbfe3fa5a7da4b74d9f4fa51a0d69f
Author: Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2026-01-23 10:35:55 +0000
Commit: Brooks Davis <brooks@FreeBSD.org>
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);