Skip to content

Commit d67a537

Browse files
pmladekJiri Kosina
authored andcommitted
livepatch: Remove ordering (stacking) of the livepatches
The atomic replace and cumulative patches were introduced as a more secure way to handle dependent patches. They simplify the logic: + Any new cumulative patch is supposed to take over shadow variables and changes made by callbacks from previous livepatches. + All replaced patches are discarded and the modules can be unloaded. As a result, there is only one scenario when a cumulative livepatch gets disabled. The different handling of "normal" and cumulative patches might cause confusion. It would make sense to keep only one mode. On the other hand, it would be rude to enforce using the cumulative livepatches even for trivial and independent (hot) fixes. However, the stack of patches is not really necessary any longer. The patch ordering was never clearly visible via the sysfs interface. Also the "normal" patches need a lot of caution anyway. Note that the list of enabled patches is still necessary but the ordering is not longer enforced. Otherwise, the code is ready to disable livepatches in an random order. Namely, klp_check_stack_func() always looks for the function from the livepatch that is being disabled. klp_func structures are just removed from the related func_stack. Finally, the ftrace handlers is removed only when the func_stack becomes empty. Signed-off-by: Petr Mladek <[email protected]> Acked-by: Miroslav Benes <[email protected]> Acked-by: Josh Poimboeuf <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent c4e6874 commit d67a537

File tree

3 files changed

+11
-17
lines changed

3 files changed

+11
-17
lines changed

Documentation/livepatch/cumulative-patches.txt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ to do different changes to the same function(s) then we need to define
77
an order in which the patches will be installed. And function implementations
88
from any newer livepatch must be done on top of the older ones.
99

10-
This might become a maintenance nightmare. Especially if anyone would want
11-
to remove a patch that is in the middle of the stack.
10+
This might become a maintenance nightmare. Especially when more patches
11+
modified the same function in different ways.
1212

1313
An elegant solution comes with the feature called "Atomic Replace". It allows
1414
creation of so called "Cumulative Patches". They include all wanted changes
@@ -26,11 +26,9 @@ for example:
2626
.replace = true,
2727
};
2828

29-
Such a patch is added on top of the livepatch stack when enabled.
30-
3129
All processes are then migrated to use the code only from the new patch.
3230
Once the transition is finished, all older patches are automatically
33-
disabled and removed from the stack of patches.
31+
disabled.
3432

3533
Ftrace handlers are transparently removed from functions that are no
3634
longer modified by the new cumulative patch.
@@ -57,8 +55,7 @@ The atomic replace allows:
5755
+ Remove eventual performance impact caused by core redirection
5856
for functions that are no longer patched.
5957

60-
+ Decrease user confusion about stacking order and what code
61-
is actually in use.
58+
+ Decrease user confusion about dependencies between livepatches.
6259

6360

6461
Limitations:

Documentation/livepatch/livepatch.txt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ without HAVE_RELIABLE_STACKTRACE are not considered fully supported by
143143
the kernel livepatching.
144144

145145
The /sys/kernel/livepatch/<patch>/transition file shows whether a patch
146-
is in transition. Only a single patch (the topmost patch on the stack)
147-
can be in transition at a given time. A patch can remain in transition
148-
indefinitely, if any of the tasks are stuck in the initial patch state.
146+
is in transition. Only a single patch can be in transition at a given
147+
time. A patch can remain in transition indefinitely, if any of the tasks
148+
are stuck in the initial patch state.
149149

150150
A transition can be reversed and effectively canceled by writing the
151151
opposite value to the /sys/kernel/livepatch/<patch>/enabled file while
@@ -351,6 +351,10 @@ to '0'.
351351
The right implementation is selected by the ftrace handler, see
352352
the "Consistency model" section.
353353

354+
That said, it is highly recommended to use cumulative livepatches
355+
because they help keeping the consistency of all changes. In this case,
356+
functions might be patched two times only during the transition period.
357+
354358

355359
5.3. Replacing
356360
--------------
@@ -389,9 +393,6 @@ becomes empty.
389393

390394
Third, the sysfs interface is destroyed.
391395

392-
Note that patches must be disabled in exactly the reverse order in which
393-
they were enabled. It makes the problem and the implementation much easier.
394-
395396

396397
5.5. Removing
397398
-------------

kernel/livepatch/core.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,10 +925,6 @@ static int __klp_disable_patch(struct klp_patch *patch)
925925
if (klp_transition_patch)
926926
return -EBUSY;
927927

928-
/* enforce stacking: only the last enabled patch can be disabled */
929-
if (!list_is_last(&patch->list, &klp_patches))
930-
return -EBUSY;
931-
932928
klp_init_transition(patch, KLP_UNPATCHED);
933929

934930
klp_for_each_object(patch, obj)

0 commit comments

Comments
 (0)