Bug 2511484 - CVE-2026-71226 libkcapi: Memory corruption via uncanceled AIO requests on error in libkcapi's one-shot AIO path [fedora-all]
Summary: CVE-2026-71226 libkcapi: Memory corruption via uncanceled AIO requests on err...
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": ["a41e9ad2-0d7c-47ef-b776-4...
Depends On:
Blocks: CVE-2026-71226
TreeView+ depends on / blocked
 
Reported: 2026-08-05 12:24 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:28 UTC
Type: ---
Embargoed:
fedora-admin-xmlrpc: mirror+


Attachments (Terms of Use)

Description Vladimir Vasilev 2026-08-05 12:24:41 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: Memory Corruption via Uncanceled AIO Requests on Error: libkcapi's  
one-shot AIO path can return an error before all submitted IOCBs are  
drained, allowing later kernel writes into caller-owned output buffers.
Requirements to exploit: A consumer must use the one-shot AIO interfaces  
with `KCAPI_INIT_AIO` so the real AIO backend is active, hit an error after  
one or more IOCBs have been submitted or completed, and then free or reuse  
the referenced `outiov` buffers before all kernel completions finish.
Component affected: `libkcapi-1.5.0-3.el10`, `lib/kcapi-kernel-if.c`,  
`_kcapi_aio_read_all()`, `_kcapi_aio_read_iov()`,  
`_kcapi_cipher_crypt_aio()` in the one-shot AIO path
Version affected: `libkcapi-1.5.0-3.el10` when the handle is initialized  
with `KCAPI_INIT_AIO` and libkcapi enables its real kernel AIO backend
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Unknown.
CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H - 6.8 (MEDIUM)
AV:L - exploitation is local to the process using libkcapi.
AC:L - once the real AIO path is active, the unsafe behavior is reached  
directly through documented error paths after request submission.
PR:N - no elevated privileges are required beyond the ability to  
exercise the affected API in the local process.
UI:N - no separate user interaction is required.
S:U - the impact stays within the security scope of the calling process.
C:L - late writes into reused buffers can expose limited process data.
I:L - late kernel writes can alter caller memory after the library has  
reported failure.
A:H - heap corruption or process termination is a realistic outcome.
Impact: Moderate. This flaw can cause real process memory corruption, but  
it depends on an opt-in AIO configuration, kernel AIO availability, and an  
error path after submission rather than a default or easily reachable  
execution path. Under Red Hat's severity guidance, that is more consistent  
with Moderate impact than Important or Critical.
Embargo: no
Reason: the issue is local and configuration-dependent, requires  
explicit AIO use plus an error-path trigger, and does not present a  
straightforward remote compromise scenario.
Acknowledgement: Aisle Research
Vulnerability Details: In the affected one-shot AIO path, libkcapi can  
return failure before all submitted kernel requests are drained.  
`_kcapi_aio_read_all()` returns immediately on the first negative  
completion result, and `_kcapi_aio_read_iov()` returns immediately on a  
short `io_submit()` result even if some IOCBs were already submitted.  
`_kcapi_cipher_crypt_aio()` then propagates that error directly to the  
caller. If the caller treats the operation as failed and promptly frees or  
reuses `outiov[*].iov_base`, later kernel completions may still write into  
those buffers.
```c
if (events[i].res < 0) {
handle->aio.iocb_ret[events[i].data] =
events[i].res;
return (int)events[i].res;
}
...
ret = io_submit(handle->aio.aio_ctx, (long)iovlen, handle->aio.ciopp);
if ((uint32_t)ret != iovlen) {
if (ret < 0) {
ret = -errno;
kcapi_dolog(KCAPI_LOG_ERR, "io_read Error: %d\n", ret);
return ret;
} else {
kcapi_dolog(KCAPI_LOG_ERR,
"Could not sumbit AIO read\n");
return -EIO;
}
}
```
```c
ret = _kcapi_aio_read_iov(handle, outiov, process);
if (ret < 0)
return ret;
```
The issue is not established for the default synchronous path. Reachability  
depends on the caller enabling `KCAPI_INIT_AIO` so libkcapi uses the real  
kernel AIO backend.
Steps to reproduce:
1. Build an ASAN-enabled harness that calls `kcapi_cipher_encrypt_aio()` or  
`kcapi_aead_decrypt_aio()` with multiple output `iovec` entries.
2. Initialize the handle with `KCAPI_INIT_AIO` so the real AIO path is  
active.
3. Force a deterministic short-submit path with an `LD_PRELOAD` wrapper  
around `syscall(__NR_io_submit, ...)` that returns `0 < ret < iovlen` after  
forwarding only the first `N` IOCBs.
4. Optionally fault-inject `io_getevents()` so one returned event has `res  
< 0` before all completions are consumed.
5. When the API returns an error, immediately free or reallocate the  
`outiov[*].iov_base` buffers.
6. Observe delayed writes into freed or reused memory, for example as an  
ASAN use-after-free, heap corruption, or a canary mismatch.
Mitigation: Until a fix is available, avoid initializing affected handles  
with `KCAPI_INIT_AIO` and prefer the synchronous interfaces. If the real  
AIO path must remain enabled, applications should not immediately free or  
reuse `outiov` buffers after an error return.
Proposed Fix: Drain all submitted requests before returning an error. A  
minimal approach is to record the first completion error, continue draining  
outstanding completions, and drain any successfully submitted subset after  
a short `io_submit()` result.
```diff
diff --git a/lib/kcapi-kernel-if.c b/lib/kcapi-kernel-if.c
— a/lib/kcapi-kernel-if.c
+++ b/lib/kcapi-kernel-if.c
@@ -420,6 +420,7 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle,  
size_t toread,
struct timespec *timeout)
{
+	int first_err = 0;
if (toread > KCAPI_AIO_CONCURRENT)
return -EINVAL;
@@ -440,8 +441,10 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle,  
size_t toread,
if (events[i].res < 0) {
handle->aio.iocb_ret[events[i].data] =
events[i].res;
-				return (int)events[i].res;
+				if (!first_err)
+					first_err = (int)events[i].res;
+				continue;
}
@@ -467,7 +470,7 @@ int _kcapi_aio_read_all(struct kcapi_handle *handle,  
size_t toread,
toread -= (uint32_t)rc;
}
-	return 0;
+	return first_err;
}
@@ -534,15 +537,20 @@ int _kcapi_aio_read_iov(struct kcapi_handle *handle,
ret = io_submit(handle->aio.aio_ctx, (long)iovlen, handle->aio.ciopp);
if ((uint32_t)ret != iovlen) {
+		size_t submitted = (ret > 0) ? (size_t)ret : 0;
+		int submit_err = (ret < 0) ? -errno : -EIO;
if (ret < 0) {
-			ret = -errno;
kcapi_dolog(KCAPI_LOG_ERR, "io_read Error: %d\n", ret);
-			return ret;
} else {
kcapi_dolog(KCAPI_LOG_ERR,
"Could not sumbit AIO read\n");
-			return -EIO;
}
+		if (submitted) {
+			int drain = _kcapi_aio_read_all(handle, submitted, NULL);
+			if (submit_err == 0 && drain < 0)
+				submit_err = drain;
+		}
+		return submit_err;
}
```
(Equivalent fix using `io_cancel` + confirmed drain is also acceptable.)
------
This report was generated using AI technology. Always review AI-generated  
content prior to use

Comment 1 Aoife Moloney 2026-08-17 15:46:45 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:18 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:35 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:02 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:00 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:28 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:48 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.