Bug 2462372 (CVE-2026-89096)

Summary: CVE-2026-89096 nfs-utils: nfs-utils: Denial of Service via memory leak in rpc.statd
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 nfs-utils. An unauthenticated remote attacker can trigger a Denial of Service (DoS) by sending repeated state notification requests to an exposed rpc.statd service. The service fails to properly release memory allocated during callback processing, leading to continuous memory growth. Sustained requests can exhaust system resources, eventually causing the service to degrade or crash.
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: 2554514    
Bug Blocks:    

Description OSIDB Bzimport 2026-04-26 18:58:36 UTC
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(&notify, 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(&notify, 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(&notify, 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(&notify, lp);
+	free(lp);
return 1;
@@
nlist_free(&notify, 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