Bug 2554514
| Summary: | CVE-2026-89096 nfs-utils: nfs-utils: Denial of Service via memory leak in rpc.statd [fedora-all] | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Marco Benatto <mbenatto> |
| Component: | nfs-utils | Assignee: | Steve Dickson <steved> |
| Status: | NEW --- | QA Contact: | Fedora Extras Quality Assurance <extras-qa> |
| Severity: | medium | Docs Contact: | |
| Priority: | medium | ||
| Version: | rawhide | CC: | luk.claes, steved |
| Target Milestone: | --- | Keywords: | Security, SecurityTracking |
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Unspecified | ||
| Whiteboard: | {"flaws": ["f1da1bf4-11ab-4a28-b41e-7706c779e17b"]} | ||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: | 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: | |||
| Bug Blocks: | 2462372 | ||
Disclaimer: Community trackers are created by Red Hat Product Security team on a best effort basis. Package maintainers are required to ascertain if the flaw indeed affects their package, before starting the update process. AI_ONLY_REPORT package: nfs-utils-2.8.3-5.el10_2 ------ Summary: Memory Leak in nlist_free Leading to Remote Denial of Service: `rpc.statd` leaks `notify_list` structures during matching `SM_NOTIFY` callback cleanup, allowing sustained heap growth and eventual denial of service in exposed deployments. Requirements to exploit: The attacker needs network reachability to `rpc.statd` on a deployment that accepts remote `SM_NOTIFY` requests, at least one monitored host present in `rtnl`, and a `mon_name` or source address that matches that monitored host while alternating `state` values. Host-based access controls or firewalling can reduce or block reachability in some deployments. Component affected: `nfs-utils` `rpc.statd`: `utils/statd/notlist.c` (`nlist_free`), remote `SM_NOTIFY` handling in `utils/statd/callback.c`, callback cleanup in `utils/statd/rmtcall.c`, and related `rtnl` cleanup in `utils/statd/monitor.c` Version affected: `nfs-utils-2.8.3-5.el10_2` when `rpc.statd` is running, accepts remote `SM_NOTIFY` traffic, and has at least one monitored host entry present 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 vulnerable entry point is the network-facing `SM_NOTIFY` path in `rpc.statd`. AC:H - Successful exploitation requires a reachable deployment, a matching monitored host, and sustained state-changing `SM_NOTIFY` traffic. PR:N - The vulnerable code path itself does not require prior authentication. UI:N - No user interaction is required once the service is reachable. S:U - The impact remains within the `rpc.statd` service boundary. C:N - No confidentiality impact is established by the available evidence. I:N - No integrity impact is established by the available evidence. A:H - Repeated requests can drive unbounded heap growth in `rpc.statd` and eventually degrade or stop service. Impact: Moderate. Under Red Hat's severity guidance, remote denial of service issues are often Important when they are easy to trigger. Here, exploitation is more constrained because it depends on exposed `rpc.statd`, an existing monitored-host match, and repeated state toggling, so Moderate is the better fit. Embargo: no Reason: This is a configuration-dependent availability issue with no demonstrated confidentiality or integrity impact, and exposure can be reduced immediately by restricting access to `rpc.statd`. Acknowledgement: Aisle Research Vulnerability Details: The code shows an ownership mismatch around `nlist_free()`. The function removes an entry from its list and frees internal strings, but it does not free the `notify_list` structure itself: ```c void nlist_free(notify_list **head, notify_list *entry) { if (head && (*head)) nlist_remove(head, entry); if (NL_MY_NAME(entry)) free(NL_MY_NAME(entry)); if (NL_MON_NAME(entry)) free(NL_MON_NAME(entry)); free(entry->dns_name); } ``` Remote `SM_NOTIFY` handling can allocate fresh `notify_list` objects by cloning a matched monitored-host entry and queueing it on `notify` whenever the state changes: ```c for (lp = rtnl ; lp ; lp = lp->next) if (NL_STATE(lp) != argp->state && (statd_matchhostname(argp->mon_name, lp->dns_name) || statd_matchhostname(ip_addr, lp->dns_name))) { NL_STATE(lp) = argp->state; call = nlist_clone(lp); nlist_insert(¬ify, call); } ``` Those queued entries are later cleaned only with `nlist_free()` in the callback processing paths, without a corresponding `free()` of the structure: ```c } else { xlog(D_GENERAL, "%s: Callback to %s (for %s) succeeded", _func_, NL_MY_NAME(lp), NL_MON_NAME(lp)); } nlist_free(¬ify, lp); return 1; } ... } else { xlog(L_ERROR, "%s: Can't callback %s (%d,%d), giving up", _func_, NL_MY_NAME(entry), NL_MY_PROG(entry), NL_MY_VERS(entry)); nlist_free(¬ify, entry); } } ``` Taken together, these observed code paths create a repeatable allocate-then-leak cycle on the `notify` queue. The established impact is denial of service through memory growth. The same ownership mismatch also appears in `SM_UNMON` and `SM_UNMON_ALL` cleanup for `rtnl` entries, which is why the proposed patch below also adds explicit `free(clnt)` calls in `utils/statd/monitor.c`. Remote exploitability remains deployment-dependent because the request must reach `rpc.statd` and satisfy the monitored-host matching logic. Steps to reproduce: 1. Start `rpc.statd` in a deployment where it accepts remote `SM_NOTIFY` traffic and has at least one monitored host entry loaded or registered (`rtnl != NULL`). 2. Identify a monitored host name or source address that satisfies the `statd_matchhostname()` comparison against `lp->dns_name`. 3. Send repeated `SM_NOTIFY` RPC requests for that host while alternating `state` values so `NL_STATE(lp) != argp->state` remains true. 4. Allow the event loop to process queued entries through `process_notify_list()` and `process_reply()`. 5. Observe `rpc.statd` RSS or heap usage growing over time until the service becomes degraded or unavailable. Mitigation: Until a fix is available, restrict network access to `rpc.statd` to trusted NFS peers only. Where supported by the build and deployment, host-based access controls and firewall rules can block untrusted `SM_NOTIFY` sources. Restarting `rpc.statd` reclaims leaked memory but does not remove the underlying flaw. Proposed Fix: A minimally scoped correction is to keep `nlist_free()` ownership semantics unchanged and explicitly free callers that currently leak after cleanup: ```diff diff --git a/utils/statd/rmtcall.c b/utils/statd/rmtcall.c @@ nlist_free(¬ify, lp); + free(lp); return 1; @@ nlist_free(¬ify, entry); + free(entry); } } diff --git a/utils/statd/monitor.c b/utils/statd/monitor.c @@ nsm_delete_monitored_host(clnt->dns_name, mon_name, my_name, 1); nlist_free(&rtnl, clnt); + free(clnt); return (&result); @@ nsm_delete_monitored_host(clnt->dns_name, mon_name, my_name, 1); nlist_free(&rtnl, clnt); + free(clnt); ++count; clnt = temp; ``` This avoids changing `nlist_free()` ownership semantics globally and prevents introducing double-free bugs at mixed call sites. ------ This report was generated using AI technology. Always review AI-generated content prior to use