Re: [PATCH] KVM: x86: Fix C++ user API for structures with variable length arrays
From: David Woodhouse
Date: Thu Mar 05 2026 - 14:21:23 EST
On Thu, 2026-03-05 at 10:36 -0800, Sean Christopherson wrote:
> On Thu, Feb 26, 2026, David Woodhouse wrote:
> > From: David Woodhouse <dwmw@xxxxxxxxxxxx>
> >
> > Commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with
> > flexible-array members") broke the userspace API for C++. Not just in
> > the sense of 'userspace needs to be updated, but UAPI is supposed to be
> > stable", but broken in the sense that I can't actually see *how* the
> > structures can be used from C++ in the same way that they were usable
> > before.
> >
> > These structures ending in VLAs are typically a *header*, which can be
> > followed by an arbitrary number of entries. Userspace typically creates
> > a larger structure with some non-zero number of entries, for example in
> > QEMU's kvm_arch_get_supported_msr_feature():
> >
> > struct {
> > struct kvm_msrs info;
> > struct kvm_msr_entry entries[1];
> > } msr_data = {};
> >
> > While that works in C, it fails in C++ with an error like:
> > flexible array member ‘kvm_msrs::entries’ not at end of ‘struct msr_data’
> >
> > Fix this by using __DECLARE_FLEX_ARRAY() for the VLA, which is a helper
> > provided by <linux/stddef.h> that already uses [0] for C++ compilation.
> >
> > Also put the header fields into a struct_group() to provide (in C) a
> > separate struct (e.g 'struct kvm_msrs_hdr') without the trailing VLA.
>
> Unless I'm missing something, this is an entirely optional change that needs to
> be done separately, especialy since I want to tag this for:
>
> Cc: stable@xxxxxxxxxxxxxxx
>
> I definitely don't hate the __struct_group definitions, but I don't know that I
> love them either as they make the code a bit harder to read, and more importantly
> there's a non-zero chance that defining the new structurs could break userspace
> builds and force an update, e.g. if userspace already concocts its own header
> overlay, which would be very unpleasant for a stable@ patch.
>
> If we do define headers, I think I'd want a wrapper around __struct_group() to
> prettify the common case and force consistent naming, e.g.
>
> #define kvm_struct_header(NAME, MEMBERS...) \
> __struct_group(NAME ##_header, h, /* no attrs */, MEMBERS)
>
> struct kvm_msrs {
> kvm_struct_header(kvm_msrs,
> __u32 nmsrs; /* number of msrs in entries */
> __u32 pad;
> );
>
> __DECLARE_FLEX_ARRAY(struct kvm_msr_entry, entries);
> };
>
> But that's likely going to lead to some amount of bikeshedding, e.g. arguably
> kvm_header() would be sufficient and easier on the eyes. Which is all the more
> reason to handle it separately.
>
> > Fixes: 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members")
> > Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
> > ---
> > arch/x86/include/uapi/asm/kvm.h | 29 ++++++++++++++++++-----------
> > include/uapi/linux/kvm.h | 9 ++++++---
> > /* for KVM_GET_PIT and KVM_SET_PIT */
> > @@ -397,8 +402,10 @@ struct kvm_xsave {
> > * The offsets of the state save areas in struct kvm_xsave follow
> > * the contents of CPUID leaf 0xD on the host.
> > */
> > - __u32 region[1024];
> > - __u32 extra[];
> > + __struct_group(kvm_xsave_hdr, hdr, /* no attrs */,
> > + __u32 region[1024];
> > + );
>
> This is *very* misleading, as XSTATE itself has a header, but this is something
> else entirely (just the always-allocated region).
>
> > + __DECLARE_FLEX_ARRAY(__u32, extra);
> > };
>
> There are several structs that got missed:
>
> kvm_pmu_event_filter
> kvm_reg_list
> kvm_signal_mask
> kvm_coalesced_mmio_ring
> kvm_cpuid
> kvm_stats_desc
Ack. Shall we do just the __DECLARE_FLEX_ARRAY() part, including those
missed structures?
Attachment:
smime.p7s
Description: S/MIME cryptographic signature