| From 223f22b4887ce954ea6ec8d40ee1a88d8283a48d Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 20 Dec 2025 10:41:09 -0500 |
| Subject: xdrgen: Initialize data pointer for zero-length items |
| |
| From: Chuck Lever <chuck.lever@oracle.com> |
| |
| [ Upstream commit 27b0fcae8f535fb882b1876227a935dcfdf576aa ] |
| |
| The xdrgen decoders for strings and opaque data had an |
| optimization that skipped calling xdr_inline_decode() when the |
| item length was zero. This left the data pointer uninitialized, |
| which could lead to unpredictable behavior when callers access |
| it. |
| |
| Remove the zero-length check and always call xdr_inline_decode(). |
| When passed a length of zero, xdr_inline_decode() returns the |
| current buffer position, which is valid and matches the behavior |
| of hand-coded XDR decoders throughout the kernel. |
| |
| Fixes: 4b132aacb076 ("tools: Add xdrgen") |
| Reviewed-by: Jeff Layton <jlayton@kernel.org> |
| Reviewed-by: NeilBrown <neil@brown.name> |
| Signed-off-by: Chuck Lever <chuck.lever@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| include/linux/sunrpc/xdrgen/_builtins.h | 20 ++++++++------------ |
| 1 file changed, 8 insertions(+), 12 deletions(-) |
| |
| diff --git a/include/linux/sunrpc/xdrgen/_builtins.h b/include/linux/sunrpc/xdrgen/_builtins.h |
| index 66ca3ece951ab..a5ab75d2db044 100644 |
| --- a/include/linux/sunrpc/xdrgen/_builtins.h |
| +++ b/include/linux/sunrpc/xdrgen/_builtins.h |
| @@ -188,12 +188,10 @@ xdrgen_decode_string(struct xdr_stream *xdr, string *ptr, u32 maxlen) |
| return false; |
| if (unlikely(maxlen && len > maxlen)) |
| return false; |
| - if (len != 0) { |
| - p = xdr_inline_decode(xdr, len); |
| - if (unlikely(!p)) |
| - return false; |
| - ptr->data = (unsigned char *)p; |
| - } |
| + p = xdr_inline_decode(xdr, len); |
| + if (unlikely(!p)) |
| + return false; |
| + ptr->data = (unsigned char *)p; |
| ptr->len = len; |
| return true; |
| } |
| @@ -219,12 +217,10 @@ xdrgen_decode_opaque(struct xdr_stream *xdr, opaque *ptr, u32 maxlen) |
| return false; |
| if (unlikely(maxlen && len > maxlen)) |
| return false; |
| - if (len != 0) { |
| - p = xdr_inline_decode(xdr, len); |
| - if (unlikely(!p)) |
| - return false; |
| - ptr->data = (u8 *)p; |
| - } |
| + p = xdr_inline_decode(xdr, len); |
| + if (unlikely(!p)) |
| + return false; |
| + ptr->data = (u8 *)p; |
| ptr->len = len; |
| return true; |
| } |
| -- |
| 2.51.0 |
| |