Re: [PATCH v3 3/7] livepatch: Support scoped atomic replace using replace_set
Yafang Shao <[email protected]> Tue, 16 Jun 2026 10:41:54 +0800
| Newsgroups | org.kernel.vger.live-patching |
|---|---|
| Message-ID | <CALOAHbADBDr15_i=S5CzJc5XCQ+hSA0fdLcCVXXjdjvKLZUNpA@mail.gmail.com> |
On Mon, Jun 15, 2026 at 8:30 PM Yafang Shao <[email protected]> wrote: > > On Thu, Jun 11, 2026 at 8:58 PM Petr Mladek <[email protected]> wrote: > > > > On Tue 2026-06-09 18:00:55, Petr Mladek wrote: > > > On Sun 2026-06-07 21:16:55, Yafang Shao wrote: > > > I would write something like: > > > > > > <proposal> > > > The practice shows that the current semantic of the patch.replace flag is > > > not ideal. > > > > > > The atomic replace is disabled by default. And the no-replace mode allows > > > wild installation of many livepatches in parallel. The author and > > > administrator are fully responsible for preventing problems caused > > > by producing and installing incompatible livepatches. > > > > > > The most safe atomic replace mode must be explicitly enabled by > > > setting "patch.replace = true". It is all or nothing. The livepatch > > > with enabled .replace will always replace all already installed > > > livepatches. It makes it very safe but it might be too harsh. > > > > > > Improve the situation by switching "bool .replace" flag to > > > "u32 .replace_set" and and updating its semantic. > > > > > > Any .replace_set value might be associated with a set of livepatched > > > symbols, callbacks, shadow variable and state IDs. > > > > > > A livepatch with a particular .replace_set number will atomically > > > rreplace any already installed livepatch with the same .replace_set > > > number. By definition, there can only ever be one active livepatch > > > for a given replace_set number. > > > > > > On the contrary, livepatches with a different .replace_set number > > > must not modify the same function, or use the state with the same > > > ID [*]. Any attempt to load an incompatible livepatch will be > > > rejected. > > > > > > Summary: > > > > > > The most safe mode when any livepatch replaces any other livepatch > > > will be the default. Note that all livepatches must keep > > > .replace_set = 0. > > > > > > It will be possible to install more livepatches in parallel by > > > using different .replace_set numbers. The livepatches might be > > > updated independently using the atomic replace feature as long > > > as the new version does not break compatibility. The kernel will > > > reject a livepatch from a different replace set when it would > > > want to modify the same function or livepatch state from > > > another replace set. > > > > > > [*] The compatibility check of callbacks and shadow variables will > > > be improved later by reworking their semantic. There is a work > > > in progress, see [0] > > > </proposal> > > > > > > > Link: https://github.com/pmladek/linux/tree/klp-state-transfer-v1-iter12 [0] > > > > > > I have realized that I actually sent "v1-iter12" to the public > > > mailing list as the official v1. So we could use: > > > > > > Link: https://lore.kernel.org/all/[email protected]/ [0] > > > > > > > > > New idea: > > > > > > I have briefly discussed the new semantic with Miroslav when I met > > > him in person. And he was a bit concerned. We as an OS distributor > > > might want to be sure that our livepatches can be installed the most > > > safe way. So, we still might want to preserve the "replace all" > > > semantic to make sure that our livepatches will not break anything. > > > > I thought more about it and we would need some solution to preserve > > the replace_all functionality. > > > > There were recently reported few serious 0-day vulnerabilities. > > We discussed a possibility to ship a quick fix with a livepatch. > > Or that customers might want to fix it themself by a livepatch. > > Such a livepatch would need to be installed in parallel to > > the official livepatch fixing older bugs. But the next official > > cumulative livepatch would need to replace it. > > > > The above scenario will not longer work with the current > > "replace_set" handling. The hotfix would need to use another > > "replace_set" so that it can be installed in parallel. > > But the next cumulative livepatch won't be able to replace > > it because it would need to modify the same function. > > > > I consulted this with AI (claude-sonet-4.6) and it gave the following > > feedback/ideas ;-) > > > > > I though about 4 approaches approaches: > > > > > > 1. Make .replace_set=0 special so that it will always replace > > > everything. Similar to the current .replace=true mode. > > > > > > Customers will still be able to install custom livepatches > > > later with .replace_set != 0. But the "0" livepatch will > > > always wipe them out. > > > > This is not ideal because it is asymetric. Why is "0" special? > > > > > > > 2. Use two flags in the livepatch, for example > > > > > > a. Rename .replace to .replace_all. The livepatch with this > > > flag set will always wipe all other livepatches. > > > > > > b. Add .replace_set which will allow to install more livepatches > > > in parallel, replace the livepatches with the same .replace_set > > > atomically, and check the compatibility. As described above. > > > > > > It is a bit more complicated. But it is more compatible with > > > the current state. And it removes the special meaning of > > > .replace_set == 0. > > > > This looks more straightforward. But the fact that "replace_all" > > replaces everything brings back the problem with the original > > "replace" flag. So, it makes this whole exercise more or less > > pointless. > > > > I had another idea with storing list of fixed bugs/CVEs in each > > livepatch. Independent fixes might be fixed by independent > > livepatches. Then a cumulative livepatch would replace only > > the livepatches which fixed the same bugs before. > > > > And (claude-sonnet-4.6) came with an interesting simplification. > > > > We could add: > > > > struct klp_patch { > > [...] > > unsigned int replace_set; > > const unsigned int *supersedes; /* Zero terminated array of replace_set IDs */ > > [...] > > } After further consideration, what about merging replace_set and supersedes into a single field? For example: struct klp_patch { [...] unsigned int *replace_set; [...] }; This replace_set field can be set at build time and also dynamically updated at load time. By default, it contains a single ID, 0. To replace a livepatch with ID 1, we can set it to 1 at load time. To replace livepatches with both ID 1 and ID 2, we can set it to [1, 2]. In other words, a livepatch with replace_set [1, 2] can replace livepatches with IDs 1, 2, or [1, 2]. A livepatch with replace_set [1, 2, 3] can replace livepatches with IDs 1, 2, 3, [1, 2], [1, 3], [2, 3], or [1, 2, 3]. I believe this approach is well-suited to complex production deployment environments. [...] -- Regards Yafang