All of lore.kernel.org
 help / color / mirror / Atom feed
From: Olga Kornievskaia <okorniev@redhat.com>
To: steved@redhat.com
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH 2/3] libtirpc: limit XDR decode node count
Date: Sun,  6 Sep 2026 21:13:27 -0400	[thread overview]
Message-ID: <20260907011328.21425-3-okorniev@redhat.com> (raw)
In-Reply-To: <20260907011328.21425-1-okorniev@redhat.com>

xdr_pmaplist(), xdr_rpcblist_ptr() and xdr_rpcb_entry_list_ptr()
decode linked lists with no upper bound on element count. A malicious
server can stream arbitrarily many list nodes, forcing unbounded heap
allocation in any client that decodes the response (rpcinfo,
rpcb_getmaps() callers).

Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
---
 src/pmap_prot2.c |  9 ++++++++-
 src/rpcb_prot.c  | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/pmap_prot2.c b/src/pmap_prot2.c
index 7611bd5..d043f34 100644
--- a/src/pmap_prot2.c
+++ b/src/pmap_prot2.c
@@ -39,6 +39,8 @@
 #include <rpc/xdr.h>
 #include <rpc/pmap_prot.h>
 
+/* Cap decoded list length to prevent memory exhaustion from malicious data */
+#define PMAPLIST_DECODE_MAX_NODES 1024
 
 /*
  * What is going on with linked lists? (!)
@@ -87,7 +89,7 @@ xdr_pmaplist(XDR *xdrs, struct pmaplist **rp)
 	 * xdr_bool when the direction is XDR_DECODE.
 	 */
 	bool_t more_elements;
-	int freeing;
+	int freeing, node_count = 0;
 	struct pmaplist *next = NULL;
 	struct pmaplist *next_copy;
 
@@ -102,6 +104,11 @@ xdr_pmaplist(XDR *xdrs, struct pmaplist **rp)
 			return (FALSE);
 		if (! more_elements)
 			return (TRUE);  /* we are done */
+		if (xdrs->x_op == XDR_DECODE &&
+			++node_count > PMAPLIST_DECODE_MAX_NODES) {
+			return (FALSE);
+		}
+
 		/*
 		 * the unfortunate side effect of non-recursion is that in
 		 * the case of freeing we must remember the next object
diff --git a/src/rpcb_prot.c b/src/rpcb_prot.c
index 809feb0..0b0574f 100644
--- a/src/rpcb_prot.c
+++ b/src/rpcb_prot.c
@@ -89,6 +89,9 @@ xdr_rpcb(
  * serialize the rpcb elements.
  */
 
+/* Cap decoded list length to prevent memory exhaustion from malicious data */
+#define RPCBLIST_DECODE_MAX_NODES 1024
+
 bool_t
 xdr_rpcblist_ptr(
 	XDR *xdrs,
@@ -101,6 +104,7 @@ xdr_rpcblist_ptr(
 	 */
 	bool_t more_elements;
 	int freeing = (xdrs->x_op == XDR_FREE);
+	int node_count = 0;
 	rpcblist_ptr next;
 	rpcblist_ptr next_copy;
 
@@ -113,6 +117,10 @@ xdr_rpcblist_ptr(
 		if (! more_elements) {
 			return (TRUE);  /* we are done */
 		}
+		if (xdrs->x_op == XDR_DECODE &&
+		    ++node_count > RPCBLIST_DECODE_MAX_NODES) {
+			return (FALSE);
+		}
 		/*
 		 * the unfortunate side effect of non-recursion is that in
 		 * the case of freeing we must remember the next object
@@ -178,6 +186,9 @@ xdr_rpcb_entry(
 	return (TRUE);
 }
 
+/* Cap decoded list length to prevent memory exhaustion from malicious data */
+#define RPCB_ENTRY_LIST_DECODE_MAX_NODES 1024
+
 bool_t
 xdr_rpcb_entry_list_ptr(
 	XDR *xdrs,
@@ -190,6 +201,7 @@ xdr_rpcb_entry_list_ptr(
 	 */
 	bool_t more_elements;
 	int freeing = (xdrs->x_op == XDR_FREE);
+	int node_count = 0;
 	rpcb_entry_list_ptr next;
 	rpcb_entry_list_ptr next_copy;
 
@@ -202,6 +214,10 @@ xdr_rpcb_entry_list_ptr(
 		if (! more_elements) {
 			return (TRUE);  /* we are done */
 		}
+		if (xdrs->x_op == XDR_DECODE &&
+		    ++node_count > RPCB_ENTRY_LIST_DECODE_MAX_NODES) {
+			return (FALSE);
+		}
 		/*
 		 * the unfortunate side effect of non-recursion is that in
 		 * the case of freeing we must remember the next object
-- 
2.52.0


  parent reply	other threads:[~2026-09-07  1:13 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-07  1:13 [PATCH 1/1] fsidd: require root credentials on abstract socket Olga Kornievskaia
2026-09-07  1:13 ` [PATCH 1/3] libtirpc: Fix use-after-free in xdr_pmaplist() XDR_FREE path Olga Kornievskaia
2026-09-13  3:48   ` Steve Dickson
2026-09-07  1:13 ` Olga Kornievskaia [this message]
2026-09-13  3:48   ` [PATCH 2/3] libtirpc: limit XDR decode node count Steve Dickson
2026-09-07  1:13 ` [PATCH 3/3] libtirpc: Bound maxsize in xdr_rpc_gss_unwrap_data() decode calls Olga Kornievskaia
2026-09-13  3:49   ` Steve Dickson
2026-09-13  3:47 ` [PATCH 1/1] fsidd: require root credentials on abstract socket Steve Dickson
2026-09-16 14:19 ` Steve Dickson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260907011328.21425-3-okorniev@redhat.com \
    --to=okorniev@redhat.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=steved@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.