On Sun, Jun 07, 2026 at 09:16:55PM +0800, Yafang Shao wrote: > Convert the replace attribute from a boolean to a u32 to function as a > "replace set." A newly loaded livepatch will now atomically replace any > existing patch belonging to the same set. There can only ever be one active > livepatch for a given replace_set number. > > This change currently supports function replacement only. Livepatches that > belong to different replace sets cannot modify the same function. If a new > livepatch attempts to modify a function already modified by an older > livepatch from a different replace_set, the loading of the new livepatch > will be refused. > > Similarly, for the KLP state, livepatches belonging to different replace > sets cannot use the same state ID. The system will refuse to load a new > livepatch if it uses a state ID already in use by an older livepatch from > a different replace_set. > > For the KLP shadow variable mechanism, developers must assign unique shadow > IDs to livepatches that belong to different replace sets. > > Support for replace_set compatibility with KLP state and shadow variables > will be implemented after Petr's KLP state transfer work is completed [0]. > > Other user-visible changes include: > - The non-replace model is now deprecated > - /sys/kernel/livepatch/livepatch_XXX/replace attribute is replaced by > /sys/kernel/livepatch/livepatch_XXX/replace_set > > Link: https://github.com/pmladek/linux/tree/klp-state-transfer-v1-iter12 [0] > Suggested-by: Song Liu <[email protected]> > Suggested-by: Petr Mladek <[email protected]> > Signed-off-by: Yafang Shao <[email protected]> > --- > .../ABI/testing/sysfs-kernel-livepatch | 5 +- > .../livepatch/cumulative-patches.rst | 23 ++++++--- > Documentation/livepatch/livepatch.rst | 21 ++++---- > include/linux/livepatch.h | 5 +- > kernel/livepatch/core.c | 24 +++++---- > kernel/livepatch/state.c | 51 +++++++++++++++---- > kernel/livepatch/transition.c | 11 ++-- > scripts/livepatch/init.c | 6 +-- > scripts/livepatch/klp-build | 16 +++--- > 9 files changed, 104 insertions(+), 58 deletions(-) > > [ ... snip ... ] > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c > index 6e15ae96a0a7..361999e5ce3d 100644 > --- a/kernel/livepatch/core.c > +++ b/kernel/livepatch/core.c > [ ... snip ... ] > @@ -600,6 +600,8 @@ static int klp_add_nops(struct klp_patch *patch) > klp_for_each_object(old_patch, old_obj) { > int err; > > + if (patch->replace_set != old_patch->replace_set) > + continue; > err = klp_add_object_nops(patch, old_obj); > if (err) > return err; > @@ -772,6 +774,8 @@ void klp_free_replaced_patches_async(struct klp_patch > *new_patch) > klp_for_each_patch_safe(old_patch, tmp_patch) { > if (old_patch == new_patch) > return; > + if (old_patch->replace_set != new_patch->replace_set) > + continue; > klp_free_patch_async(old_patch); > } > } > @@ -967,11 +971,9 @@ static int klp_init_patch(struct klp_patch *patch) > if (ret) > return ret; > > - if (patch->replace) { > - ret = klp_add_nops(patch); > - if (ret) > - return ret; > - } > + ret = klp_add_nops(patch); > + if (ret) > + return ret;
The pre-existing comment above klp_add_nops() is now misleading: They are added only when the atomic replace mode is used and only for functions which are currently livepatched but are no longer included in the new livepatch. That function is now called unconditionally, and with this patchset, there is no more "replace mode" but "replace sets". How about something like: For each older patch in the same replace_set, any function that is currently livepatched, but no longer included in the new livepatch gets a nop entry, ensuring a clean transition back to the original code during atomic replacement. -- Joe
