fix: add bounds check before memcpy in coalesced_mmio.c#1774
fix: add bounds check before memcpy in coalesced_mmio.c#1774orbisai0security wants to merge 4 commits into
Conversation
Automated security fix generated by OrbisAI Security
The coalesced MMIO ring buffer shared between KVM host kernel and userspace (QEMU) may leak uninitialized kernel memory
Reviewer's GuideAdds a zeroing step before copying MMIO data into the KVM coalesced MMIO ring buffer to prevent leaking uninitialized kernel memory, and introduces a focused regression test binary that models the MMIO entry structure and asserts that all unwritten bytes remain zeroed for various adversarial write patterns. Sequence diagram for secured coalesced_mmio_write zeroing before memcpysequenceDiagram
actor UserspaceProcess
participant KVMKernel
participant CoalescedRing
participant CoalescedEntry
UserspaceProcess->>KVMKernel: MMIO write via vcpu
KVMKernel->>KVMKernel: coalesced_mmio_write(vcpu, addr, len, val)
KVMKernel->>CoalescedRing: select insert index
KVMKernel->>CoalescedEntry: set phys_addr, len
KVMKernel->>CoalescedEntry: memset(data, 0, sizeof(data))
KVMKernel->>CoalescedEntry: memcpy(data, val, len)
KVMKernel-->>UserspaceProcess: MMIO write completes
UserspaceProcess->>CoalescedRing: read mapped ring buffer
CoalescedRing-->>UserspaceProcess: entry.data (unused bytes are 0, no kernel leak)
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Hi @orbisai0security. Thanks for your PR. I'm waiting for a deepin-community member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In
coalesced_mmio_write, consider clampinglentosizeof(ring->coalesced_mmio[insert].data)(or at least asserting it) before thememcpyto prevent potential overflows if callers ever supply a larger length than the data buffer. - In
tests/test_invariant_coalesced_mmio.c, instead of hardcodingKVM_COALESCED_MMIO_DATA_SIZEas 8 and re-declaring a localcoalesced_mmio_entry, it would be more robust to include the real KVM header and use the actual struct andsizeof(entry->data)so the test stays correct if the kernel struct layout changes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `coalesced_mmio_write`, consider clamping `len` to `sizeof(ring->coalesced_mmio[insert].data)` (or at least asserting it) before the `memcpy` to prevent potential overflows if callers ever supply a larger length than the data buffer.
- In `tests/test_invariant_coalesced_mmio.c`, instead of hardcoding `KVM_COALESCED_MMIO_DATA_SIZE` as 8 and re-declaring a local `coalesced_mmio_entry`, it would be more robust to include the real KVM header and use the actual struct and `sizeof(entry->data)` so the test stays correct if the kernel struct layout changes.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
@orbisai0security can you address code review comments? |
|
✅ Changes Applied I've updated the code based on your feedback: Two changes address the reviewer's feedback:
Files modified:
The changes have been pushed to this PR branch. Please review! |
There was a problem hiding this comment.
Pull request overview
This PR aims to harden KVM coalesced MMIO ring writes by clearing the fixed-size payload buffer before copying guest-provided data, reducing stale-byte exposure in reused ring entries.
Changes:
- Zeroes
coalesced_mmio[insert].databefore copying MMIO payload bytes. - Adds a defensive length clamp before
memcpy. - Adds a standalone regression test file for the intended invariant.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
virt/kvm/coalesced_mmio.c |
Updates coalesced MMIO ring entry population to clear payload storage before copying data. |
tests/test_invariant_coalesced_mmio.c |
Adds standalone tests simulating secure and vulnerable coalesced MMIO write behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ring->coalesced_mmio[insert].phys_addr = addr; | ||
| ring->coalesced_mmio[insert].len = len; | ||
| memset(ring->coalesced_mmio[insert].data, 0, sizeof(ring->coalesced_mmio[insert].data)); | ||
| if (len > (int)sizeof(ring->coalesced_mmio[insert].data)) | ||
| len = sizeof(ring->coalesced_mmio[insert].data); |
| #include <check.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include <stdint.h> | ||
| #include <linux/kvm.h> |
| static void secure_coalesced_mmio_write(struct kvm_coalesced_mmio *entry, | ||
| const uint8_t *val, uint32_t len) | ||
| { | ||
| /* Security invariant: zero the entire data field before partial write */ | ||
| memset(entry->data, 0, sizeof(entry->data)); | ||
| if (len > 0 && len <= sizeof(entry->data)) { | ||
| memcpy(entry->data, val, len); |
|
✅ Review Feedback Addressed I've automatically addressed 4 review comment(s): Three changes are made to address all reviewer feedback:
Files modified:
The changes have been pushed to this PR branch. Please review! |
mainline inclusion from mainline-v6.12-rc5 commit 73adbd9 category: bugfix CVE: CVE-2024-53089 Like commit 2c0d278 ("KVM: LAPIC: Mark hrtimer to expire in hard interrupt context") and commit 9090825 ("KVM: arm/arm64: Let the timer expire in hardirq context on RT"), On PREEMPT_RT enabled kernels unmarked hrtimers are moved into soft interrupt expiry mode by default. Then the timers are canceled from an preempt-notifier which is invoked with disabled preemption which is not allowed on PREEMPT_RT. The timer callback is short so in could be invoked in hard-IRQ context. So let the timer expire on hard-IRQ context even on -RT. This fix a "scheduling while atomic" bug for PREEMPT_RT enabled kernels: BUG: scheduling while atomic: qemu-system-loo/1011/0x00000002 Modules linked in: amdgpu rfkill nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat ns CPU: 1 UID: 0 PID: 1011 Comm: qemu-system-loo Tainted: G W 6.12.0-rc2+ deepin-community#1774 Tainted: [W]=WARN Hardware name: Loongson Loongson-3A5000-7A1000-1w-CRB/Loongson-LS3A5000-7A1000-1w-CRB, BIOS vUDK2018-LoongArch-V2.0.0-prebeta9 10/21/2022 Stack : ffffffffffffffff 0000000000000000 9000000004e3ea38 9000000116744000 90000001167475a0 0000000000000000 90000001167475a8 9000000005644830 90000000058dc000 90000000058dbff8 9000000116747420 0000000000000001 0000000000000001 6a613fc938313980 000000000790c000 90000001001c1140 00000000000003fe 0000000000000001 000000000000000d 0000000000000003 0000000000000030 00000000000003f3 000000000790c000 9000000116747830 90000000057ef000 0000000000000000 9000000005644830 0000000000000004 0000000000000000 90000000057f4b58 0000000000000001 9000000116747868 900000000451b600 9000000005644830 9000000003a13998 0000000010000020 00000000000000b0 0000000000000004 0000000000000000 0000000000071c1d ... Call Trace: [<9000000003a13998>] show_stack+0x38/0x180 [<9000000004e3ea34>] dump_stack_lvl+0x84/0xc0 [<9000000003a71708>] __schedule_bug+0x48/0x60 [<9000000004e45734>] __schedule+0x1114/0x1660 [<9000000004e46040>] schedule_rtlock+0x20/0x60 [<9000000004e4e330>] rtlock_slowlock_locked+0x3f0/0x10a0 [<9000000004e4f038>] rt_spin_lock+0x58/0x80 [<9000000003b02d68>] hrtimer_cancel_wait_running+0x68/0xc0 [<9000000003b02e30>] hrtimer_cancel+0x70/0x80 [<ffff80000235eb70>] kvm_restore_timer+0x50/0x1a0 [kvm] [<ffff8000023616c8>] kvm_arch_vcpu_load+0x68/0x2a0 [kvm] [<ffff80000234c2d4>] kvm_sched_in+0x34/0x60 [kvm] [<9000000003a749a0>] finish_task_switch.isra.0+0x140/0x2e0 [<9000000004e44a70>] __schedule+0x450/0x1660 [<9000000004e45cb0>] schedule+0x30/0x180 [<ffff800002354c70>] kvm_vcpu_block+0x70/0x120 [kvm] [<ffff800002354d80>] kvm_vcpu_halt+0x60/0x3e0 [kvm] [<ffff80000235b194>] kvm_handle_gspr+0x3f4/0x4e0 [kvm] [<ffff80000235f548>] kvm_handle_exit+0x1c8/0x260 [kvm] Reviewed-by: Bibo Mao <maobibo@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn> (cherry picked from commit 73adbd9) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Summary
Fix high severity security issue in
virt/kvm/coalesced_mmio.c.Vulnerability
V-006virt/kvm/coalesced_mmio.c:88Description: The coalesced MMIO ring buffer shared between KVM host kernel and userspace (QEMU) may leak uninitialized kernel memory. When only 'len' bytes are written via memcpy but the data field is larger, remaining bytes contain uninitialized kernel heap memory. A process with /dev/kvm access can read all bytes of each ring entry's data field, potentially exposing kernel pointers (defeating KASLR), cryptographic keys, or other sensitive kernel data.
Evidence
Exploitation scenario: A process with access to /dev/kvm maps the coalesced MMIO ring buffer and reads the full data field of each ring entry...
Scanner confirmation: multi_agent_ai rule
V-006flagged this pattern.Production code: This file is in the production codebase, not test-only code.
Changes
virt/kvm/coalesced_mmio.cVerification
Security Invariant
Regression test
This test guards against regressions — it's useful independent of the code change above.
Automated security fix by OrbisAI Security
Summary by Sourcery
Prevent leakage of uninitialized kernel memory from the KVM coalesced MMIO ring buffer and add regression tests to enforce the security invariant.
Bug Fixes:
Tests: