All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Zhangjiaji <zhangjiaji1@huawei.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	"kvm@vger.kernel.org" <kvm@vger.kernel.org>,
	 "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"Wangqinxiao (Tom)" <wangqinxiao@huawei.com>,
	 zhangyashu <zhangyashu2@h-partners.com>,
	"wangyanan (Y)" <wangyanan55@huawei.com>
Subject: Re: [BUG REPORT] USE_AFTER_FREE in complete_emulated_mmio found by KASAN/Syzkaller fuzz test (v5.10.0)
Date: Fri, 6 Feb 2026 15:30:35 -0800	[thread overview]
Message-ID: <aYZ5m5iJ_h_2wqw_@google.com> (raw)
In-Reply-To: <369eaaa2b3c1425c85e8477066391bc7@huawei.com>

On Mon, Feb 02, 2026, Zhangjiaji wrote:
> Syzkaller hit 'KASAN: use-after-free Read in complete_emulated_mmio' bug.
> 
> ==================================================================
> BUG: KASAN: use-after-free in complete_emulated_mmio+0x305/0x420
> Read of size 1 at addr ffff888009c378d1 by task syz-executor417/984
> 
> CPU: 1 PID: 984 Comm: syz-executor417 Not tainted 5.10.0-182.0.0.95.h2627.eulerosv2r13.x86_64 #3 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 Call Trace:
> dump_stack+0xbe/0xfd
> print_address_description.constprop.0+0x19/0x170
> __kasan_report.cold+0x6c/0x84
> kasan_report+0x3a/0x50
> check_memory_region+0xfd/0x1f0
> memcpy+0x20/0x60
> complete_emulated_mmio+0x305/0x420
> kvm_arch_vcpu_ioctl_run+0x63f/0x6d0
> kvm_vcpu_ioctl+0x413/0xb20
> __se_sys_ioctl+0x111/0x160
> do_syscall_64+0x30/0x40
> entry_SYSCALL_64_after_hwframe+0x67/0xd1
> RIP: 0033:0x42477d
> Code: 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 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 b0 ff ff ff f7 d8 64 89 01 48
> RSP: 002b:00007faa8e6890e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
> RAX: ffffffffffffffda RBX: 00000000004d7338 RCX: 000000000042477d
> RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000005
> RBP: 00000000004d7330 R08: 00007fff28d546df R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000246 R12: 00000000004d733c
> R13: 0000000000000000 R14: 000000000040a200 R15: 00007fff28d54720
> 
> The buggy address belongs to the page:
> page:0000000029f6a428 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x9c37
> flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff)
> raw: 000fffffc0000000 0000000000000000 ffffea0000270dc8 0000000000000000
> raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kasan: bad access detected
> 
> Memory state around the buggy address:
> ffff888009c37780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> ffff888009c37800: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> >ffff888009c37880: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>                                                  ^
> ffff888009c37900: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> ffff888009c37980: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ==================================================================
> 
> 
> Syzkaller reproducer:
> # {Threaded:true Repeat:true RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: SandboxArg:0 Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:true Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
> r0 = openat$kvm(0xffffffffffffff9c, &(0x7f00000001c0), 0x0, 0x0)
> r1 = ioctl$KVM_CREATE_VM(r0, 0xae01, 0x0)
> r2 = ioctl$KVM_CREATE_VCPU(r1, 0xae41, 0x0) syz_kvm_setup_cpu$x86(r1, r2, &(0x7f0000fe2000/0x18000)=nil, &(0x7f0000000080)=[@text32={0x20, &(0x7f0000000000)="44c8df2020c020c003000000000f22c0671e26653e360f2224660f65b600000000b9e0450200f5e8f5e8f30f1ed6c744240000100000c744240200000000c7442406000000000f011424eacf5700000301b8010000000f01c1", 0x59}], 0x1, 0x27, 0x0, 0x1) ioctl$KVM_RUN(r2, 0xae80, 0x0) ioctl$KVM_SMI(0xffffffffffffffff, 0xaeb7) (async) ioctl$KVM_RUN(r2, 0xae80, 0x0)
> 
> 
> ----------------------------
> Hi,
> 
> I've analyzed the Syzkaller output and the complete_emulated_mmio() code
> path.  The buggy address is created in em_enter(), where it passes its local
> variable `ulong rbp` to emulate_push(), finally ends in
> emulator_read_write_onepage() putting the address into
> vcpu->mmio_fragments[].data .  The bug happens when kvm guest executes an
> "enter" instruction, and top of the stack crosses the mem page.  In that
> case, the em_enter() function cannot complete the instruction within itself,
> but leave the rest data (which is in the other page) to
> complete_emulated_mmio().  When complete_emulated_mmio() starts, em_enter()
> has exited, so local variable `ulong rbp` is also released.  Now
> complete_emulated_mmio() trys to access vcpu->mmio_fragments[].data , and the
> bug happened.
> 
> any idea?

Egad, sorry!  I had reproduced this shortly after you sent the report and prepped
a fix, but got distracted and lost this in my inbox.

Can you test this on your end?  I repro'd by modifying a KVM-Unit-Test and hacking
KVM to tweak the stack, so I haven't confirmed the syzkaller version.

It's a bit gross, as it abuses an unused field as scratch space, but AFAICT that's
"fine".  The alternative would be add a dedicated field, which seems like overkill?

I'm also going to try and add a WARN to detect if the @val parameter passed to
emulator_read_write() is ever on the kernel stack, e.g. to help detect lurking
bugs like this one without relying on kasahn.

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index c8e292e9a24d..dacef51c2565 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1897,13 +1897,12 @@ static int em_enter(struct x86_emulate_ctxt *ctxt)
        int rc;
        unsigned frame_size = ctxt->src.val;
        unsigned nesting_level = ctxt->src2.val & 31;
-       ulong rbp;
 
        if (nesting_level)
                return X86EMUL_UNHANDLEABLE;
 
-       rbp = reg_read(ctxt, VCPU_REGS_RBP);
-       rc = emulate_push(ctxt, &rbp, stack_size(ctxt));
+       ctxt->memop.orig_val = reg_read(ctxt, VCPU_REGS_RBP);
+       rc = emulate_push(ctxt, &ctxt->memop.orig_val, stack_size(ctxt));
        if (rc != X86EMUL_CONTINUE)
                return rc;
        assign_masked(reg_rmw(ctxt, VCPU_REGS_RBP), reg_read(ctxt, VCPU_REGS_RSP),

  reply	other threads:[~2026-02-06 23:30 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-02  1:24 [BUG REPORT] USE_AFTER_FREE in complete_emulated_mmio found by KASAN/Syzkaller fuzz test (v5.10.0) Zhangjiaji
2026-02-06 23:30 ` Sean Christopherson [this message]
2026-02-09 20:21   ` Sean Christopherson
2026-02-10  6:26 ` Paolo Bonzini
2026-02-10 14:35   ` Sean Christopherson
2026-02-10 17:41     ` Paolo Bonzini
  -- strict thread matches above, loose matches on Subject: below --
2026-02-10 11:56 Zhangjiaji
2026-02-10 19:11 ` Sean Christopherson
2026-02-18 20:56   ` Sean Christopherson
2026-05-08  7:57     ` Xinyu Zheng
2026-05-08 14:25       ` Sean Christopherson
2026-05-09  1:55         ` Xinyu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aYZ5m5iJ_h_2wqw_@google.com \
    --to=seanjc@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=wangqinxiao@huawei.com \
    --cc=wangyanan55@huawei.com \
    --cc=zhangjiaji1@huawei.com \
    --cc=zhangyashu2@h-partners.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.