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-utilsAssignee: Steve Dickson <steved>
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: medium    
Version: rawhideCC: 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    

Description Marco Benatto 2026-10-16 22:54:45 UTC
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(&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