lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 13 Sep 2017 09:22:06 +0200 (CEST)
From:   Miroslav Benes <mbenes@...e.cz>
To:     Joe Lawrence <joe.lawrence@...hat.com>
cc:     live-patching@...r.kernel.org, linux-kernel@...r.kernel.org,
        Josh Poimboeuf <jpoimboe@...hat.com>,
        Jessica Yu <jeyu@...nel.org>, Jiri Kosina <jikos@...nel.org>,
        Petr Mladek <pmladek@...e.com>,
        Chris J Arges <chris.j.arges@...onical.com>
Subject: Re: [PATCH v5 1/3] livepatch: add (un)patch callbacks

On Tue, 12 Sep 2017, Joe Lawrence wrote:

> On 09/12/2017 04:53 AM, Miroslav Benes wrote:
> 
> >> +a post-unpatch handler and a post-patch with a pre-unpatch handler in
> >> +symmetry: the patch handler acquires and configures resources and the
> >> +unpatch handler tears down and releases those same resources.
> > 
> > I think it is more than a typical use case. Test 9 shows that. Pre-unpatch 
> > callbacks are skipped if a transition is reversed. I don't have a problem 
> > with that per se, because it seems like a good approach, but maybe we 
> > should describe it properly here. Am I right?
> 
> I think the text was a little fuzzy in regard to what "typical" was
> referring to.  How about this edit:
> 
> --
> Each callback is optional, omitting one does not preclude specifying any
> other.  However, the livepatching core executes the handlers in
> symmetry: pre-patch callbacks have a post-patch counterpart and

s/post-patch/post-unpatch/

> post-patch callbacks have a pre-unpatch counterpart.  An unpatch
> callback will only be executed if its corresponding patch callback was
> executed.  Typical use cases pair a patch handler that acquires and
> configures resources with an unpatch handler tears down and releases
> those same resources.
> --
> 
> Does that clarify that the execution symmetry is fixed and that
> implementing callbacks with that property in mind is up to the caller?

Yes, thank you.
 
> More on the reversed transition comment below ...
> 
> > Anyway, it relates to the next remark just below, which is another rule. 
> > So it is not totally arbitrary.
> > 
> >> +A callback is only executed if its host klp_object is loaded.  For
> >> +in-kernel vmlinux targets, this means that callbacks will always execute
> >> +when a livepatch is enabled/disabled.  For patch target kernel modules,
> >> +callbacks will only execute if the target module is loaded.  When a
> >> +module target is (un)loaded, its callbacks will execute only if the
> >> +livepatch module is enabled.
> >> +
> >> +The pre-patch callback, if specified, is expected to return a status
> >> +code (0 for success, -ERRNO on error).  An error status code indicates
> >> +to the livepatching core that patching of the current klp_object is not
> >> +safe and to stop the current patching request.  (When no pre-patch
> >> +callback is provided, the transition is assumed to be safe.)  If a
> >> +pre-patch callback returns failure, the kernel's module loader will:
> >> +
> >> +  - Refuse to load a livepatch, if the livepatch is loaded after
> >> +    targeted code.
> >> +
> >> +    or:
> >> +
> >> +  - Refuse to load a module, if the livepatch was already successfully
> >> +    loaded.
> >> +
> >> +No post-patch, pre-unpatch, or post-unpatch callbacks will be executed
> >> +for a given klp_object if its pre-patch callback returned non-zero
> >> +status.
> > 
> > Shouldn't this be changed to what Josh proposed? That is
> > 
> >   No post-patch, pre-unpatch, or post-unpatch callbacks will be executed
> >   for a given klp_object if the object failed to patch, due to a failed
> >   pre_patch callback or for any other reason.
> > 
> >   If the object did successfully patch, but the patch transition never
> >   started for some reason (e.g., if another object failed to patch),
> >   only the post-unpatch callback will be called.
> 
> Yeah, I thought I added to the doc, but apparently only coded it.  In
> between these two sentences I'd like to include your suggestion about a
> reversed-transition:
> 
> --
> If a patch transition is reversed, no pre-unpatch handlers will be run
> (this follows the previously mentioned symmetry -- pre-unpatch callbacks
> will only occur if their corresponding post-patch callback executed).
> --
> 
> I think it fits better down here with the collection of misc. rules and
> notes.

Yes.
 
> >> +Test 1
> >> +------
> >> +
> >> +Test a combination of loading a kernel module and a livepatch that
> >> +patches a function in the first module.  (Un)load the target module
> >> +before the livepatch module:
> >> +
> >> +- load target module
> >> +- load livepatch
> >> +- disable livepatch
> >> +- unload target module
> >> +- unload livepatch
> >> +
> >> +First load a target module:
> >> +
> >> +  % insmod samples/livepatch/livepatch-callbacks-mod.ko
> >> +  [   34.475708] livepatch_callbacks_mod: livepatch_callbacks_mod_init
> >> +
> >> +On livepatch enable, before the livepatch transition starts, pre-patch
> >> +callbacks are executed for vmlinux and livepatch_callbacks_mod (those
> >> +klp_objects currently loaded).  After klp_objects are patched according
> >> +to the klp_patch, their post-patch callbacks run and the transition
> >> +completes:
> >> +
> >> +  % insmod samples/livepatch/livepatch-callbacks-demo.ko
> >> +  [   36.503719] livepatch: enabling patch 'livepatch_callbacks_demo'
> >> +  [   36.504213] livepatch: 'livepatch_callbacks_demo': initializing unpatching transition
> > 
> > s/unpatching/patching/
> > 
> > I guess it is a copy&paste error and you can find it elsewhere too.
> 
> Oh no!  This is a actually a bug from patch 3:
> 
>   void klp_init_transition(struct klp_patch *patch, int state)
>   {
>           ...
> 
>   	WARN_ON_ONCE(klp_target_state != KLP_UNDEFINED);
> 
>   	pr_debug("'%s': initializing %s transition\n", patch->mod->name,
>   		 klp_target_state == KLP_PATCHED ? "patching" : "unpatching");
> 
> Wow, that debug msg is going to be very confusing.  I can move this
> down, or just print the target "state" as passed into the function.

Oh, it is a bug. You're right. I'd move it down. Target state could 
cause confusion. User shouldn't need to know anything about live patching 
internals.
 
> > 
> > Apart from these, the documentation is great!
> 
> Thanks, I find the test cases / doc more work than actually writing the
> code.  So many combinations and corner cases to such a simple idea.
> 
> > 
> >> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> >> index 194991ef9347..58403a9af54b 100644
> >> --- a/include/linux/livepatch.h
> >> +++ b/include/linux/livepatch.h
> >> @@ -87,24 +87,49 @@ struct klp_func {
> >>  	bool transition;
> >>  };
> >>  
> >> +struct klp_object;
> >> +
> >> +/**
> >> + * struct klp_callbacks - pre/post live-(un)patch callback structure
> >> + * @pre_patch:		executed before code patching
> >> + * @post_patch:		executed after code patching
> >> + * @pre_unpatch:	executed before code unpatching
> >> + * @post_unpatch:	executed after code unpatching
> >> + *
> >> + * All callbacks are optional.  Only the pre-patch callback, if provided,
> >> + * will be unconditionally executed.  If the parent klp_object fails to
> >> + * patch for any reason, including a non-zero error status returned from
> >> + * the pre-patch callback, no further callbacks will be executed.
> >> + */
> >> +struct klp_callbacks {
> >> +	int (*pre_patch)(struct klp_object *obj);
> >> +	void (*post_patch)(struct klp_object *obj);
> >> +	void (*pre_unpatch)(struct klp_object *obj);
> >> +	void (*post_unpatch)(struct klp_object *obj);
> >> +};
> >> +
> >>  /**
> >>   * struct klp_object - kernel object structure for live patching
> >>   * @name:	module name (or NULL for vmlinux)
> >>   * @funcs:	function entries for functions to be patched in the object
> >> + * @callbacks:	functions to be executed pre/post (un)patching
> >>   * @kobj:	kobject for sysfs resources
> >>   * @mod:	kernel module associated with the patched object
> >>   *		(NULL for vmlinux)
> >>   * @patched:	the object's funcs have been added to the klp_ops list
> >> + * @callbacks_enabled:	flag indicating if callbacks should be run
> > 
> > "flag indicating if post-unpatch callback should be run" ?
> >
> > and then we could change the name to something like 
> > 'pre-patch_callback_enabled' (but that's really ugly).
> 
> Since we removed all the extraneous checks (for post-patch and
> pre-unpatch) against this value, it's probably clearest to rename it
> "post_unpatch_callback_enabled".
> 
> Initially I preferred leaving the callbacks_enabled check in every
> callback execution wrapper, but if those callers will be guaranteed not
> to ever invoke these routines in the wrong contexts, then it's probably
> clearest to call out "post-unpatch" in its name.
> 
> >>   */
> >>  struct klp_object {
> >>  	/* external */
> >>  	const char *name;
> >>  	struct klp_func *funcs;
> >> +	struct klp_callbacks callbacks;
> >>  
> >>  	/* internal */
> >>  	struct kobject kobj;
> >>  	struct module *mod;
> >>  	bool patched;
> >> +	bool callbacks_enabled;
> >>  };
> > 
> > How about moving callbacks_enabled to klp_callbacks structure? It belongs 
> > there. It is true, that we'd mix internal and external members with that.
> > 
> > [...]
> 
> No strong preferences here.  It's simple enough to change.  And it would
> reduce the enable flag above to "post_unpatch_enabled"

If everyone agrees, I'd move it to klp_callbacks structure and call it as 
you propose.
 
Thanks,
Miroslav

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ