Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libnfs for openSUSE:Factory checked in at 2026-11-03 17:51:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libnfs (Old) and /work/SRC/openSUSE:Factory/.libnfs.new.1257 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libnfs" Tue Nov 3 17:51:27 2026 rev:14 rq:1394338 version:6.0.2 Changes: -------- --- /work/SRC/openSUSE:Factory/libnfs/libnfs.changes 2026-07-10 17:39:05.676617580 +0200 +++ /work/SRC/openSUSE:Factory/.libnfs.new.1257/libnfs.changes 2026-11-03 17:51:31.202174938 +0100 @@ -1,0 +2,6 @@ +Thu Oct 29 03:14:16 UTC 2026 - Xiaoguang Wang <[email protected]> + +- Add libnfs-CVE-2026-108985.patch: ZDR: enforce the maxsize bound + (bsc#1284986, CVE-2026-108985). + +------------------------------------------------------------------- New: ---- libnfs-CVE-2026-108985.patch ----------(New B)---------- New: - Add libnfs-CVE-2026-108985.patch: ZDR: enforce the maxsize bound (bsc#1284986, CVE-2026-108985). ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libnfs.spec ++++++ --- /var/tmp/diff_new_pack.qdg62S/_old 2026-11-03 17:51:32.573232247 +0100 +++ /var/tmp/diff_new_pack.qdg62S/_new 2026-11-03 17:51:32.576232372 +0100 @@ -32,6 +32,8 @@ Patch1: libnfs-CVE-2026-53689.patch # PATCH-FIX-UPSTReAM libnfs-CVE-2026-57918.patch [email protected] -- socket: prevent an underflow in xid. Patch2: libnfs-CVE-2026-57918.patch +# PATCH-FIX-UPSTREAM libnfs-CVE-2026-108985.patch bsc#1284986 [email protected] -- ZDR: enforce the maxsize bound +Patch3: libnfs-CVE-2026-108985.patch BuildRequires: autoconf BuildRequires: libtool BuildRequires: pkgconfig ++++++ libnfs-CVE-2026-108985.patch ++++++ >From f7c4c8b65e9e2373a43c31c09aaff60b809c493d Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg <[email protected]> Date: Thu, 8 Oct 2026 07:22:11 +1000 Subject: [PATCH] ZDR: enforce the maxsize bound libnfs_zdr_bytes(), libnfs_zdr_string() and libnfs_zdr_array() took a maxsize and never consulted it. A decode into a caller-supplied buffer copied the wire length with memcpy(), so a preallocated destination could be written past its end. Limits supplied by the generated decoders, including NFS4_FHSIZE and NFS4_OPAQUE_LIMIT, were skipped the same way. A positive maxsize is now a hard limit, checked before any copy or allocation. Zero and ~0 stay unlimited: rpcgen emits ~0 where the protocol states no limit, and the AUTH credential and verifier paths pass the live length, which is zero on a zeroed object. A caller-supplied byte buffer remains maxsize bytes long, so a zero maxsize accepts only an empty copy into that buffer. Jinpyo Lee, Tobabz Team, reported that the bound was never enforced. Reported-by: Jinpyo Lee <[email protected]> Signed-off-by: Ronnie Sahlberg <[email protected]> Backport of 7613236 to 5.0.3 on top of 55c18ea. Test files omitted. --- lib/libnfs-zdr.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/libnfs-zdr.c b/lib/libnfs-zdr.c index a259de1..3070767 100644 --- a/lib/libnfs-zdr.c +++ b/lib/libnfs-zdr.c @@ -167,15 +167,37 @@ bool_t libnfs_zdr_int64_t(ZDR *zdrs, int64_t *i) return libnfs_zdr_uint64_t(zdrs, (uint64_t *)i); } +/* + * Positive maxsize values are hard limits. ~0 is what rpcgen emits when + * the protocol states no limit. Zero is unlimited too: the AUTH + * credential and verifier paths pass the live length, and a zeroed + * object still has length zero. + */ +static bool_t libnfs_zdr_size_ok(uint32_t size, uint32_t maxsize) +{ + if (maxsize == 0 || maxsize == ~(uint32_t)0) { + return TRUE; + } + return size <= maxsize; +} + bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize) { uint32_t zero = 0; int pad; + if (zdrs->x_op == ZDR_ENCODE && !libnfs_zdr_size_ok(*size, maxsize)) { + return FALSE; + } + if (!libnfs_zdr_u_int(zdrs, size)) { return FALSE; } + if (zdrs->x_op == ZDR_DECODE && !libnfs_zdr_size_ok(*size, maxsize)) { + return FALSE; + } + if (zdrs->pos + (int)*size > zdrs->size) { return FALSE; } @@ -194,6 +216,14 @@ bool_t libnfs_zdr_bytes(ZDR *zdrs, char **bufp, uint32_t *size, uint32_t maxsize return TRUE; case ZDR_DECODE: if (*bufp != NULL) { + /* + * Caller-supplied storage is maxsize bytes long. + * A zero maxsize leaves that storage empty, so + * only an empty field may be copied into it. + */ + if (*size > maxsize) { + return FALSE; + } memcpy(*bufp, &zdrs->buf[zdrs->pos], *size); } else { *bufp = &zdrs->buf[zdrs->pos]; @@ -279,6 +309,9 @@ bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize) if (zdrs->x_op == ZDR_ENCODE) { size = strlen(*strp); + if (!libnfs_zdr_size_ok(size, maxsize)) { + return FALSE; + } } if (!libnfs_zdr_u_int(zdrs, &size)) { @@ -287,6 +320,9 @@ bool_t libnfs_zdr_string(ZDR *zdrs, char **strp, uint32_t maxsize) if (size > zdrs->size) { return FALSE; } + if (zdrs->x_op == ZDR_DECODE && !libnfs_zdr_size_ok(size, maxsize)) { + return FALSE; + } if (zdrs->pos + (int)size > zdrs->size) { return FALSE; } @@ -325,10 +361,18 @@ bool_t libnfs_zdr_array(ZDR *zdrs, char **arrp, uint32_t *size, uint32_t maxsize int i; uint32_t s; + if (zdrs->x_op == ZDR_ENCODE && !libnfs_zdr_size_ok(*size, maxsize)) { + return FALSE; + } + if (!libnfs_zdr_u_int(zdrs, size)) { return FALSE; } + if (zdrs->x_op == ZDR_DECODE && !libnfs_zdr_size_ok(*size, maxsize)) { + return FALSE; + } + if (*size > UINT32_MAX/elsize) { return FALSE; } -- 2.54.0
