Bug 2478979 (CVE-2026-85977)

Summary: CVE-2026-85977 libtirpc: libtirpc: Denial of Service via unbounded memory allocation during portmapper response decoding
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: akhatavk, aos-team-art-private, asdas, dpaolell, jdelft, jupierce, lgarciaa, mbiarnes, ppalepu, ppostler, prdhamdh, rhel-process-autobot, security-response-team, sghai, sidsharm, suppawar, vlaad, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in libtirpc. A remote attacker can exploit this vulnerability by sending specially crafted PMAPPROC_DUMP replies to a client application that uses the pmap_getmaps() function against an attacker-controlled host. This unbounded decoding can lead to excessive memory and CPU allocation, causing the client process to experience a Denial of Service (DoS) due to resource exhaustion.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 2554146    
Bug Blocks:    

Description OSIDB Bzimport 2026-05-18 03:51:35 UTC
AI_ONLY_REPORT
package: libtirpc-1.3.7-2.1.hum1
------
Summary: Unbounded pmaplist decoding can cause memory exhaustion (DoS):  
attacker-controlled `PMAPPROC_DUMP` replies can drive unbounded decode-time  
allocation in `xdr_pmaplist()` and exhaust memory or CPU in the client  
process.
Requirements to exploit: An attacker must be able to make a libtirpc  
consumer call `pmap_getmaps()` against an attacker-controlled host, or  
otherwise supply the `PMAPPROC_DUMP` response on that path. No  
authentication or post-request user interaction is required, but the  
vulnerable client-side portmapper path must be used by the consuming  
application.
Component affected: `libtirpc-1.3.7-2.1.hum1` portmapper/XDR decode path in  
`src/pmap_prot2.c` (`xdr_pmaplist()`), reachable from `src/pmap_getmaps.c`  
(`pmap_getmaps()`)
Version affected: `libtirpc-1.3.7-2.1.hum1`, when the `pmap_getmaps()` /  
`PMAPPROC_DUMP` client decode path is exercised
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H - 5.9 (MEDIUM)
AV:N - The malicious `PMAPPROC_DUMP` response is delivered over the  
network to a client using `pmap_getmaps()`.
AC:H - Exploitation depends on the victim using this specific client  
path against an attacker-controlled or spoofed endpoint; once that  
precondition holds, the payload is straightforward.
PR:N - No authentication is required.
UI:N - No additional user interaction is required after the vulnerable  
request is made.
S:U - The impact is limited to the vulnerable client process and its  
resources.
C:N - No confidentiality impact is established by the available evidence.
I:N - No integrity impact is established by the available evidence.
A:H - A long attacker-controlled list can consume substantial memory and  
CPU, causing the client to hang, fail allocation, or be terminated.
Impact: Moderate. This is a real availability issue, but the available  
evidence supports a usage-dependent client-side path rather than a broadly  
exposed server path in the package itself. Under Red Hat's severity  
guidance, that makes the issue less broadly exploitable than the typical  
remote DoS cases rated Important, and there is no evidence of  
confidentiality, integrity, or system-compromise impact.
Embargo: no
Reason: This is an availability-only flaw in a client-side,  
usage-dependent path with straightforward short-term mitigations, so  
immediate public handling appears appropriate.
Acknowledgement: Aisle Research
Vulnerability Details: `pmap_getmaps()` uses `xdr_pmaplist()` to decode  
`PMAPPROC_DUMP` replies. In `xdr_pmaplist()`, loop termination depends  
entirely on the decoded `more_elements` value, and no maximum node count or  
byte budget is enforced:
```c
for (; {
more_elements = (bool_t)(*rp != NULL);
if (! xdr_bool(xdrs, &more_elements))
return (FALSE);
if (! more_elements)
return (TRUE);
if (! xdr_reference(xdrs, (caddr_t *)rp,
(u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap))
return (FALSE);
rp = (freeing) ? next : &((*rp)->pml_next);
}
```
During `XDR_DECODE`, `xdr_reference()` allocates a new `struct pmaplist`  
node whenever the pointer is `NULL`:
```c
case XDR_DECODE:
*pp = loc = (caddr_t) mem_alloc(size);
if (loc == NULL) {
warnx("xdr_reference: out of memory");
return (FALSE);
}
memset(loc, 0, size);
break;
```
This makes both allocation count and decode work peer-controlled. A  
responder that keeps sending `more_elements=TRUE` with additional `struct  
pmap` records can force repeated allocations until the client slows  
significantly, fails allocation, or is killed for resource exhaustion. The  
available transport code does not show a total decode budget in this path;  
the receive timeout is applied per read/poll cycle, so continued input can  
continue to drive work.
Steps to reproduce:
1. Build or use a libtirpc consumer with the portmapper client path enabled  
and create a small client that calls `pmap_getmaps()` against a host you  
control.
2. Run a malicious or mock rpcbind/portmapper service on TCP/111 that  
returns a valid `PMAPPROC_DUMP` reply body containing many repetitions of  
`bool TRUE` followed by one `struct pmap` record, with a final `bool FALSE`  
only after a very long list or not until resource exhaustion is reached.
3. Observe client memory and CPU consumption while the reply is decoded  
through `xdr_pmaplist()`.
4. Increase the number of returned elements; the client eventually becomes  
slow, fails allocation, or is terminated by the OOM killer.
5. As a validation step, add a local decode cap and confirm the same  
payload is rejected quickly.
Mitigation: Until a fix is available, avoid calling `pmap_getmaps()`  
against untrusted or attacker-influenced endpoints. If this functionality  
is required, add a local maximum node or allocation budget for  
`xdr_pmaplist()` decoding, or isolate the caller so failure only affects a  
constrained helper process.
Proposed Fix: Add an explicit decode-time limit for the number of  
`pmaplist` nodes accepted by `xdr_pmaplist()`, and fail decoding once the  
limit is exceeded.
```diff
diff --git a/src/pmap_prot2.c b/src/pmap_prot2.c
— a/src/pmap_prot2.c
+++ b/src/pmap_prot2.c
@@ -38,6 +38,10 @@
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
+#ifndef PMAPLIST_DECODE_MAX_NODES
+#define PMAPLIST_DECODE_MAX_NODES 1024U
+#endif
+
bool_t
xdr_pmaplist(XDR *xdrs, struct pmaplist **rp)
{
@@ -53,6 +57,7 @@ xdr_pmaplist(XDR *xdrs, struct pmaplist **rp)
bool_t more_elements;
int freeing;
struct pmaplist *next = NULL; / pacify gcc */
+       u_int decoded_nodes = 0;
freeing = (xdrs->x_op == XDR_FREE);
@@ -67,6 +72,12 @@ xdr_pmaplist(XDR *xdrs, struct pmaplist **rp)
if (! more_elements)
return (TRUE);
+               if (xdrs->x_op == XDR_DECODE) {
+                       if (++decoded_nodes > PMAPLIST_DECODE_MAX_NODES) {
+                               return (FALSE);
+                       }
+               }
+
if (freeing)
next = &((*rp)->pml_next);
if (! xdr_reference(xdrs, (caddr_t *)rp,
```
------
This report was generated using AI technology. Always review AI-generated  
content prior to use