Bug 2462960 (CVE-2026-94640)
| Summary: | CVE-2026-94640 rpcbind: Unbounded memory allocation in rpcbind statistics tracking allows unauthenticated remote denial of service | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | OSIDB Bzimport <bzimport> |
| Component: | vulnerability | Assignee: | Product Security DevOps Team <prodsec-dev> |
| Status: | NEW --- | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | unspecified | CC: | 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 rpcbind. This vulnerability allows a remote, unauthenticated attacker to cause a Denial of Service (DoS) by sending a large number of unique requests. The rpcbind service records previously unseen RPC (Remote Procedure Call) statistics in unbounded in-memory lists, leading to persistent memory growth and increased CPU usage. This can degrade or exhaust service availability.
|
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: | 2539094 | ||
| Bug Blocks: | |||
AI_ONLY_REPORT package: rpcbind-1.2.7-3.el10 ------ Summary: Unbounded Memory Allocation in Statistics Gathering (Memory Exhaustion DoS): `rpcbind-1.2.7-3.el10` records previously unseen RPC statistics tuples in unbounded in-memory linked lists, allowing unauthenticated network requests to drive persistent memory growth and increasing CPU cost until service availability is degraded or exhausted. Requirements to exploit: An attacker must be able to reach the `rpcbind` service over the network and send a large number of unauthenticated `RPCBPROC_GETADDR` requests, or related `CALLIT`/`INDIRECT`/`BCAST` requests, using distinct `prog`/`vers`/`proc` values. Deployments restricted to loopback or otherwise filtered are less exposed. Component affected: `rpcbind-1.2.7-3.el10`, `src/rpcb_stat.c`, `rpcbs_getaddr()` and `rpcbs_rmtcall()`, reached from `rpcbproc_getaddr_com()` and `rpcbproc_callit_com()`. Version affected: `rpcbind-1.2.7-3.el10` 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:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (HIGH) AV:N - The vulnerable request paths are reachable over the network when `rpcbind` is exposed on port 111. AC:L - The attack consists of sending repeated requests with previously unseen tuple values; no special conditions beyond reachability are required. PR:N - The affected `GETADDR` path does not require authentication. UI:N - No user interaction is required. S:U - The impact is limited to the affected `rpcbind` service. C:N - The available technical evidence does not show confidentiality impact. I:N - The available technical evidence does not show integrity impact. A:H - Repeated unique requests can cause sustained memory growth and increasing per-request CPU cost, leading to service degradation or exhaustion. Impact: Important. Red Hat classifies flaws that allow remote users to cause denial of service as Important. Here, a network-reachable `rpcbind` instance can be driven into availability loss through unbounded statistics growth without authentication. This does not rise to Critical because the available evidence supports availability impact only, not code execution or broader system compromise. Embargo: no Reason: The issue is availability-only based on the current evidence, and exposure can be reduced operationally by restricting access to `rpcbind` on port 111 or limiting it to trusted interfaces while a fix is prepared. Acknowledgement: Aisle Research Vulnerability Details: `rpcbind` keeps per-tuple RPC statistics in linked lists. In `rpcbs_getaddr()`, the code linearly searches for an existing `(prog, vers, netid)` entry and allocates a new node when no match is found: ```c for (al = inf[rtype].addrinfo; al; al = al->next) { if(al->netid == NULL) return; if ((al->prog == prog) && (al->vers == vers) && (strcmp(al->netid, netid) == 0)) { ... return; } } nconf = rpcbind_get_conf(netid); if (nconf == NULL) { return; } al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist)); if (al == NULL) { return; } ... al->next = inf[rtype].addrinfo; inf[rtype].addrinfo = al; ``` `rpcbs_rmtcall()` follows the same allocate-and-prepend pattern for `(prog, vers, proc, netid)` entries. The `RPCBPROC_GETADDR` request path reaches `rpcbs_getaddr()`, and `RPCBPROC_CALLIT`/`RPCBPROC_INDIRECT`/`RPCBPROC_BCAST` reach `rpcbs_rmtcall()`. The tuple is not fully attacker-controlled because `netid` comes from the transport (`transp->xp_netid`), but the request-controlled `prog`, `vers`, and `proc` fields are sufficient to create an effectively unbounded number of distinct entries over a single reachable transport. The access-control logic only applies the non-loopback restriction to `RPCBPROC_SET` and `RPCBPROC_UNSET`; `GETADDR`, `CALLIT`, and related operations are not blocked by that default check. Because each request traverses the corresponding linked list before updating or allocating an entry, the flaw affects both memory consumption and CPU cost. This behavior is consistent with CWE-400 and CWE-770. Steps to reproduce: 1. Start the affected `rpcbind` service and ensure it is reachable on port 111 from the test system. 2. Record the process identifier and baseline memory usage: ```bash pidof rpcbind grep -E 'VmRSS|VmSize' /proc/$(pidof rpcbind)/status ``` 3. Send many unique `GETADDR` tuples. `GETADDR` alone is sufficient to reproduce the issue: ```bash TARGET=127.0.0.1 for i in $(seq 1 200000); do rpcinfo -T udp "$TARGET" $((200000+i)) $((i%65535+1)) >/dev/null 2>&1 done ``` 4. Re-check memory usage: ```bash grep -E 'VmRSS|VmSize' /proc/$(pidof rpcbind)/status ``` 5. Observe that `VmRSS` and `VmSize` grow steadily and do not shrink during normal runtime. If a fixed-rate query workload is repeated before and after list growth, latency and CPU usage also increase because the search remains linear. Mitigation: Restrict access to `rpcbind` on port 111 to trusted systems until a fix is available. Deployments already limited to loopback or protected by network filtering are less exposed. Where operationally acceptable, reducing external reachability of `rpcbind` is the most direct temporary mitigation. Proposed Fix: A minimal mitigation is to cap the number of remembered tuple-level statistics entries per RPCB statistics version so that new attacker-controlled tuples cannot grow the lists without bound. ```diff diff --git a/src/rpcb_stat.c b/src/rpcb_stat.c index 0000000..1111111 100644 — a/src/rpcb_stat.c +++ b/src/rpcb_stat.c @@ -50,6 +50,12 @@ #include <string.h> #include "rpcbind.h" +/* Bound stats growth from attacker-controlled tuple churn */ +#define RPCBS_ADDRINFO_MAX 4096 +#define RPCBS_RMTINFO_MAX 4096 +static unsigned int addrinfo_count[RPCBVERS_STAT]; +static unsigned int rmtinfo_count[RPCBVERS_STAT]; + static rpcb_stat_byvers inf; @@ -126,6 +132,10 @@ rpcbs_getaddr(rpcvers_t rtype, rpcprog_t prog, rpcvers_t vers, char *netid, if (nconf == NULL) { return; } + if (addrinfo_count[rtype] >= RPCBS_ADDRINFO_MAX) { + return; + } + al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist)); if (al == NULL) { return; @@ -142,6 +152,7 @@ rpcbs_getaddr(rpcvers_t rtype, rpcprog_t prog, rpcvers_t vers, char *netid, } al->next = inf[rtype].addrinfo; inf[rtype].addrinfo = al; addrinfo_count[rtype]+; } @@ -175,6 +186,10 @@ rpcbs_rmtcall(rpcvers_t rtype, rpcproc_t rpcbproc, rpcprog_t prog, if (nconf == NULL) { return; } + if (rmtinfo_count[rtype] >= RPCBS_RMTINFO_MAX) { + return; + } + rl = (rpcbs_rmtcalllist *) malloc(sizeof (rpcbs_rmtcalllist)); if (rl == NULL) { return; @@ -195,6 +210,7 @@ rpcbs_rmtcall(rpcvers_t rtype, rpcproc_t rpcbproc, rpcprog_t prog, rl->indirect = 1; rl->next = inf[rtype].rmtinfo; inf[rtype].rmtinfo = rl; rmtinfo_count[rtype]+; return; } ``` Alternative approaches include bounded eviction of old statistics entries or disabling tuple-level statistics by default. ------ This report was generated using AI technology. Always review AI-generated content prior to use