Re: [BUG REPORT] USE_AFTER_FREE in complete_emulated_mmio found by KASAN/Syzkaller fuzz test (v5.10.0)
From: Sean Christopherson
Date: Fri May 08 2026 - 10:25:17 EST
On Fri, May 08, 2026, Xinyu Zheng wrote:
> On 2/19/2026 4:56 AM, Sean Christopherson wrote:
> > On Tue, Feb 10, 2026, Sean Christopherson wrote:
> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > index 2c7d76262898..0bb2a34fb93d 100644
> > --- a/include/linux/kvm_host.h
> > +++ b/include/linux/kvm_host.h
> > @@ -320,7 +320,8 @@ static inline bool kvm_vcpu_can_poll(ktime_t cur, ktime_t stop)
> > struct kvm_mmio_fragment {
> > gpa_t gpa;
> > void *data;
> > - unsigned len;
> > + u64 val;
>
> Hi, Jiayi and Sean,
>
> Since I met a KABI consistence break problem from this change, I am finding
> a way to avoid add including kvm_mmio_fragment.val.
I assume you're looking for a solution for a private/proprietary kernel? I.e.
not trying to figure out a solution for an upstream LTS kernel?
> Can I try to directly malloc a 8 size buffer for kvm_mmio_fragment.data
> instead of using kvm_mmio_fragment.val, and free this buffer in
> complete_emulated_mmio when all fragments is been copied?
I highly doubt that will work, because you'd still need to stash the pointer
somewhere. And it pretty much would have to be somewhere in kvm_vcpu, which
would likely mean a change in KABI. FWIW, freeing the allocation in
complete_emulated_mmio() wouldn't suffice; you'd also need to free the memory
on vCPU destruction, because there's no guarantee userspace would complete
KVM_RUN.
You should be able to use the padding in the "kvm_run.s". Thanks to s390's
massive regs size, there's a huge amount of unused space in the union on x86.
Note, because there can be two fragments in-flight, you'd need to index the
array using the correct fragment number.
Userspace can scribble the value, but that's completely irrelevant from a host
safety perspective.
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 6c8afa2047bf..29c7123d5467 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -515,7 +515,10 @@ struct kvm_run {
__u64 kvm_valid_regs;
__u64 kvm_dirty_regs;
union {
- struct kvm_sync_regs regs;
+ struct {
+ struct kvm_sync_regs regs;
+ u64 x86_mmio_val[2];
+ };
char padding[SYNC_REGS_SIZE_BYTES];
} s;
};