[syzbot] [kvm?] WARNING in kvm_read_guest_offset_cached

22 views
Skip to first unread message

syzbot

unread,
Jul 16, 2025, 1:05:35 AM7/16/25
to k...@vger.kernel.org, linux-...@vger.kernel.org, pbon...@redhat.com, syzkall...@googlegroups.com
Hello,

syzbot found the following issue on:

HEAD commit: 155a3c003e55 Merge tag 'for-6.16/dm-fixes-2' of git://git...
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=103e858c580000
kernel config: https://syzkaller.appspot.com/x/.config?x=8d5ef2da1e1c848
dashboard link: https://syzkaller.appspot.com/bug?extid=bc0e18379a290e5edfe4
compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=153188f0580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=16f6198c580000

Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-155a3c00.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/725a320dfe66/vmlinux-155a3c00.xz
kernel image: https://storage.googleapis.com/syzbot-assets/9f06899bb6f3/bzImage-155a3c00.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+bc0e18...@syzkaller.appspotmail.com

------------[ cut here ]------------
WARNING: CPU: 0 PID: 6107 at arch/x86/kvm/../../../virt/kvm/kvm_main.c:3459 kvm_read_guest_offset_cached+0x3f5/0x4b0 virt/kvm/kvm_main.c:3459
Modules linked in:
CPU: 0 UID: 0 PID: 6107 Comm: syz.0.16 Not tainted 6.16.0-rc6-syzkaller-00002-g155a3c003e55 #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:kvm_read_guest_offset_cached+0x3f5/0x4b0 virt/kvm/kvm_main.c:3459
Code: 0f 01 e8 3e 6c 61 00 e9 9b fc ff ff e8 14 25 85 00 48 8b 3c 24 31 d2 48 89 ee e8 16 bf fa 00 e9 2e fe ff ff e8 fc 24 85 00 90 <0f> 0b 90 bb ea ff ff ff e9 4d fe ff ff e8 e9 24 85 00 48 8b 74 24
RSP: 0018:ffffc9000349f960 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888050329898 RCX: ffffffff8136ca66
RDX: ffff88803cfa8000 RSI: ffffffff8136cd84 RDI: 0000000000000006
RBP: 0000000000000004 R08: 0000000000000006 R09: 0000000000000008
R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000004
R13: ffffc90003921000 R14: 0000000000000000 R15: ffffc900039215a0
FS: 000055558378f500(0000) GS:ffff8880d6713000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000000 CR3: 0000000025de6000 CR4: 0000000000352ef0
Call Trace:
<TASK>
apf_pageready_slot_free arch/x86/kvm/x86.c:13452 [inline]
kvm_arch_can_dequeue_async_page_present+0x172/0x310 arch/x86/kvm/x86.c:13571
kvm_check_async_pf_completion+0x61/0x440 virt/kvm/async_pf.c:158
vcpu_enter_guest arch/x86/kvm/x86.c:10930 [inline]
vcpu_run+0x48c2/0x5500 arch/x86/kvm/x86.c:11335
kvm_arch_vcpu_ioctl_run+0x51e/0x18c0 arch/x86/kvm/x86.c:11658
kvm_vcpu_ioctl+0x5eb/0x1690 virt/kvm/kvm_main.c:4464
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:907 [inline]
__se_sys_ioctl fs/ioctl.c:893 [inline]
__x64_sys_ioctl+0x18e/0x210 fs/ioctl.c:893
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fdb7658e929
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd25fe7d98 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fdb767b5fa0 RCX: 00007fdb7658e929
RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000005
RBP: 00007fdb76610b39 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fdb767b5fa0 R14: 00007fdb767b5fa0 R15: 0000000000000003
</TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

Sean Christopherson

unread,
Jul 16, 2025, 11:23:13 AM7/16/25
to syzbot, k...@vger.kernel.org, linux-...@vger.kernel.org, pbon...@redhat.com, syzkall...@googlegroups.com
kvm_pv_enable_async_pf() sets vcpu->arch.apf.msr_en_val even if the gpa is bad,
which leaves the cache in an empty state. Something like so over a few patches
fixes the problem:

---
arch/x86/kvm/x86.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index a1c49bc681c4..0fbbf297b3c8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3547,11 +3547,16 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
return 0;
}

-static inline bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
+static bool __kvm_pv_async_pf_enabled(u64 msr_en_val)
{
u64 mask = KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT;

- return (vcpu->arch.apf.msr_en_val & mask) == mask;
+ return (msr_en_val & mask) == mask;
+}
+
+static inline bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
+{
+ return __kvm_pv_async_pf_enabled(vcpu->arch.apf.msr_en_val);
}

static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
@@ -3573,22 +3578,21 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
if (!lapic_in_kernel(vcpu))
return data ? 1 : 0;

+ if (__kvm_pv_async_pf_enabled(data) &&
+ kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
+ sizeof(u64)))
+ return 1;
+
vcpu->arch.apf.msr_en_val = data;
-
- if (!kvm_pv_async_pf_enabled(vcpu)) {
- kvm_clear_async_pf_completion_queue(vcpu);
- kvm_async_pf_hash_reset(vcpu);
- return 0;
- }
-
- if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
- sizeof(u64)))
- return 1;
-
vcpu->arch.apf.send_always = (data & KVM_ASYNC_PF_SEND_ALWAYS);
vcpu->arch.apf.delivery_as_pf_vmexit = data & KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;

- kvm_async_pf_wakeup_all(vcpu);
+ if (kvm_pv_async_pf_enabled(vcpu)) {
+ kvm_clear_async_pf_completion_queue(vcpu);
+ kvm_async_pf_hash_reset(vcpu);
+ } else {
+ kvm_async_pf_wakeup_all(vcpu);
+ }

return 0;
}

base-commit: 2a046f6a4ecce47ada50dba529ec726dd0d34351
--

Alexander Potapenko

unread,
Feb 10, 2026, 4:22:30 AMFeb 10
to Sean Christopherson, syzbot, k...@vger.kernel.org, linux-...@vger.kernel.org, pbon...@redhat.com, syzkall...@googlegroups.com
This bug is still occasionally reproducible on an Intel host running 6.19.

Sean Christopherson

unread,
Feb 25, 2026, 8:47:46 PMFeb 25
to Alexander Potapenko, syzbot, k...@vger.kernel.org, linux-...@vger.kernel.org, pbon...@redhat.com, syzkall...@googlegroups.com
Gah, I never actually posted a series to fix this. I'll try to get that done
this week.

Xiaoyao Li

unread,
4:45 AM (10 hours ago) 4:45 AM
to Ethan Yang, k...@vger.kernel.org, sea...@google.com, pbon...@redhat.com, syzbot+bc0e18...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, x...@kernel.org, tg...@kernel.org, mi...@redhat.com, b...@alien8.de, dave....@linux.intel.com, h...@zytor.com, gli...@google.com
On 4/3/2026 11:11 AM, Ethan Yang wrote:
> kvm_pv_enable_async_pf() updates vcpu->arch.apf.msr_en_val before
> initializing the APF data gfn_to_hva cache. If userspace provides an
> invalid GPA, kvm_gfn_to_hva_cache_init() fails, but msr_en_val stays
> enabled and leaves APF state half-initialized.
>
> Later APF paths can then try to use the empty cache and trigger
> WARN_ON() in kvm_read_guest_offset_cached().
>
> Determine the new APF enabled state from the incoming MSR value, do cache
> initialization first on the enable path, and commit msr_en_val only after
> successful initialization. Keep the disable path behavior unchanged.
>
> Reported-by: syzbot+bc0e18...@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=bc0e18379a290e5edfe4
> Link: https://lore.kernel.org/r/aHfD3Mcz...@google.com
> Suggested-by: Sean Christopherson <sea...@google.com>
> Signed-off-by: Ethan Yang <ethan.ya...@gmail.com>

Reviewed-by: Xiaoyao Li <xiaoy...@intel.com>

though some nits below.

> ---
> arch/x86/kvm/x86.c | 19 +++++++++++++------
> 1 file changed, 13 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index fd1c4a36b59..c355bbd36c3 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1041,11 +1041,15 @@ bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr)
> }
> EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_require_dr);
>
> -static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
> +static bool kvm_pv_async_pf_enabled_data(u64 data)

I'm not sure if the name with "__" as __kvm_pv_async_pf_enabled() fits
better?

> {
> u64 mask = KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT;
> + return (data & mask) == mask;
> +}
>
> - return (vcpu->arch.apf.msr_en_val & mask) == mask;
> +static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
> +{
> + return kvm_pv_async_pf_enabled_data(vcpu->arch.apf.msr_en_val);
> }
>
> static inline u64 pdptr_rsvd_bits(struct kvm_vcpu *vcpu)
> @@ -3645,17 +3649,20 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
> if (!lapic_in_kernel(vcpu))
> return data ? 1 : 0;
>
> + bool new_enabled = kvm_pv_async_pf_enabled_data(data);

I would like just call it "enable"

> +
> + if (new_enabled &&
> + kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,

Please align the second line

> + sizeof(u64)))
> + return 1;
> vcpu->arch.apf.msr_en_val = data;
>
> - if (!kvm_pv_async_pf_enabled(vcpu)) {
> + if (!new_enabled) {
> kvm_clear_async_pf_completion_queue(vcpu);
> kvm_async_pf_hash_reset(vcpu);
> return 0;
> }
>
> - if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
> - sizeof(u64)))
> - return 1;
>

Ethan Yang

unread,
4:45 AM (10 hours ago) 4:45 AM
to k...@vger.kernel.org, sea...@google.com, pbon...@redhat.com, syzbot+bc0e18...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, x...@kernel.org, tg...@kernel.org, mi...@redhat.com, b...@alien8.de, dave....@linux.intel.com, h...@zytor.com, gli...@google.com
kvm_pv_enable_async_pf() updates vcpu->arch.apf.msr_en_val before
initializing the APF data gfn_to_hva cache. If userspace provides an
invalid GPA, kvm_gfn_to_hva_cache_init() fails, but msr_en_val stays
enabled and leaves APF state half-initialized.

Later APF paths can then try to use the empty cache and trigger
WARN_ON() in kvm_read_guest_offset_cached().

Determine the new APF enabled state from the incoming MSR value, do cache
initialization first on the enable path, and commit msr_en_val only after
successful initialization. Keep the disable path behavior unchanged.

Reported-by: syzbot+bc0e18...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=bc0e18379a290e5edfe4
Link: https://lore.kernel.org/r/aHfD3Mcz...@google.com
Suggested-by: Sean Christopherson <sea...@google.com>
Signed-off-by: Ethan Yang <ethan.ya...@gmail.com>
---
arch/x86/kvm/x86.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index fd1c4a36b59..c355bbd36c3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1041,11 +1041,15 @@ bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_require_dr);

-static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
+static bool kvm_pv_async_pf_enabled_data(u64 data)
{
u64 mask = KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT;
+ return (data & mask) == mask;
+}

- return (vcpu->arch.apf.msr_en_val & mask) == mask;
+static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
+{
+ return kvm_pv_async_pf_enabled_data(vcpu->arch.apf.msr_en_val);
}

static inline u64 pdptr_rsvd_bits(struct kvm_vcpu *vcpu)
@@ -3645,17 +3649,20 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
if (!lapic_in_kernel(vcpu))
return data ? 1 : 0;

+ bool new_enabled = kvm_pv_async_pf_enabled_data(data);
+
+ if (new_enabled &&
+ kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
+ sizeof(u64)))
+ return 1;
vcpu->arch.apf.msr_en_val = data;

- if (!kvm_pv_async_pf_enabled(vcpu)) {
+ if (!new_enabled) {
kvm_clear_async_pf_completion_queue(vcpu);
kvm_async_pf_hash_reset(vcpu);
return 0;
}

- if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
- sizeof(u64)))
- return 1;

vcpu->arch.apf.send_always = (data & KVM_ASYNC_PF_SEND_ALWAYS);
vcpu->arch.apf.delivery_as_pf_vmexit = data & KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT;
--
2.47.3

Ethan Yang

unread,
6:01 AM (9 hours ago) 6:01 AM
to k...@vger.kernel.org, xiaoy...@intel.com, sea...@google.com, pbon...@redhat.com, syzbot+bc0e18...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, syzkall...@googlegroups.com, x...@kernel.org, tg...@kernel.org, mi...@redhat.com, b...@alien8.de, dave....@linux.intel.com, h...@zytor.com, gli...@google.com
kvm_pv_enable_async_pf() updates vcpu->arch.apf.msr_en_val before
initializing the APF data gfn_to_hva cache. If userspace provides an
invalid GPA, kvm_gfn_to_hva_cache_init() fails, but msr_en_val stays
enabled and leaves APF state half-initialized.

Later APF paths can then try to use the empty cache and trigger
WARN_ON() in kvm_read_guest_offset_cached().

Determine the new APF enabled state from the incoming MSR value, do cache
initialization first on the enable path, and commit msr_en_val only after
successful initialization. Keep the disable path behavior unchanged.

Reported-by: syzbot+bc0e18...@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=bc0e18379a290e5edfe4
Link: https://lore.kernel.org/r/aHfD3Mcz...@google.com
Suggested-by: Sean Christopherson <sea...@google.com>
Reviewed-by: Xiaoyao Li <xiaoy...@intel.com>
Signed-off-by: Ethan Yang <ethan.ya...@gmail.com>
---
v2:
- Rename helper to __kvm_pv_async_pf_enabled()
- Rename new_enabled to enable
- Align wrapped line in kvm_gfn_to_hva_cache_init() call
---
arch/x86/kvm/x86.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 63afdb6bb07..93b7ad9b52b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1035,11 +1035,16 @@ bool kvm_require_dr(struct kvm_vcpu *vcpu, int dr)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_require_dr);

-static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
+static bool __kvm_pv_async_pf_enabled(u64 data)
{
u64 mask = KVM_ASYNC_PF_ENABLED | KVM_ASYNC_PF_DELIVERY_AS_INT;

- return (vcpu->arch.apf.msr_en_val & mask) == mask;
+ return (data & mask) == mask;
+}
+
+static bool kvm_pv_async_pf_enabled(struct kvm_vcpu *vcpu)
+{
+ return __kvm_pv_async_pf_enabled(vcpu->arch.apf.msr_en_val);
}

static inline u64 pdptr_rsvd_bits(struct kvm_vcpu *vcpu)
@@ -3616,6 +3621,7 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
{
gpa_t gpa = data & ~0x3f;
+ bool enable;

/* Bits 4:5 are reserved, Should be zero */
if (data & 0x30)
@@ -3632,18 +3638,20 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
if (!lapic_in_kernel(vcpu))
return data ? 1 : 0;

+ enable = __kvm_pv_async_pf_enabled(data);
+
+ if (enable &&
+ kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
+ sizeof(u64)))
+ return 1;
vcpu->arch.apf.msr_en_val = data;

- if (!kvm_pv_async_pf_enabled(vcpu)) {
+ if (!enable) {
kvm_clear_async_pf_completion_queue(vcpu);
kvm_async_pf_hash_reset(vcpu);
return 0;
}

- if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
- sizeof(u64)))
- return 1;
-
Reply all
Reply to author
Forward
0 new messages