Bug 2511487 - CVE-2026-71227 libkcapi: Infinite loop denial of service in libkcapi _kcapi_aio_read_all() due to unhandled io_getevents() timeout return [fedora-all]
Summary: CVE-2026-71227 libkcapi: Infinite loop denial of service in libkcapi _kcapi_a...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: libkcapi
Version: 45
Hardware: Unspecified
OS: Unspecified
medium
medium
Target Milestone: ---
Assignee: Ondrej Mosnáček
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard: {"flaws": ["f10a1128-44b5-463b-b58e-f...
Depends On:
Blocks: CVE-2026-71227
TreeView+ depends on / blocked
 
Reported: 2026-08-05 12:32 UTC by Vladimir Vasilev
Modified: 2026-08-21 03:05 UTC (History)
4 users (show)

Fixed In Version: libkcapi-1.5.1-2.fc45 libkcapi-1.5.1-2.fc46
Clone Of:
Environment:
Last Closed: 2026-08-20 17:35:31 UTC
Type: ---
Embargoed:
fedora-admin-xmlrpc: mirror+


Attachments (Terms of Use)

Description Vladimir Vasilev 2026-08-05 12:32:34 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: libkcapi-1.5.0-3.el10
------
Summary: Denial of Service via Infinite Loop in AIO Read on Timeout: reuse  
of an AIO-enabled handle after a prior completion error can leave  
`_kcapi_aio_read_all()` in a non-progress timeout loop and hang the caller  
indefinitely.
Requirements to exploit: An attacker must be able to influence an  
application that uses the AIO interface from `libkcapi-1.5.0-3.el10`,  
initializes handles with `KCAPI_INIT_AIO`, triggers at least one AIO  
completion error, and then reuses the same handle in a later AIO operation  
so that `_kcapi_aio_read_iov()` waits for more completions than remain  
outstanding.
Component affected: `libkcapi-1.5.0-3.el10`, `lib/kcapi-kernel-if.c`,  
`_kcapi_aio_read_all()` and `_kcapi_aio_read_iov()`
Version affected: `libkcapi-1.5.0-3.el10`, when built with AIO support and  
exercised through handles initialized with `KCAPI_INIT_AIO`
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:H/PR:N/UI:N/S:U/C:N/I:N/A:H - 5.1 (MEDIUM)
AV:L - The available evidence establishes exploitability through a local  
process invoking the affected library AIO path; broader remote reachability  
depends on a consuming application and is not established here.
AC:H - Triggering the flaw requires an AIO-enabled path,  
`KCAPI_INIT_AIO`, at least one completion error, and later handle reuse  
with more requested completions than remain outstanding.
PR:N - No privileges are required to invoke the affected API path.
UI:N - No separate user interaction is required once attacker-controlled  
input reaches the affected AIO flow.
S:U - The impact remains within the vulnerable process.
C:N - No confidentiality impact is established.
I:N - No integrity impact is established.
A:H - The affected thread or request path can enter a non-terminating  
wait loop, causing a persistent denial of service.
Impact: Moderate. Under Red Hat's severity guidance, this is more than Low  
because a successful trigger can reliably deny availability for an affected  
thread or operation. It is below Important because exploitability depends  
on the optional AIO interface, `KCAPI_INIT_AIO`, and a specific  
error-and-reuse sequence that is not shown to be the default or broadly  
reachable deployment path.
Embargo: no
Reason: This is an availability-only issue in a configuration-dependent  
AIO code path with a practical workaround, so non-embargoed handling is  
appropriate.
Acknowledgement: Aisle Research
Vulnerability Details: In `lib/kcapi-kernel-if.c`, `_kcapi_aio_read_all()`  
waits for `toread` completions but does not handle a timeout return of `0`  
from `io_getevents()`:
```c
while (toread) {
int rc = io_getevents(handle->aio.aio_ctx, 1, (long)toread, events,  
timeout);
if (rc < 0)
return rc;
...
toread -= (uint32_t)rc;
}
```
If `io_getevents()` times out and returns `0`, `toread` is unchanged and  
the loop makes no progress. `_kcapi_aio_read_iov()` can drive that  
condition while waiting for a busy IOCB slot:
```c
while (cb->aio_fildes) {
struct timespec timeout = { .tv_sec = 0, .tv_nsec = 10000 };
ret = _kcapi_aio_read_all(handle, iovlen, &timeout);
if (ret < 0)
return ret;
}
```
The available evidence indicates that, after an earlier AIO completion  
error causes `_kcapi_aio_read_all()` to return before all slots are  
drained, a later reuse of the same handle can call  
`_kcapi_aio_read_all(handle, iovlen, &timeout)` even when fewer completions  
can still arrive. Repeated timeout returns then leave the caller in a  
non-terminating wait loop. The demonstrated impact is denial of service  
through a stuck thread or operation; no confidentiality or integrity impact  
is established.
Steps to reproduce:
1. Use a build with AIO enabled and initialize a handle with  
`KCAPI_INIT_AIO`.
2. Call an AIO API such as `kcapi_aead_decrypt_aio` or `kcapi_cipher_*_aio`  
with multiple IOVs and force at least one completion error, for example by  
supplying an invalid AEAD tag for one request.
3. Reuse the same handle for another AIO call where `iovlen` is greater  
than the number of still-completable prior events.
4. Observe `_kcapi_aio_read_iov()` entering `while (cb->aio_fildes)` and  
repeatedly calling `_kcapi_aio_read_all(handle, iovlen, &timeout)`.
5. Observe `io_getevents(..., timeout)` returning `0` repeatedly while  
`_kcapi_aio_read_all()` does not reduce `toread`, leaving the thread stuck.
Mitigation: Until a fixed package is available, avoid the affected AIO path  
where feasible. If AIO must be used, do not reuse a handle after any AIO  
completion error; destroy and reinitialize the handle before subsequent AIO  
operations. Deployments that do not require AIO should avoid initializing  
handles with `KCAPI_INIT_AIO`.
Proposed Fix: A minimal fix is to treat zero-completion timeouts as errors,  
clear IOCB slot state before returning the first completion error, and wait  
for only one completion while recycling a busy IOCB slot.
```diff
diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c
@@ -426,6 +426,7 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle,  
size_t toread,
while (toread) {
+		int first_err = 0;
int i;
struct io_event events[KCAPI_AIO_CONCURRENT];
int rc = io_getevents(handle->aio.aio_ctx, 1, (long)toread,
@@ -433,18 +434,24 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle,  
size_t toread,
if (rc < 0)
return rc;
+		if (rc == 0)
+			return timeout ? -ETIMEDOUT : -EIO;
for (i = 0; i < rc; i++) {
struct iocb *cb;
-			if (events[i].res < 0) {
+			if (events[i].res < 0 && !first_err)
+				first_err = (int)events[i].res;
+			if (events[i].res < 0)
handle->aio.iocb_ret[events[i].data] = events[i].res;
-				return (int)events[i].res;
-			}
-
-			cb = (struct iocb *)(uintptr_t)events[i].obj;
-			if (events[i].res > 0)
+			else if (events[i].res > 0)
handle->aio.iocb_ret[events[i].data] = events[i].res;
-			else
+			else {
+				cb = (struct iocb *)(uintptr_t)events[i].obj;
handle->aio.iocb_ret[events[i].data] = (__s64)cb->aio_nbytes;
+			}
+
+			cb = (struct iocb *)(uintptr_t)events[i].obj;
cb->aio_fildes = 0;
}
+		if (first_err)
+			return first_err;
toread -= (uint32_t)rc;
}
@@ -510,7 +517,7 @@ int _kcapi_aio_read_iov(struct kcapi_handle *handle,
struct timespec timeout;
timeout.tv_sec = 0;
timeout.tv_nsec = 10000;
-			ret = _kcapi_aio_read_all(handle, iovlen, &timeout);
+			ret = _kcapi_aio_read_all(handle, 1, &timeout);
if (ret < 0)
return ret;
}
```
------
This report was generated using AI technology. Always review AI-generated  
content prior to use

Comment 1 Aoife Moloney 2026-08-17 15:46:47 UTC
This bug appears to have been reported against 'rawhide' during the Fedora Linux 45 development cycle.
Changing version to 45.

Comment 2 Fedora Update System 2026-08-18 18:53:22 UTC
FEDORA-2026-4ba4b4f139 (libkcapi-1.5.1-1.fc45) has been submitted as an update to Fedora 45.
https://bodhi.fedoraproject.org/updates/FEDORA-2026-4ba4b4f139

Comment 3 Fedora Update System 2026-08-18 18:54:40 UTC
FEDORA-2026-6a1526575a (libkcapi-1.5.1-1.fc46) has been submitted as an update to Fedora 46.
https://bodhi.fedoraproject.org/updates/FEDORA-2026-6a1526575a

Comment 4 Fedora Update System 2026-08-20 13:05:05 UTC
FEDORA-2026-1a1eac3dfb (libkcapi-1.5.1-2.fc45) has been submitted as an update to Fedora 45.
https://bodhi.fedoraproject.org/updates/FEDORA-2026-1a1eac3dfb

Comment 5 Fedora Update System 2026-08-20 13:06:03 UTC
FEDORA-2026-e3ee465ab3 (libkcapi-1.5.1-2.fc46) has been submitted as an update to Fedora 46.
https://bodhi.fedoraproject.org/updates/FEDORA-2026-e3ee465ab3

Comment 6 Fedora Update System 2026-08-20 17:35:31 UTC
FEDORA-2026-1a1eac3dfb (libkcapi-1.5.1-2.fc45) has been pushed to the Fedora 45 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 7 Fedora Update System 2026-08-21 03:05:51 UTC
FEDORA-2026-e3ee465ab3 (libkcapi-1.5.1-2.fc46) has been pushed to the Fedora 46 stable repository.
If problem still persists, please make note of it in this bug report.


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