mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Miroslav Benes <mbenes@suse.cz>
To: Petr Mladek <pmladek@suse.com>
Cc: Jiri Kosina <jikos@kernel.org>,
	Josh Poimboeuf <jpoimboe@redhat.com>,
	Jason Baron <jbaron@akamai.com>,
	Joe Lawrence <joe.lawrence@redhat.com>,
	Jessica Yu <jeyu@kernel.org>,
	Evgenii Shatokhin <eshatokhin@virtuozzo.com>,
	live-patching@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v12 06/12] livepatch: Simplify API by removing registration step
Date: Wed, 5 Sep 2018 11:34:06 +0200 (CEST)	[thread overview]
Message-ID: <alpine.LSU.2.21.1809051108440.7768@pobox.suse.cz> (raw)
In-Reply-To: <20180828143603.4442-7-pmladek@suse.com>

On Tue, 28 Aug 2018, Petr Mladek wrote:

> The possibility to re-enable a registered patch was useful for immediate
> patches where the livepatch module had to stay until the system reboot.
> The improved consistency model allows to achieve the same result by
> unloading and loading the livepatch module again.
> 
> Also we are going to add a feature called atomic replace. It will allow
> to create a patch that would replace all already registered patches. The
> aim is to handle dependent patches a more secure way. It will obsolete

"in a more secure way", or "more securely" is maybe even better.

> the stack of patches that helped to handle the dependencies so far.
> Then it might be unclear when a cumulative patch re-enabling is safe.
> 
> It would be complicated to support the many modes. Instead we could
> actually make the API and code easier.

s/easier/simpler/ ?

or "easier to understand" ?
 
> This patch removes the two step public API. All the checks and init calls
> are moved from klp_register_patch() to klp_enabled_patch(). Also the patch
> is automatically freed, including the sysfs interface when the transition
> to the disabled state is completed.
> 
> As a result, there is newer a disabled patch on the top of the stack.

s/newer/never/

> Therefore we do not need to check the stack in __klp_enable_patch().
> And we could simplify the check in __klp_disable_patch().
> 
> Also the API and logic is much easier. It is enough to call
> klp_enable_patch() in module_init() call. The patch patch can be disabled
> by writing '0' into /sys/kernel/livepatch/<patch>/enabled. Then the module
> can be removed once the transition finishes and sysfs interface is freed.

I think it would be good to discuss our sysfs interface here as well.

Writing '1' to enabled attribute now makes sense only when you need to 
reverse an unpatching transition. Writing '0' means "disable" or a 
reversion again.

Wouldn't be better to split it to two different attributes? Something like 
"disable" and "reverse"? It could be more intuitive.

Maybe we'd also find out that even patch->enabled member is not useful 
anymore in such case.

> diff --git a/Documentation/livepatch/livepatch.txt b/Documentation/livepatch/livepatch.txt
> index 2d7ed09dbd59..7fb01d27d81d 100644
> --- a/Documentation/livepatch/livepatch.txt
> +++ b/Documentation/livepatch/livepatch.txt
> @@ -14,10 +14,8 @@ Table of Contents:

[...]

> -5.2. Enabling
> +5.1. Enabling
>  -------------
>  
> -Registered patches might be enabled either by calling klp_enable_patch() or
> -by writing '1' to /sys/kernel/livepatch/<name>/enabled. The system will
> -start using the new implementation of the patched functions at this stage.
> +Livepatch modules have to call klp_enable_patch() in module_init() callback.
> +This function is rather complex and might even fail in the early phase.
>  
> -When a patch is enabled, livepatch enters into a transition state where
> -tasks are converging to the patched state.  This is indicated by a value
> -of '1' in /sys/kernel/livepatch/<name>/transition.  Once all tasks have
> -been patched, the 'transition' value changes to '0'.  For more
> -information about this process, see the "Consistency model" section.
> +First, the addresses of the patched functions are found according to their
> +names. The special relocations, mentioned in the section "New functions",
> +are applied. The relevant entries are created under
> +/sys/kernel/livepatch/<name>. The patch is rejected when any above
> +operation fails.
>  
> -If an original function is patched for the first time, a function
> -specific struct klp_ops is created and an universal ftrace handler is
> -registered.
> +Third, livepatch enters into a transition state where tasks are converging

s/Third/Second/ ?

[...]

> @@ -655,116 +660,38 @@ static int klp_init_patch(struct klp_patch *patch)
>  	struct klp_object *obj;
>  	int ret;
>  
> -	if (!patch->objs)
> -		return -EINVAL;
> -
> -	mutex_lock(&klp_mutex);
> -
>  	patch->enabled = false;
> -	patch->forced = false;
> +	patch->module_put = false;
>  	INIT_LIST_HEAD(&patch->list);
>  	init_completion(&patch->finish);
>  
> +	if (!patch->objs)
> +		return -EINVAL;
> +
> +	/*
> +	 * A reference is taken on the patch module to prevent it from being
> +	 * unloaded.
> +	 */
> +	if (!try_module_get(patch->mod))
> +		return -ENODEV;
> +	patch->module_put = true;
> +
>  	ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch,
>  				   klp_root_kobj, "%s", patch->mod->name);
>  	if (ret) {
> -		mutex_unlock(&klp_mutex);
>  		return ret;
>  	}

{ } are not necessary after the change.

[...]

>  static int __klp_enable_patch(struct klp_patch *patch)
>  {
>  	struct klp_object *obj;
> @@ -846,17 +740,8 @@ static int __klp_enable_patch(struct klp_patch *patch)
>  	if (WARN_ON(patch->enabled))
>  		return -EINVAL;
>  
> -	/* enforce stacking: only the first disabled patch can be enabled */
> -	if (patch->list.prev != &klp_patches &&
> -	    !list_prev_entry(patch, list)->enabled)
> -		return -EBUSY;
> -
> -	/*
> -	 * A reference is taken on the patch module to prevent it from being
> -	 * unloaded.
> -	 */
> -	if (!try_module_get(patch->mod))
> -		return -ENODEV;
> +	if (!patch->kobj.state_initialized)
> +		return -EINVAL;

I think the check is not needed here. __klp_enable_patch() is called right after
klp_init_patch() in klp_enable_patch().

>  	pr_notice("enabling patch '%s'\n", patch->mod->name);
>  

[...]

> @@ -405,7 +399,11 @@ void klp_try_complete_transition(void)
>  	}
>  
>  	/* we're done, now cleanup the data structures */
> +	patch = klp_transition_patch;
>  	klp_complete_transition();
> +
> +	if (!patch->enabled)
> +		klp_free_patch_nowait(patch);
>  }

I'd welcome a comment here. I thought it was more logical to call
klp_free_patch_nowait() in klp_complete_transition(). It's not possible though.
klp_complete_transition() is also called from klp_cancel_transition() which has
its own freeing in klp_enable_patch()'s error path.
 
Regards,
Miroslav

  reply	other threads:[~2018-09-05  9:34 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-28 14:35 [PATCH v12 00/12] Petr Mladek
2018-08-28 14:35 ` [PATCH v12 01/12] livepatch: Change void *new_func -> unsigned long new_addr in struct klp_func Petr Mladek
2018-08-31  8:37   ` Miroslav Benes
2018-08-28 14:35 ` [PATCH v12 02/12] livepatch: Helper macros to define livepatch structures Petr Mladek
2018-08-28 14:35 ` [PATCH v12 03/12] livepatch: Shuffle klp_enable_patch()/klp_disable_patch() code Petr Mladek
2018-08-31  8:38   ` Miroslav Benes
2018-08-28 14:35 ` [PATCH v12 04/12] livepatch: Consolidate klp_free functions Petr Mladek
2018-08-31 10:39   ` Miroslav Benes
2018-10-12 11:43     ` Petr Mladek
2018-08-28 14:35 ` [PATCH v12 05/12] livepatch: Refuse to unload only livepatches available during a forced transition Petr Mladek
2018-08-28 14:35 ` [PATCH v12 06/12] livepatch: Simplify API by removing registration step Petr Mladek
2018-09-05  9:34   ` Miroslav Benes [this message]
2018-10-12 13:01     ` Petr Mladek
2018-10-15 16:01       ` Miroslav Benes
2018-10-18 14:54         ` Petr Mladek
2018-10-18 15:30           ` Josh Poimboeuf
2018-10-19 12:16             ` Miroslav Benes
2018-10-19 14:36               ` Josh Poimboeuf
2018-10-22 13:25                 ` Petr Mladek
2018-10-23 16:39                   ` Josh Poimboeuf
2018-10-24  2:55                     ` Josh Poimboeuf
2018-10-24 11:14                     ` Petr Mladek
2018-08-28 14:35 ` [PATCH v12 07/12] livepatch: Use lists to manage patches, objects and functions Petr Mladek
2018-09-03 16:00   ` Miroslav Benes
2018-10-12 12:12     ` Petr Mladek
2018-08-28 14:35 ` [PATCH v12 08/12] livepatch: Add atomic replace Petr Mladek
2018-08-28 14:36 ` [PATCH v12 09/12] livepatch: Remove Nop structures when unused Petr Mladek
2018-09-04 14:50   ` Miroslav Benes
2018-08-28 14:36 ` [PATCH v12 10/12] livepatch: Atomic replace and cumulative patches documentation Petr Mladek
2018-09-04 15:15   ` Miroslav Benes
2018-08-28 14:36 ` [PATCH v12 11/12] livepatch: Remove ordering and refuse loading conflicting patches Petr Mladek
2018-08-28 14:36 ` [PATCH v12 12/12] selftests/livepatch: introduce tests Petr Mladek
2018-08-30 11:58 ` [PATCH v12 00/12] Miroslav Benes
2018-10-11 12:48   ` Petr Mladek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LSU.2.21.1809051108440.7768@pobox.suse.cz \
    --to=mbenes@suse.cz \
    --cc=eshatokhin@virtuozzo.com \
    --cc=jbaron@akamai.com \
    --cc=jeyu@kernel.org \
    --cc=jikos@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=pmladek@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®