Re: [RFC PATCH 0/3] liveupdate: Move to feature flags for LUO and memfd ABI compatibility
From: Paolo Bonzini
Date: Fri Sep 11 2026 - 13:14:25 EST
On 9/10/26 17:35, Sean Christopherson wrote:
On Thu, Sep 10, 2026, Jason Gunthorpe wrote:I strongly agree with Sean on this, like really really agree.
Sometimes you can do more and more work to try and be more and more
general but this is *alot* of work and even then eventually hits
problematic limits. Like what do you do with the sealing flags? That's
ABI breaking if the successor does not support them, and downgrades
make exactly that possible.
A CSPish user can do things like patch the new sealing flag into their
current kernel (while preventing userspace from using it), ensure
everything is updated to that, then jump ahead to a newer kernel and
enjoy the new flag with full downgrade support. There is so much more
control on their part that makes the problem far more managably simple
that upstream does not get to have.
I guess maybe we have a different definition of ABI? I'm not saying
that upstream has to be 100% forwards and backwards compatible. I'm
saying the serialization payload itself should communicate what
features are effectively required.
All you need is serializing *actions*. Make the destination a small interpreter not something that read structs. memfd/guest_memfd is already created by a bunch of actions, which are syscalls, so it shouldn't be hard to either come up with the actions or parse them in the destination.
An example matching (going by memory) what is now in place for memfd:
- memfd_create(name[], flags)
- memfd_map(folios[], index)
- memfd_finish(seals, pos, size, mode)
So:
#define MEMFD_LUO_CREATE 0
#define MEMFD_LUO_MAP 1
#define MEMFD_LUO_FINISH 2
struct memfd_luo_op {
/* 0 = end */
u32 size;
u32 op;
union {
struct {
u32 flags;
char name[];
} memfd_luo_create;
struct {
u32 flags;
} memfd_luo_secret;
struct {
u64 i_size;
u64 f_pos;
u32 f_seals;
u32 i_mode;
} memfd_luo_finish;
struct {
u64 index;
struct memfd_luo_folio src_folios[]; // whatever
} memfd_luo_map;
};
} __aligned(8);
You write almost everything at prepare, just ensure there is room for finish and write that on freeze.
Want to move secret memfds? Sure they're different in underlying implementation but they can share LUO serialization format almost entirely. Make it a new op instead of create.. you have 4 billion possible ops, adding them isn't quite free but not too expensive either.
In fact memfd is the easy case, almost always you'll have a more complicated initialization sequence and a huge explosion of possibilities, but the good thing is that the kernel *already* has to initialize its data structures from actions. We're not quite serializing syscalls but pretty close, in fact for KVM a lot of code could be shared between ioctls and LUO receiving side.
It doesn't have to match exactly userspace, for example you wouldn't really need to transmit MFD_ALLOW_SEALING because it's implicit in the seals you transmit. That said, taking inspiration doesn't hurt; just remember to *always* validate unknown flags.
If it really succeeds at that and it becomes very popular, then let's
discuss upstreaming doing additional version combinations.
Why on earth would we have version numbers in the first place? IMO, monotically
increasing version numbers are flat out the worst way to communicate features.
This, too. KVM has been at API version 12 since 2007. It is not userspace compatible with 2007 vintage QEMU, because a couple misfeatures were removed after 10 years or so of waiting, so I guess technically it would be 15 or 16, but it doesn't matter because no one checks KVM_API_VERSION. If a ioctl works it works, if it doesn't you get a much better message than "KVM API version mismatch".
Okay, how about worse, todays kernel has hugetlbfs and there are
patches around to luo serialize that. Lots and lots of talks about a
post-hugetlbfs world out there.
And? Adding a compatibility layer to a future kernel so that it understands an
incoming HugeTLBFS payload should be trivial. I can totally see not wanting to
support serializing a post-HugeTBLFS kernel's memory representation into the "old"
format, though even that probably wouldn't be all that difficult.
Yeah, hugetlbfs is an implementation detail *of the destination* not the source. The destination somehow needs to take the 1GB area and donate it to hugetlbfs. That's not the source's problem. All the source->destination ABI contains is MFD_HUGETLB and MFD_HUGE_*, which promise to the destination a certain alignment of all map requests.
Do we want to reject the hugetlbfs serialization until we have a year
of debate outlining every possible ABI scenario? I also vote no.
That's a bit of a strawman argument. Is designing a forward-looking ABI easy?
No, but it's also not *that* hard if you have a half-decent userspace ABI.
Hard NAK. There will inevitably be boundaries that cannot be crossed, but I am100%. And I'll add, what happened to "we don't break userspace"? This does the intentional opposite in the hope that no one cares about using this feature upstream. Which in the long term hurts downstream forks as much as upstream.
not at all ok punting on downgrades. To me, that's basically saying "we want to
add just enough support upstream so that it's not too painful to carry full support
out-of-tree". That completely goes against the spirit of open source and upstream
Linux, and I want no part of it.
Paolo