https://bugs.dpdk.org/show_bug.cgi?id=2001

            Bug ID: 2001
           Summary: vhost-crypto TOCTOU out-of-bounds write
           Product: DPDK
           Version: unspecified
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: normal
          Priority: Normal
         Component: vhost/virtio
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---
             Group: security

Report date: 2026-03-11
Reported by: Adiel Sol <[email protected]>

Hi DPDK Security Team,
I would like to report a security vulnerability in DPDK vhost-crypto.
Summary
The vhost-crypto code has a time-of-check to time-of-use (TOCTOU) bug in the
path that finalizes a crypto request. When the host finishes a request, it
writes the result into the virtio used ring. The descriptor index for that
write is read again from the guest-writable available ring at finalization
time, and the code does not check that this index is within the virtqueue size.
Between the initial fetch and finalization, a malicious guest can change that
value in shared memory. The host then uses the guest-controlled value as an
index and writes to vq->used->ring[desc_idx], causing an out-of-bounds write
(up to about 524 KB past the used ring when the index is 0xFFFF). The used ring
has only 256 entries. A malicious guest with a vhost-crypto device can trigger
this to corrupt host DPDK process memory. In practice this can lead to host
crash or arbitrary code execution on the host (guest escape). Because the DPDK
process usually runs as root, a successful exploit can mean full control of the
host.
Affected Component

  *   lib/vhost/vhost_crypto.c (finalize path; function
vhost_crypto_finalize_one_request() and the code that re-reads desc_idx from
vq->avail->ring[used_idx] and writes to vq->used->ring[desc_idx] without
validation).
  *   Versions: DPDK 26.03.0-rc1 and earlier versions that include the
vhost-crypto finalize path. Any product that uses DPDK vhost-crypto in the same
way may be affected.

Root Cause
At fetch time the host correctly masks used_idx and reads desc_idx from the
available ring. At finalize time the code reads desc_idx again from
vq->avail->ring[used_idx] (guest-writable shared memory) and then writes
vq->used->ring[desc_idx].id and .len with no check that desc_idx < vq->size.
The available ring is writable by the guest at any time. Between fetch and
finalize the host is busy with the crypto operation (enqueue to cryptodev, wait
for completion), so the guest has a long race window (microseconds to
milliseconds) to overwrite vq->avail->ring[used_idx] with any 16-bit value
(e.g. 0xFFFF). The host then uses that value as an index. The used ring has
only vq->size entries (e.g. 256), so indexing with 0xFFFF causes a write at
65535 * 8 bytes past the start of the ring, i.e. an out-of-bounds write into
host process memory. The attacker controls the write offset and partially the
written data (the .id value comes from another guest-controlled slot; the .len
from the request). So the bug is a TOCTOU with missing input validation
(CWE-367, CWE-787, CWE-20).
Impact

  *   CVSS 3.1: High (e.g. AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H or similar;
guest-to-host escape, host RCE in scope).
  *   CWE-787 (Out-of-bounds Write), CWE-367 (TOCTOU Race Condition), CWE-20
(Improper Input Validation).
  *   A malicious guest VM with a vhost-crypto device can trigger the overflow
by submitting a valid crypto request and then overwriting the available ring
slot during the crypto operation. No special guest setup is required; the race
window is the duration of the crypto operation.
  *   Successful exploitation can lead to memory corruption in the host DPDK
process, then to arbitrary code execution on the host (guest escape) and full
compromise of the host (backdoors, pivot, etc.), often as root.

Proof of Concept

  1.  We provide two proof-of-concept programs that simulate the vulnerable
pattern (shared virtqueue, host thread, guest thread). They do not run against
a full DPDK build but demonstrate the TOCTOU and the resulting out-of-bounds
access and control-flow hijack.
  2.
OOB detection: In the PoC directory, run ./run_poc.sh. The code is built with
AddressSanitizer. The host thread fetches a request (reads desc_idx = 0), then
the guest thread overwrites the available ring slot to 0xFFFF. When the host
thread finalizes, it re-reads desc_idx and writes to used_ring[0xFFFF].
AddressSanitizer reports a SEGV (or heap-buffer-overflow) in the host thread at
the finalize line, proving the out-of-bounds access.
  3.
Control-flow hijack (guest escape / RCE): Run make run-rce in the same
directory. The layout is set so that used_ring[256] (one past the end)
overwrites a function pointer. The guest sets desc_idx = 256 and the two 32-bit
halves of the payload address. When the host calls the completion callback
after finalize, it runs the attacker-supplied function. The program prints
"PWNED: guest escape - host is now running attacker code!" This shows that the
same primitive can redirect execution and is sufficient to demonstrate the
guest-escape / RCE impact in concept.
  4.
The PoC sources, build instructions, and a captured ASan run are in the
disclosure package (e.g. poc-dpdk-vhost-crypto-toctou/ with
vhost_crypto_toctou_poc.c, vhost_toctou_rce_poc.c, run_poc.sh,
PROOF-OUTPUT.txt).

Credit Request
We kindly request that the following researchers be credited for this
discovery:
Adiel Sol, Arad Inbar, Erez Cohen, Nir Somech, Ben Grinberg, Daniel Lubel –
DREAM Security Research Team

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to