Re: [PATCH v10 03/10] livepatch: Initial support for dynamic structures

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue 2018-03-13 17:44:17, Josh Poimboeuf wrote:
> On Wed, Mar 07, 2018 at 09:20:32AM +0100, Petr Mladek wrote:
> > From: Jason Baron <jbaron@xxxxxxxxxx>
> > 
> > We are going to add a feature called atomic replace. It will allow to
> > create a patch that would replace all already registered patches.
> > For this, we will need to dynamically create funcs and objects
> > for functions that are no longer patched.
> > 
> > This patch adds basic framework to handle such dynamic structures.
> > 
> > It adds enum klp_func_type that allows to distinguish the dynamically
> > allocated funcs' structures. Note that objects' structures do not have
> > a clear type. Namely the static objects' structures might list both static
> > and dynamic funcs' structures.
> > 
> > The function type is then used to limit klp_free() functions. We will
> > want to free the dynamic structures separately when they are no longer
> > needed. At the same time, we also want to make our life easier,
> > and introduce _any_ type that will allow to process all existing
> > structures in one go.
> > 
> > We need to be careful here. First, objects' structures must be freed
> > only when all listed funcs' structures are freed. Also we must avoid
> > double free. Both problems are solved by removing the freed structures
> > from the list.
> > 
> > Also note that klp_free*() functions are called also in klp_init_patch()
> > error path when only some kobjects have been initialized. The other
> > dynamic structures must be freed immediately by calling the respective
> > klp_free_*_dynamic() functions.
> > 
> > Finally, the dynamic objects' structures are generic. The respective
> > klp_allocate_object_dynamic() and klp_free_object_dynamic() can
> > be implemented here. On the other hand, klp_free_func_dynamic()
> > is empty. It must be updated when a particular dynamic
> > klp_func_type is introduced.
> > 
> > Signed-off-by: Jason Baron <jbaron@xxxxxxxxxx>
> > [pmladek@xxxxxxxx: Converted into a generic API]
> > Signed-off-by: Petr Mladek <pmladek@xxxxxxxx>
> > Cc: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
> > Cc: Jessica Yu <jeyu@xxxxxxxxxx>
> > Cc: Jiri Kosina <jikos@xxxxxxxxxx>
> > Acked-by: Miroslav Benes <mbenes@xxxxxxx>
> 
> I appreciate the split out patches, but I feel like they're split up
> *too* much.  I found that it was hard to make sense of patches 3-5
> without looking at patch 6.  So I'd suggest combining 3-6 into a single
> patch.

I have squashed the patchset to 5 patches as of this writing. Well,
the main motivation was that it was much easier to do the other
suggested changes this way.

Otherwise I do not have a strong opinion. I think that preparatory
patches are useful if they help to split a huge change into some
logical steps. Everything usually makes much more sense in 2nd
review... ;-)


> Also, since patches 7-8 seem to be bug fixes for patch 6, they should be
> squashed in, so we don't break bisectability unnecessarily.

All the bugs were visible only with patches using the atomic replace.
Therefore they did not affect the bisectability. I guess that they
helped people who reviewed the earlier revisions. Anyway, they will
be squashed in v11.

 
> > ---
> >  include/linux/livepatch.h |  37 +++++++++++-
> >  kernel/livepatch/core.c   | 141 +++++++++++++++++++++++++++++++++++++++++-----
> >  2 files changed, 163 insertions(+), 15 deletions(-)
> > 
> > diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> > index e5db2ba7e2a5..7fb76e7d2693 100644
> > --- a/include/linux/livepatch.h
> > +++ b/include/linux/livepatch.h
> > @@ -35,12 +35,22 @@
> >  #define KLP_UNPATCHED	 0
> >  #define KLP_PATCHED	 1
> >  
> > +/*
> > + * Function type is used to distinguish dynamically allocated structures
> > + * and limit some operations.
> > + */
> > +enum klp_func_type {
> > +	KLP_FUNC_ANY = -1,	/* Substitute any type */
> > +	KLP_FUNC_STATIC = 0,    /* Original statically defined structure */
> > +};
> > +
> >  /**
> >   * struct klp_func - function structure for live patching
> >   * @old_name:	name of the function to be patched
> >   * @new_func:	pointer to the patched function code
> >   * @old_sympos: a hint indicating which symbol position the old function
> >   *		can be found (optional)
> > + * @ftype:	distinguish static and dynamic structures
> 
> The "f" in ftype is redundant because it's already in a klp_func struct.

The type item will be gone in v11.


> Also, I wonder if a 'dynamic' bool would be cleaner / more legible than
> the enum.  Instead of e.g.
> 
>   klp_free_objects(patch, KLP_FUNC_ANY);
>   klp_free_objects(patch, KLP_FUNC_NOP);
> 
> it could be
> 
>   klp_free_objects(patch)
>   klp_free_objects_dynamic(patch);
> 
> with the klp_free_objects*() functions calling a __klp_free_objects()
> helper which takes a bool as an argument.
>
> There would need to be other changes, so I'm not sure it would be
> better, but it could be worth trying out and seeing if it's cleaner.

I gave it a chance. Somewhere it helped, somewhere it made it worse.
The overall result looks better to me, so I will use it in v11.

The main challenge was that I wanted to use "bool nop" in struct klp_func
and "bool dynamic" in struct klp_object. Then I needed to pass a
common flag to handle only these structures to klp_free_objects(),
klp_free_funcs(), klp_unpatch_objects(), klp_unpatch_func().
I solved this by using the inverse logic, for example, by passing
"bool free_all" to the free() functions.


> >   * @old_addr:	the address of the function being patched
> >   * @kobj:	kobject for sysfs resources
> >   * @stack_node:	list node for klp_ops func_stack list
> > @@ -164,17 +175,41 @@ struct klp_patch {
[...]
> > +static inline bool klp_is_func_dynamic(struct klp_func *func)
> > +{
> > +	WARN_ON_ONCE(func->ftype == KLP_FUNC_ANY);
> 
> This seems like a silly warning.  Surely such a condition wouldn't get
> past code review :-)
>
> > +	return func->ftype != KLP_FUNC_STATIC;
> > +}
> 
> I think this would be clearer:
> 
> 	return func->ftype == KLP_FUNC_NOP;
> 
> and perhaps KLP_FUNC_NOP should be renamed to KLP_FUNC_DYNAMIC?
> 
> 	return func->ftype == KLP_FUNC_DYNAMIC;
> 
> (though I realize this patch doesn't have KLP_FUNC_NOP yet)

All these helpers are gone in v11. They are not needed with
the booleans.


> > +
> > +static inline bool klp_is_func_type(struct klp_func *func,
> > +				    enum klp_func_type ftype)
> > +{
> > +	return ftype == KLP_FUNC_ANY || ftype == func->ftype;
> > +}
> > +
> >  int klp_register_patch(struct klp_patch *);
> >  int klp_unregister_patch(struct klp_patch *);
> >  int klp_enable_patch(struct klp_patch *);

I followed also the other suggestions from this mail.


Best Regardsm
Petr
--
To unsubscribe from this list: send the line "unsubscribe live-patching" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux Kernel]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux