Skip to content

Commit

Permalink
livepatch: Remove ordering (stacking) of the livepatches
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
pmladek authored and Jiri Kosina committed Jan 11, 2019
1 parent c4e6874 commit d67a537
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 17 deletions.
11 changes: 4 additions & 7 deletions Documentation/livepatch/cumulative-patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ to do different changes to the same function(s) then we need to define
an order in which the patches will be installed. And function implementations
from any newer livepatch must be done on top of the older ones.

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

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

Such a patch is added on top of the livepatch stack when enabled.

All processes are then migrated to use the code only from the new patch.
Once the transition is finished, all older patches are automatically
disabled and removed from the stack of patches.
disabled.

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

+ Decrease user confusion about stacking order and what code
is actually in use.
+ Decrease user confusion about dependencies between livepatches.


Limitations:
Expand Down
13 changes: 7 additions & 6 deletions Documentation/livepatch/livepatch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ without HAVE_RELIABLE_STACKTRACE are not considered fully supported by
the kernel livepatching.

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

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

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


5.3. Replacing
--------------
Expand Down Expand Up @@ -389,9 +393,6 @@ becomes empty.

Third, the sysfs interface is destroyed.

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


5.5. Removing
-------------
Expand Down
4 changes: 0 additions & 4 deletions kernel/livepatch/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,10 +925,6 @@ static int __klp_disable_patch(struct klp_patch *patch)
if (klp_transition_patch)
return -EBUSY;

/* enforce stacking: only the last enabled patch can be disabled */
if (!list_is_last(&patch->list, &klp_patches))
return -EBUSY;

klp_init_transition(patch, KLP_UNPATCHED);

klp_for_each_object(patch, obj)
Expand Down

0 comments on commit d67a537

Please sign in to comment.