Re: [RFC 3/5] livepatch: Allow to distinguish different version of system state changes

From: Nicolai Stange
Date: Mon Jun 24 2019 - 06:26:12 EST


Petr Mladek <pmladek@xxxxxxxx> writes:

> ---
> include/linux/livepatch.h | 2 ++
> kernel/livepatch/core.c | 8 ++++++++
> kernel/livepatch/state.c | 40 +++++++++++++++++++++++++++++++++++++++-
> kernel/livepatch/state.h | 9 +++++++++
> 4 files changed, 58 insertions(+), 1 deletion(-)
> create mode 100644 kernel/livepatch/state.h
>
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 591abdee30d7..8bc4c6cc3f3f 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -135,10 +135,12 @@ struct klp_object {
> /**
> * struct klp_state - state of the system modified by the livepatch
> * @id: system state identifier (non zero)
> + * @version: version of the change (non-zero)
> * @data: custom data
> */
> struct klp_state {
> int id;
> + int version;
> void *data;
> };
>
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 24c4a13bd26c..614642719825 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -21,6 +21,7 @@
> #include <asm/cacheflush.h>
> #include "core.h"
> #include "patch.h"
> +#include "state.h"
> #include "transition.h"
>
> /*
> @@ -1003,6 +1004,13 @@ int klp_enable_patch(struct klp_patch *patch)
>
> mutex_lock(&klp_mutex);
>
> + if(!klp_is_patch_compatible(patch)) {
> + pr_err("Livepatch patch (%s) is not compatible with the already installed livepatches.\n",
> + patch->mod->name);
> + mutex_unlock(&klp_mutex);
> + return -EINVAL;
> + }
> +
> ret = klp_init_patch_early(patch);
> if (ret) {
> mutex_unlock(&klp_mutex);


Just as a remark: klp_reverse_transition() could still transition back
to a !klp_is_patch_compatible() patch.

I don't think it's much of a problem, because for live patches
introducing completely new states to the system, it is reasonable
to assume that they'll start applying incompatible changes only from
their ->post_patch(), I guess.

For state "upgrades" to higher versions, it's not so clear though and
some care will be needed. But I think these could still be handled
safely at the cost of some complexity in the new live patch's
->post_patch().

Another detail is that ->post_unpatch() will be called for the new live
patch which has been unpatched due to transition reversal and one would
have to be careful not to free shared state from under the older, still
active live patch. How would ->post_unpatch() distinguish between
transition reversal and "normal" live patch disabling? By
klp_get_prev_state() != NULL?

Perhaps transition reversal should be mentioned in the documentation?

Thanks,

Nicolai


--
SUSE Linux GmbH, GF: Felix ImendÃrffer, Mary Higgins, Sri Rasiah, HRB
21284 (AG NÃrnberg)