Bug 2469511 (CVE-2026-89098) - CVE-2026-89098 nfs-utils: nfs-utils: Denial of Service via assertion failure in fsidd
Summary: CVE-2026-89098 nfs-utils: nfs-utils: Denial of Service via assertion failure ...
Keywords:
Status: NEW
Alias: CVE-2026-89098
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security
QA Contact:
URL:
Whiteboard:
Depends On: 2554300
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-11 20:31 UTC by OSIDB Bzimport
Modified: 2026-10-16 18:16 UTC (History)
18 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-11 20:31:37 UTC
AI_ONLY_REPORT
package: nfs-utils-2.8.3-5.el10_2
------
Summary: Local DoS in fsidd via Reachable assert() on Empty Command  
Arguments: a local unprivileged user can terminate `fsidd` by sending a  
malformed command containing only a valid command prefix and trailing  
space, causing a denial of service for reexport FSID lookups until the  
daemon is restarted.
Requirements to exploit: Local access to a system where `fsidd` is running  
for reexport functionality, with the ability to connect to its abstract  
UNIX domain socket and send a crafted request.
Component affected: `nfs-utils`; `support/reexport/fsidd.c`; `client_cb()`
Version affected: `nfs-utils-2.8.3-5.el10_2`, when `fsidd` is present and  
in use for reexport workflows
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 5.5 (MEDIUM)
AV:L - Exploitation requires local access to the host and access to the  
`fsidd` UNIX socket.
AC:L - A single malformed request is sufficient to reach the failing  
assertion.
PR:N - No protocol-level authentication is required before the request  
is parsed.
UI:N - No user interaction is needed once local access is available.
S:U - The impact is limited to the vulnerable service itself.
C:N - No confidentiality impact was established.
I:N - No integrity impact was established.
A:H - Successful exploitation aborts `fsidd`, disrupting FSID lookup  
handling for reexport use until restart.
Impact: Moderate. This issue enables a reliable local denial of service  
against `fsidd`, but the impact is limited to availability and depends on a  
deployment that actually uses `fsidd` for reexport handling. Under Red  
Hat's severity guidance, this is more appropriately Moderate than Important  
because it is not a remote flaw, does not expose confidentiality or  
integrity, and affects a configuration-dependent service path rather than a  
broadly reachable default remote attack surface.
Embargo: no
Reason: This is a local, configuration-dependent denial of service with  
straightforward mitigation and no demonstrated confidentiality, integrity,  
or privilege-escalation impact.
Acknowledgement: Aisle Research
Vulnerability Details: In `client_cb()`, `fsidd` parses several commands  
received over its local socket and relies on `assert()` to enforce that an  
argument is present after the command prefix. The following exact checks  
are reachable from untrusted input:
```c
if (strncmp(buf, "get_fsidnum ", strlen("get_fsidnum ")) == 0) {
char *req_path = buf + strlen("get_fsidnum ");
...
assert(req_path < buf + n );
}
...
} else if (strncmp(buf, "get_or_create_fsidnum ",  
strlen("get_or_create_fsidnum ")) == 0) {
char *req_path = buf + strlen("get_or_create_fsidnum ");
...
assert(req_path < buf + n );
}
...
} else if (strncmp(buf, "get_path ", strlen("get_path ")) == 0) {
char *req_fsidnum = buf + strlen("get_path ");
...
assert(req_fsidnum < buf + n );
}
```
If a request is exactly the command prefix plus a trailing space, such as  
`get_fsidnum `, then the parsed argument pointer is equal to `buf + n` and  
the assertion fails. In an assertion-enabled build, this causes `fsidd` to  
abort.
The default socket name is defined as an abstract UNIX socket:
```c
#define FSID_SOCKET_NAME "@/run/fsid.sock"
```
Based on the available code and report evidence, `fsidd` processes requests  
on this socket without checking peer credentials first, so local socket  
access is sufficient to reach the vulnerable path. The operational effect  
is a local denial of service against `fsidd`, which can interrupt reexport  
FSID lookup handling until the service is restarted.
Steps to reproduce:
1. Use a system where `fsidd` is running for reexport handling.
2. Verify that the service is active.
```bash
systemctl status fsidd
```
3. Send a malformed command containing a valid command name, trailing  
space, and no argument to the abstract UNIX seqpacket socket.
```bash
python3 - <<'PY'
import socket
s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
s.connect("\0/run/fsid.sock")
s.sendall(b"get_fsidnum ")
PY
```
4. Observe that `fsidd` terminates with an assertion failure or `SIGABRT`,  
for example in the service journal.
```bash
journalctl -u fsidd -n 20 --no-pager
```
5. Confirm that reexport FSID lookup operations fail until `fsidd` is  
restarted.
Mitigation: Where reexport support is not required, disable the affected  
`fsidd` usage path. Otherwise, restrict untrusted local access to the host  
and apply input validation so malformed requests are rejected instead of  
reaching `assert()`. A service restart policy may reduce outage duration,  
but it does not prevent the crash condition.
Proposed Fix: Replace the reachable assertions with explicit  
malformed-input handling and return an error to the client.
```diff
diff --git a/support/reexport/fsidd.c b/support/reexport/fsidd.c
— a/support/reexport/fsidd.c
+++ b/support/reexport/fsidd.c
@@ -48,7 +48,12 @@ static void client_cb(evutil_socket_t cl, short ev, void  
*d)
char *answer = NULL;
bool found;
-		assert(req_path < buf + n );
+		if (req_path >= buf + n) {
+			char answer[] = "- Command failed: Bad input";
+			(void)send(cl, answer, strlen(answer), 0);
+			return;
+		}
@@ -70,7 +75,12 @@ static void client_cb(evutil_socket_t cl, short ev, void  
*d)
char *answer = NULL;
bool found;
-		assert(req_path < buf + n );
+		if (req_path >= buf + n) {
+			char answer[] = "- Command failed: Bad input";
+			(void)send(cl, answer, strlen(answer), 0);
+			return;
+		}
@@ -94,7 +104,12 @@ static void client_cb(evutil_socket_t cl, short ev,  
void *d)
uint32_t fsidnum;
bool found;
-		assert(req_fsidnum < buf + n );
+		if (req_fsidnum >= buf + n) {
+			char answer[] = "- Command failed: Bad input";
+			(void)send(cl, answer, strlen(answer), 0);
+			return;
+		}
```
------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.