All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-02 17:58 ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-02 17:58 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function.number>

The number is incremented on each known initialized func kobj thus creating
unique names in this case.

An example of this issue is documented here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
 kernel/livepatch/core.c                          | 20 ++++++++++++++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..dcd36db 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..ecacf65 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func.number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -727,13 +727,29 @@ static void klp_free_patch(struct klp_patch *patch)
 	kobject_put(&patch->kobj);
 }
 
+static int klp_count_sysfs_funcs(struct klp_object *obj, const char *name)
+{
+	struct klp_func *func;
+	int n = 0;
+
+	/* count the times a function name occurs and is initialized */
+	klp_for_each_func(obj, func) {
+		if ((!strcmp(func->old_name, name) &&
+		    func->kobj.state_initialized))
+			n++;
+	}
+
+	return n;
+}
+
 static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 {
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s.%d", func->old_name,
+				    klp_count_sysfs_funcs(obj, func->old_name));
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-02 17:58 ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-02 17:58 UTC (permalink / raw)
  To: live-patching-u79uwXL29TY76Z2rM5mHXA
  Cc: jeyu-H+wXaHxf7aLQT0dZR+AlfA, Chris J Arges, Josh Poimboeuf,
	Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function.number>

The number is incremented on each known initialized func kobj thus creating
unique names in this case.

An example of this issue is documented here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
 kernel/livepatch/core.c                          | 20 ++++++++++++++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..dcd36db 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..ecacf65 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func.number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -727,13 +727,29 @@ static void klp_free_patch(struct klp_patch *patch)
 	kobject_put(&patch->kobj);
 }
 
+static int klp_count_sysfs_funcs(struct klp_object *obj, const char *name)
+{
+	struct klp_func *func;
+	int n = 0;
+
+	/* count the times a function name occurs and is initialized */
+	klp_for_each_func(obj, func) {
+		if ((!strcmp(func->old_name, name) &&
+		    func->kobj.state_initialized))
+			n++;
+	}
+
+	return n;
+}
+
 static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 {
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s.%d", func->old_name,
+				    klp_count_sysfs_funcs(obj, func->old_name));
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-02 17:58 ` Chris J Arges
  (?)
@ 2015-11-02 19:15 ` Jessica Yu
  -1 siblings, 0 replies; 104+ messages in thread
From: Jessica Yu @ 2015-11-02 19:15 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

+++ Chris J Arges [02/11/15 11:58 -0600]:
>The following directory structure will allow for cases when the same
>function name exists in a single object.
>	/sys/kernel/livepatch/<patch>/<object>/<function.number>
>
>The number is incremented on each known initialized func kobj thus creating
>unique names in this case.
>
>An example of this issue is documented here:
>	https://github.com/dynup/kpatch/issues/493
>
>Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>

Thanks Chris. Verified that the patch fixes the panic caused by
multiple functions with the same name and object.

Acked-by: Jessica Yu <jeyu@redhat.com>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-02 19:52   ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-02 19:52 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On Mon, Nov 02, 2015 at 11:58:47AM -0600, Chris J Arges wrote:
> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> 
> The number is incremented on each known initialized func kobj thus creating
> unique names in this case.
> 
> An example of this issue is documented here:
> 	https://github.com/dynup/kpatch/issues/493
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
>  kernel/livepatch/core.c                          | 20 ++++++++++++++++++--
>  2 files changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> index 5bf42a8..dcd36db 100644
> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> @@ -33,7 +33,7 @@ Description:
>  		The object directory contains subdirectories for each function
>  		that is patched within the object.
>  
> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> +What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
>  Date:		Nov 2014
>  KernelVersion:	3.19.0
>  Contact:	live-patching@vger.kernel.org
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..ecacf65 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>   * /sys/kernel/livepatch/<patch>
>   * /sys/kernel/livepatch/<patch>/enabled
>   * /sys/kernel/livepatch/<patch>/<object>
> - * /sys/kernel/livepatch/<patch>/<object>/<func>
> + * /sys/kernel/livepatch/<patch>/<object>/<func.number>
>   */
>  
>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> @@ -727,13 +727,29 @@ static void klp_free_patch(struct klp_patch *patch)
>  	kobject_put(&patch->kobj);
>  }
>  
> +static int klp_count_sysfs_funcs(struct klp_object *obj, const char *name)
> +{
> +	struct klp_func *func;
> +	int n = 0;
> +
> +	/* count the times a function name occurs and is initialized */
> +	klp_for_each_func(obj, func) {
> +		if ((!strcmp(func->old_name, name) &&
> +		    func->kobj.state_initialized))
> +			n++;
> +	}
> +
> +	return n;
> +}
> +
>  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  {
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
>  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +				    &obj->kobj, "%s.%d", func->old_name,
> +				    klp_count_sysfs_funcs(obj, func->old_name));
>  }
>  
>  /* parts of the initialization that is done only when the object is loaded */
> -- 
> 1.9.1

I'd prefer something other than a period for the string separator
because some symbols have a period in their name.  How about a space?

Also, this shows the nth occurrence of the symbol name in the patch
module.  But I think it would be better to instead display the nth
occurrence of the symbol name in the kallsyms for the patched object.
That way user space can deterministically detect which function was
patched.

For example:

  $ grep " t_next" /proc/kallsyms
  ffffffff811597d0 t t_next
  ffffffff81163bb0 t t_next
  ...

In my kernel there are 6 functions named t_next in vmlinux.  "t_next 0"
would refer to the function at 0xffffffff811597d0.  "t_next 1" would
refer to the one at 0xffffffff81163bb0.

While we're at it, should we also encode the replacement function name
(func->new_func)?  e.g.:

  "t_next 0 t_next__patched".


-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-02 19:52   ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-02 19:52 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Mon, Nov 02, 2015 at 11:58:47AM -0600, Chris J Arges wrote:
> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> 
> The number is incremented on each known initialized func kobj thus creating
> unique names in this case.
> 
> An example of this issue is documented here:
> 	https://github.com/dynup/kpatch/issues/493
> 
> Signed-off-by: Chris J Arges <chris.j.arges-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
> ---
>  Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
>  kernel/livepatch/core.c                          | 20 ++++++++++++++++++--
>  2 files changed, 19 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> index 5bf42a8..dcd36db 100644
> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> @@ -33,7 +33,7 @@ Description:
>  		The object directory contains subdirectories for each function
>  		that is patched within the object.
>  
> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> +What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
>  Date:		Nov 2014
>  KernelVersion:	3.19.0
>  Contact:	live-patching-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..ecacf65 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>   * /sys/kernel/livepatch/<patch>
>   * /sys/kernel/livepatch/<patch>/enabled
>   * /sys/kernel/livepatch/<patch>/<object>
> - * /sys/kernel/livepatch/<patch>/<object>/<func>
> + * /sys/kernel/livepatch/<patch>/<object>/<func.number>
>   */
>  
>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> @@ -727,13 +727,29 @@ static void klp_free_patch(struct klp_patch *patch)
>  	kobject_put(&patch->kobj);
>  }
>  
> +static int klp_count_sysfs_funcs(struct klp_object *obj, const char *name)
> +{
> +	struct klp_func *func;
> +	int n = 0;
> +
> +	/* count the times a function name occurs and is initialized */
> +	klp_for_each_func(obj, func) {
> +		if ((!strcmp(func->old_name, name) &&
> +		    func->kobj.state_initialized))
> +			n++;
> +	}
> +
> +	return n;
> +}
> +
>  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  {
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
>  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +				    &obj->kobj, "%s.%d", func->old_name,
> +				    klp_count_sysfs_funcs(obj, func->old_name));
>  }
>  
>  /* parts of the initialization that is done only when the object is loaded */
> -- 
> 1.9.1

I'd prefer something other than a period for the string separator
because some symbols have a period in their name.  How about a space?

Also, this shows the nth occurrence of the symbol name in the patch
module.  But I think it would be better to instead display the nth
occurrence of the symbol name in the kallsyms for the patched object.
That way user space can deterministically detect which function was
patched.

For example:

  $ grep " t_next" /proc/kallsyms
  ffffffff811597d0 t t_next
  ffffffff81163bb0 t t_next
  ...

In my kernel there are 6 functions named t_next in vmlinux.  "t_next 0"
would refer to the function at 0xffffffff811597d0.  "t_next 1" would
refer to the one at 0xffffffff81163bb0.

While we're at it, should we also encode the replacement function name
(func->new_func)?  e.g.:

  "t_next 0 t_next__patched".


-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-02 19:52   ` Josh Poimboeuf
  (?)
@ 2015-11-02 20:16   ` Chris J Arges
  2015-11-02 20:32     ` Josh Poimboeuf
  -1 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-02 20:16 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On Mon, Nov 02, 2015 at 01:52:44PM -0600, Josh Poimboeuf wrote:
> On Mon, Nov 02, 2015 at 11:58:47AM -0600, Chris J Arges wrote:
> > The following directory structure will allow for cases when the same
> > function name exists in a single object.
> > 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> > 
> > The number is incremented on each known initialized func kobj thus creating
> > unique names in this case.
> > 
> > An example of this issue is documented here:
> > 	https://github.com/dynup/kpatch/issues/493
> > 
> > Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> > ---
> >  Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
> >  kernel/livepatch/core.c                          | 20 ++++++++++++++++++--
> >  2 files changed, 19 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> > index 5bf42a8..dcd36db 100644
> > --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> > +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> > @@ -33,7 +33,7 @@ Description:
> >  		The object directory contains subdirectories for each function
> >  		that is patched within the object.
> >  
> > -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> > +What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
> >  Date:		Nov 2014
> >  KernelVersion:	3.19.0
> >  Contact:	live-patching@vger.kernel.org
> > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > index 6e53441..ecacf65 100644
> > --- a/kernel/livepatch/core.c
> > +++ b/kernel/livepatch/core.c
> > @@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
> >   * /sys/kernel/livepatch/<patch>
> >   * /sys/kernel/livepatch/<patch>/enabled
> >   * /sys/kernel/livepatch/<patch>/<object>
> > - * /sys/kernel/livepatch/<patch>/<object>/<func>
> > + * /sys/kernel/livepatch/<patch>/<object>/<func.number>
> >   */
> >  
> >  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> > @@ -727,13 +727,29 @@ static void klp_free_patch(struct klp_patch *patch)
> >  	kobject_put(&patch->kobj);
> >  }
> >  
> > +static int klp_count_sysfs_funcs(struct klp_object *obj, const char *name)
> > +{
> > +	struct klp_func *func;
> > +	int n = 0;
> > +
> > +	/* count the times a function name occurs and is initialized */
> > +	klp_for_each_func(obj, func) {
> > +		if ((!strcmp(func->old_name, name) &&
> > +		    func->kobj.state_initialized))
> > +			n++;
> > +	}
> > +
> > +	return n;
> > +}
> > +
> >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> >  {
> >  	INIT_LIST_HEAD(&func->stack_node);
> >  	func->state = KLP_DISABLED;
> >  
> >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > -				    &obj->kobj, "%s", func->old_name);
> > +				    &obj->kobj, "%s.%d", func->old_name,
> > +				    klp_count_sysfs_funcs(obj, func->old_name));
> >  }
> >  
> >  /* parts of the initialization that is done only when the object is loaded */
> > -- 
> > 1.9.1
> 
> I'd prefer something other than a period for the string separator
> because some symbols have a period in their name.  How about a space?
> 

Perhaps a '-' would be better?
/t_next-0
/t_next-1

> Also, this shows the nth occurrence of the symbol name in the patch
> module.  But I think it would be better to instead display the nth
> occurrence of the symbol name in the kallsyms for the patched object.
> That way user space can deterministically detect which function was
> patched.
> 
> For example:
> 
>   $ grep " t_next" /proc/kallsyms
>   ffffffff811597d0 t t_next
>   ffffffff81163bb0 t t_next
>   ...
> 
> In my kernel there are 6 functions named t_next in vmlinux.  "t_next 0"
> would refer to the function at 0xffffffff811597d0.  "t_next 1" would
> refer to the one at 0xffffffff81163bb0.
> 

This makes sense to me.

> While we're at it, should we also encode the replacement function name
> (func->new_func)?  e.g.:
> 
>   "t_next 0 t_next__patched".
> 
> 
> -- 
> Josh
>

Since we are creating a directory for this function, at some point would we add
this as a file in that func directory? I think encoding the func name with
old_name + occurrence should accomplish uniqueness and consistency.

However, another approach would be:

/<old_func>-<new_func>

Which presumably would be unique and consistent (depending on how the patch was
authored).

--chris



 

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-02 20:16   ` Chris J Arges
@ 2015-11-02 20:32     ` Josh Poimboeuf
  2015-11-02 22:59         ` Chris J Arges
  0 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-02 20:32 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On Mon, Nov 02, 2015 at 02:16:16PM -0600, Chris J Arges wrote:
> On Mon, Nov 02, 2015 at 01:52:44PM -0600, Josh Poimboeuf wrote:
> > On Mon, Nov 02, 2015 at 11:58:47AM -0600, Chris J Arges wrote:
> > > The following directory structure will allow for cases when the same
> > > function name exists in a single object.
> > > 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> > > 
> > > The number is incremented on each known initialized func kobj thus creating
> > > unique names in this case.
> > > 
> > > An example of this issue is documented here:
> > > 	https://github.com/dynup/kpatch/issues/493
> > > 
> > > Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> > > ---
> > >  Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
> > >  kernel/livepatch/core.c                          | 20 ++++++++++++++++++--
> > >  2 files changed, 19 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> > > index 5bf42a8..dcd36db 100644
> > > --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> > > +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> > > @@ -33,7 +33,7 @@ Description:
> > >  		The object directory contains subdirectories for each function
> > >  		that is patched within the object.
> > >  
> > > -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> > > +What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
> > >  Date:		Nov 2014
> > >  KernelVersion:	3.19.0
> > >  Contact:	live-patching@vger.kernel.org
> > > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > > index 6e53441..ecacf65 100644
> > > --- a/kernel/livepatch/core.c
> > > +++ b/kernel/livepatch/core.c
> > > @@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
> > >   * /sys/kernel/livepatch/<patch>
> > >   * /sys/kernel/livepatch/<patch>/enabled
> > >   * /sys/kernel/livepatch/<patch>/<object>
> > > - * /sys/kernel/livepatch/<patch>/<object>/<func>
> > > + * /sys/kernel/livepatch/<patch>/<object>/<func.number>
> > >   */
> > >  
> > >  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> > > @@ -727,13 +727,29 @@ static void klp_free_patch(struct klp_patch *patch)
> > >  	kobject_put(&patch->kobj);
> > >  }
> > >  
> > > +static int klp_count_sysfs_funcs(struct klp_object *obj, const char *name)
> > > +{
> > > +	struct klp_func *func;
> > > +	int n = 0;
> > > +
> > > +	/* count the times a function name occurs and is initialized */
> > > +	klp_for_each_func(obj, func) {
> > > +		if ((!strcmp(func->old_name, name) &&
> > > +		    func->kobj.state_initialized))
> > > +			n++;
> > > +	}
> > > +
> > > +	return n;
> > > +}
> > > +
> > >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> > >  {
> > >  	INIT_LIST_HEAD(&func->stack_node);
> > >  	func->state = KLP_DISABLED;
> > >  
> > >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > > -				    &obj->kobj, "%s", func->old_name);
> > > +				    &obj->kobj, "%s.%d", func->old_name,
> > > +				    klp_count_sysfs_funcs(obj, func->old_name));
> > >  }
> > >  
> > >  /* parts of the initialization that is done only when the object is loaded */
> > > -- 
> > > 1.9.1
> > 
> > I'd prefer something other than a period for the string separator
> > because some symbols have a period in their name.  How about a space?
> > 
> 
> Perhaps a '-' would be better?
> /t_next-0
> /t_next-1

Yeah, that would work.  I tend to prefer a space or a comma as a
delimiter but anything unique is fine.

> > Also, this shows the nth occurrence of the symbol name in the patch
> > module.  But I think it would be better to instead display the nth
> > occurrence of the symbol name in the kallsyms for the patched object.
> > That way user space can deterministically detect which function was
> > patched.
> > 
> > For example:
> > 
> >   $ grep " t_next" /proc/kallsyms
> >   ffffffff811597d0 t t_next
> >   ffffffff81163bb0 t t_next
> >   ...
> > 
> > In my kernel there are 6 functions named t_next in vmlinux.  "t_next 0"
> > would refer to the function at 0xffffffff811597d0.  "t_next 1" would
> > refer to the one at 0xffffffff81163bb0.
> > 
> 
> This makes sense to me.
> 
> > While we're at it, should we also encode the replacement function name
> > (func->new_func)?  e.g.:
> > 
> >   "t_next 0 t_next__patched".
> > 
> > 
> > -- 
> > Josh
> >
> 
> Since we are creating a directory for this function, at some point would we add
> this as a file in that func directory?

Yeah, we could always add that later.  It's probably best to wait until
somebody actually needs it anyway.

> I think encoding the func name with
> old_name + occurrence should accomplish uniqueness and consistency.
>
> However, another approach would be:
> 
> /<old_func>-<new_func>
> 
> Which presumably would be unique and consistent (depending on how the patch was
> authored).

As you said, depending on how the patch was authored, I think it would
still be possible for it to be not unique, as we can have duplicate
symbol names in the patch module too.

And also you wouldn't have the ability to determine exactly which
"old_func" is being patched, which could potentially be an important
detail.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-02 22:59         ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-02 22:59 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function.number>

The number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of this issue is documented here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
 kernel/livepatch/core.c                          | 45 ++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..dcd36db 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..6bcf600 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func.number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -727,13 +727,54 @@ static void klp_free_patch(struct klp_patch *patch)
 	kobject_put(&patch->kobj);
 }
 
+static int klp_get_func_pos_callback(void *data, const char *name,
+				      struct module *mod, unsigned long addr)
+{
+	struct klp_find_arg *args = data;
+
+	if ((mod && !args->objname) || (!mod && args->objname))
+		return 0;
+
+	if (strcmp(args->name, name))
+		return 0;
+
+	if (args->objname && strcmp(args->objname, mod->name))
+		return 0;
+
+	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
+	if (args->addr == addr)
+		return 1;
+
+	/* if we don't match addr, count instance of named symbol */
+	args->count++;
+
+	return 0;
+}
+
+static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
+{
+	struct klp_find_arg args = {
+		.objname = obj->name,
+		.name = func->old_name,
+		.addr = func->old_addr,
+		.count = 0,
+	};
+
+	mutex_lock(&module_mutex);
+	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
+	mutex_unlock(&module_mutex);
+
+	return args.count;
+}
+
 static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 {
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%d", func->old_name,
+				    klp_get_func_pos(obj, func));
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-02 22:59         ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-02 22:59 UTC (permalink / raw)
  To: live-patching-u79uwXL29TY76Z2rM5mHXA
  Cc: jeyu-H+wXaHxf7aLQT0dZR+AlfA, Chris J Arges, Josh Poimboeuf,
	Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function.number>

The number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of this issue is documented here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
 kernel/livepatch/core.c                          | 45 ++++++++++++++++++++++--
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..dcd36db 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..6bcf600 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func.number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -727,13 +727,54 @@ static void klp_free_patch(struct klp_patch *patch)
 	kobject_put(&patch->kobj);
 }
 
+static int klp_get_func_pos_callback(void *data, const char *name,
+				      struct module *mod, unsigned long addr)
+{
+	struct klp_find_arg *args = data;
+
+	if ((mod && !args->objname) || (!mod && args->objname))
+		return 0;
+
+	if (strcmp(args->name, name))
+		return 0;
+
+	if (args->objname && strcmp(args->objname, mod->name))
+		return 0;
+
+	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
+	if (args->addr == addr)
+		return 1;
+
+	/* if we don't match addr, count instance of named symbol */
+	args->count++;
+
+	return 0;
+}
+
+static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
+{
+	struct klp_find_arg args = {
+		.objname = obj->name,
+		.name = func->old_name,
+		.addr = func->old_addr,
+		.count = 0,
+	};
+
+	mutex_lock(&module_mutex);
+	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
+	mutex_unlock(&module_mutex);
+
+	return args.count;
+}
+
 static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 {
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%d", func->old_name,
+				    klp_get_func_pos(obj, func));
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-02 22:59         ` Chris J Arges
  (?)
@ 2015-11-03  9:50         ` Miroslav Benes
  2015-11-03 15:03           ` Josh Poimboeuf
  -1 siblings, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-03  9:50 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Mon, 2 Nov 2015, Chris J Arges wrote:

> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function.number>

There is still a period here and in the documentation :)

> The number corresponds to the nth occurrence of the symbol name in
> kallsyms for the patched object.
> 
> An example of this issue is documented here:
> 	https://github.com/dynup/kpatch/issues/493
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  Documentation/ABI/testing/sysfs-kernel-livepatch |  2 +-
>  kernel/livepatch/core.c                          | 45 ++++++++++++++++++++++--
>  2 files changed, 44 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> index 5bf42a8..dcd36db 100644
> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> @@ -33,7 +33,7 @@ Description:
>  		The object directory contains subdirectories for each function
>  		that is patched within the object.
>  
> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> +What:		/sys/kernel/livepatch/<patch>/<object>/<function.number>

Dash should be here.

Since it is a documentation, could you add few words what this number is? 
I think that the sentence "The number corresponds..." from the changelog 
above would be great.

>  Date:		Nov 2014
>  KernelVersion:	3.19.0
>  Contact:	live-patching@vger.kernel.org
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..6bcf600 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -587,7 +587,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>   * /sys/kernel/livepatch/<patch>
>   * /sys/kernel/livepatch/<patch>/enabled
>   * /sys/kernel/livepatch/<patch>/<object>
> - * /sys/kernel/livepatch/<patch>/<object>/<func>
> + * /sys/kernel/livepatch/<patch>/<object>/<func.number>

And here.

The rest is fine.

Thanks a lot for the patch
Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 10:52           ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-03 10:52 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Mon, 2 Nov 2015, Chris J Arges wrote:

[...]

> +static int klp_get_func_pos_callback(void *data, const char *name,
> +				      struct module *mod, unsigned long addr)
> +{
> +	struct klp_find_arg *args = data;
> +
> +	if ((mod && !args->objname) || (!mod && args->objname))
> +		return 0;
> +
> +	if (strcmp(args->name, name))
> +		return 0;
> +
> +	if (args->objname && strcmp(args->objname, mod->name))
> +		return 0;
> +
> +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> +	if (args->addr == addr)
> +		return 1;
> +
> +	/* if we don't match addr, count instance of named symbol */
> +	args->count++;
> +
> +	return 0;
> +}
> +
> +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> +{
> +	struct klp_find_arg args = {
> +		.objname = obj->name,
> +		.name = func->old_name,
> +		.addr = func->old_addr,
> +		.count = 0,
> +	};
> +
> +	mutex_lock(&module_mutex);
> +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> +	mutex_unlock(&module_mutex);
> +
> +	return args.count;
> +}
> +
>  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  {
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
>  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +				    &obj->kobj, "%s,%d", func->old_name,
> +				    klp_get_func_pos(obj, func));
>  }

There is a problem which I missed before. klp_init_func() is called before 
klp_find_verify_func_addr() in klp_init_object(). This means that 
func->old_addr is either not verified yet or worse it is still 0. This 
means that klp_get_func_pos_callback() never returns 1 and is thus called 
on each symbol. So if you for example patched cmdline_proc_show the 
resulting directory in sysfs would be called cmdline_proc_show,1 because 
addr is never matched. Had old_addr been specified the name would have 
been probably correct, but not for sure.

This should be fixed as well.

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 10:52           ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-03 10:52 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Josh Poimboeuf, Seth Jennings,
	Jiri Kosina, Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Mon, 2 Nov 2015, Chris J Arges wrote:

[...]

> +static int klp_get_func_pos_callback(void *data, const char *name,
> +				      struct module *mod, unsigned long addr)
> +{
> +	struct klp_find_arg *args = data;
> +
> +	if ((mod && !args->objname) || (!mod && args->objname))
> +		return 0;
> +
> +	if (strcmp(args->name, name))
> +		return 0;
> +
> +	if (args->objname && strcmp(args->objname, mod->name))
> +		return 0;
> +
> +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> +	if (args->addr == addr)
> +		return 1;
> +
> +	/* if we don't match addr, count instance of named symbol */
> +	args->count++;
> +
> +	return 0;
> +}
> +
> +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> +{
> +	struct klp_find_arg args = {
> +		.objname = obj->name,
> +		.name = func->old_name,
> +		.addr = func->old_addr,
> +		.count = 0,
> +	};
> +
> +	mutex_lock(&module_mutex);
> +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> +	mutex_unlock(&module_mutex);
> +
> +	return args.count;
> +}
> +
>  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  {
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
>  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +				    &obj->kobj, "%s,%d", func->old_name,
> +				    klp_get_func_pos(obj, func));
>  }

There is a problem which I missed before. klp_init_func() is called before 
klp_find_verify_func_addr() in klp_init_object(). This means that 
func->old_addr is either not verified yet or worse it is still 0. This 
means that klp_get_func_pos_callback() never returns 1 and is thus called 
on each symbol. So if you for example patched cmdline_proc_show the 
resulting directory in sysfs would be called cmdline_proc_show,1 because 
addr is never matched. Had old_addr been specified the name would have 
been probably correct, but not for sure.

This should be fixed as well.

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 12:44             ` Petr Mladek
  0 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-03 12:44 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Josh Poimboeuf,
	Seth Jennings, Jiri Kosina, Vojtech Pavlik, linux-api,
	linux-kernel

On Tue 2015-11-03 11:52:08, Miroslav Benes wrote:
> On Mon, 2 Nov 2015, Chris J Arges wrote:
> 
> [...]
> 
> > +static int klp_get_func_pos_callback(void *data, const char *name,
> > +				      struct module *mod, unsigned long addr)
> > +{
> > +	struct klp_find_arg *args = data;
> > +
> > +	if ((mod && !args->objname) || (!mod && args->objname))
> > +		return 0;
> > +
> > +	if (strcmp(args->name, name))
> > +		return 0;
> > +
> > +	if (args->objname && strcmp(args->objname, mod->name))
> > +		return 0;
> > +
> > +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> > +	if (args->addr == addr)
> > +		return 1;
> > +
> > +	/* if we don't match addr, count instance of named symbol */
> > +	args->count++;
> > +
> > +	return 0;
> > +}
> > +
> > +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> > +{
> > +	struct klp_find_arg args = {
> > +		.objname = obj->name,
> > +		.name = func->old_name,
> > +		.addr = func->old_addr,
> > +		.count = 0,
> > +	};
> > +
> > +	mutex_lock(&module_mutex);
> > +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> > +	mutex_unlock(&module_mutex);
> > +
> > +	return args.count;
> > +}
> > +
> >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> >  {
> >  	INIT_LIST_HEAD(&func->stack_node);
> >  	func->state = KLP_DISABLED;
> >  
> >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > -				    &obj->kobj, "%s", func->old_name);
> > +				    &obj->kobj, "%s,%d", func->old_name,
> > +				    klp_get_func_pos(obj, func));
> >  }
> 
> There is a problem which I missed before. klp_init_func() is called before 
> klp_find_verify_func_addr() in klp_init_object(). This means that 
> func->old_addr is either not verified yet or worse it is still 0. This 
> means that klp_get_func_pos_callback() never returns 1 and is thus called 
> on each symbol. So if you for example patched cmdline_proc_show the 
> resulting directory in sysfs would be called cmdline_proc_show,1 because 
> addr is never matched. Had old_addr been specified the name would have 
> been probably correct, but not for sure.

This might happen when the function name is unique. Then we might but
we do not need to pre-define the address in the patch.

Also I would omit the suffix at all when it is the first occurrence.
It will cause that unique symbols will not be numbered.

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 12:44             ` Petr Mladek
  0 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-03 12:44 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Josh Poimboeuf, Seth Jennings,
	Jiri Kosina, Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue 2015-11-03 11:52:08, Miroslav Benes wrote:
> On Mon, 2 Nov 2015, Chris J Arges wrote:
> 
> [...]
> 
> > +static int klp_get_func_pos_callback(void *data, const char *name,
> > +				      struct module *mod, unsigned long addr)
> > +{
> > +	struct klp_find_arg *args = data;
> > +
> > +	if ((mod && !args->objname) || (!mod && args->objname))
> > +		return 0;
> > +
> > +	if (strcmp(args->name, name))
> > +		return 0;
> > +
> > +	if (args->objname && strcmp(args->objname, mod->name))
> > +		return 0;
> > +
> > +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> > +	if (args->addr == addr)
> > +		return 1;
> > +
> > +	/* if we don't match addr, count instance of named symbol */
> > +	args->count++;
> > +
> > +	return 0;
> > +}
> > +
> > +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> > +{
> > +	struct klp_find_arg args = {
> > +		.objname = obj->name,
> > +		.name = func->old_name,
> > +		.addr = func->old_addr,
> > +		.count = 0,
> > +	};
> > +
> > +	mutex_lock(&module_mutex);
> > +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> > +	mutex_unlock(&module_mutex);
> > +
> > +	return args.count;
> > +}
> > +
> >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> >  {
> >  	INIT_LIST_HEAD(&func->stack_node);
> >  	func->state = KLP_DISABLED;
> >  
> >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > -				    &obj->kobj, "%s", func->old_name);
> > +				    &obj->kobj, "%s,%d", func->old_name,
> > +				    klp_get_func_pos(obj, func));
> >  }
> 
> There is a problem which I missed before. klp_init_func() is called before 
> klp_find_verify_func_addr() in klp_init_object(). This means that 
> func->old_addr is either not verified yet or worse it is still 0. This 
> means that klp_get_func_pos_callback() never returns 1 and is thus called 
> on each symbol. So if you for example patched cmdline_proc_show the 
> resulting directory in sysfs would be called cmdline_proc_show,1 because 
> addr is never matched. Had old_addr been specified the name would have 
> been probably correct, but not for sure.

This might happen when the function name is unique. Then we might but
we do not need to pre-define the address in the patch.

Also I would omit the suffix at all when it is the first occurrence.
It will cause that unique symbols will not be numbered.

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-03 10:52           ` Miroslav Benes
  (?)
  (?)
@ 2015-11-03 14:58           ` Josh Poimboeuf
  2015-11-03 16:09             ` Miroslav Benes
  -1 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 14:58 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
> On Mon, 2 Nov 2015, Chris J Arges wrote:
> 
> [...]
> 
> > +static int klp_get_func_pos_callback(void *data, const char *name,
> > +				      struct module *mod, unsigned long addr)
> > +{
> > +	struct klp_find_arg *args = data;
> > +
> > +	if ((mod && !args->objname) || (!mod && args->objname))
> > +		return 0;
> > +
> > +	if (strcmp(args->name, name))
> > +		return 0;
> > +
> > +	if (args->objname && strcmp(args->objname, mod->name))
> > +		return 0;
> > +
> > +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> > +	if (args->addr == addr)
> > +		return 1;
> > +
> > +	/* if we don't match addr, count instance of named symbol */
> > +	args->count++;
> > +
> > +	return 0;
> > +}
> > +
> > +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> > +{
> > +	struct klp_find_arg args = {
> > +		.objname = obj->name,
> > +		.name = func->old_name,
> > +		.addr = func->old_addr,
> > +		.count = 0,
> > +	};
> > +
> > +	mutex_lock(&module_mutex);
> > +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> > +	mutex_unlock(&module_mutex);
> > +
> > +	return args.count;
> > +}
> > +
> >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> >  {
> >  	INIT_LIST_HEAD(&func->stack_node);
> >  	func->state = KLP_DISABLED;
> >  
> >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > -				    &obj->kobj, "%s", func->old_name);
> > +				    &obj->kobj, "%s,%d", func->old_name,
> > +				    klp_get_func_pos(obj, func));
> >  }
> 
> There is a problem which I missed before. klp_init_func() is called before 
> klp_find_verify_func_addr() in klp_init_object(). This means that 
> func->old_addr is either not verified yet or worse it is still 0. This 
> means that klp_get_func_pos_callback() never returns 1 and is thus called 
> on each symbol. So if you for example patched cmdline_proc_show the 
> resulting directory in sysfs would be called cmdline_proc_show,1 because 
> addr is never matched. Had old_addr been specified the name would have 
> been probably correct, but not for sure.
> 
> This should be fixed as well.

Even worse, klp_init_func() can be called even if the object hasn't been
loaded.  In that case there's no way to know what the value of n is, and
therefore no way to reliably create the sysfs entry.

Should we create "func,n" in klp_init_object_loaded() instead of
klp_init_func()?

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 15:03               ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 15:03 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Miroslav Benes, Chris J Arges, live-patching, jeyu,
	Seth Jennings, Jiri Kosina, Vojtech Pavlik, linux-api,
	linux-kernel

On Tue, Nov 03, 2015 at 01:44:41PM +0100, Petr Mladek wrote:
> Also I would omit the suffix at all when it is the first occurrence.
> It will cause that unique symbols will not be numbered.

That would make parsing the entry unnecessarily harder and more
error-prone.  I think it should always have the suffix, so it's
consistent and there are no surprises.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 15:03               ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 15:03 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Miroslav Benes, Chris J Arges,
	live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue, Nov 03, 2015 at 01:44:41PM +0100, Petr Mladek wrote:
> Also I would omit the suffix at all when it is the first occurrence.
> It will cause that unique symbols will not be numbered.

That would make parsing the entry unnecessarily harder and more
error-prone.  I think it should always have the suffix, so it's
consistent and there are no surprises.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-03  9:50         ` Miroslav Benes
@ 2015-11-03 15:03           ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 15:03 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Tue, Nov 03, 2015 at 10:50:05AM +0100, Miroslav Benes wrote:
> On Mon, 2 Nov 2015, Chris J Arges wrote:
> 
> > The following directory structure will allow for cases when the same
> > function name exists in a single object.
> > 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> 
> There is still a period here and in the documentation :)

and in the subject :-)

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-03 14:58           ` [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory Josh Poimboeuf
@ 2015-11-03 16:09             ` Miroslav Benes
  2015-11-03 16:50               ` Josh Poimboeuf
  0 siblings, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-03 16:09 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Tue, 3 Nov 2015, Josh Poimboeuf wrote:

> On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
> > On Mon, 2 Nov 2015, Chris J Arges wrote:
> > 
> > [...]
> > 
> > > +static int klp_get_func_pos_callback(void *data, const char *name,
> > > +				      struct module *mod, unsigned long addr)
> > > +{
> > > +	struct klp_find_arg *args = data;
> > > +
> > > +	if ((mod && !args->objname) || (!mod && args->objname))
> > > +		return 0;
> > > +
> > > +	if (strcmp(args->name, name))
> > > +		return 0;
> > > +
> > > +	if (args->objname && strcmp(args->objname, mod->name))
> > > +		return 0;
> > > +
> > > +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> > > +	if (args->addr == addr)
> > > +		return 1;
> > > +
> > > +	/* if we don't match addr, count instance of named symbol */
> > > +	args->count++;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> > > +{
> > > +	struct klp_find_arg args = {
> > > +		.objname = obj->name,
> > > +		.name = func->old_name,
> > > +		.addr = func->old_addr,
> > > +		.count = 0,
> > > +	};
> > > +
> > > +	mutex_lock(&module_mutex);
> > > +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> > > +	mutex_unlock(&module_mutex);
> > > +
> > > +	return args.count;
> > > +}
> > > +
> > >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> > >  {
> > >  	INIT_LIST_HEAD(&func->stack_node);
> > >  	func->state = KLP_DISABLED;
> > >  
> > >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > > -				    &obj->kobj, "%s", func->old_name);
> > > +				    &obj->kobj, "%s,%d", func->old_name,
> > > +				    klp_get_func_pos(obj, func));
> > >  }
> > 
> > There is a problem which I missed before. klp_init_func() is called before 
> > klp_find_verify_func_addr() in klp_init_object(). This means that 
> > func->old_addr is either not verified yet or worse it is still 0. This 
> > means that klp_get_func_pos_callback() never returns 1 and is thus called 
> > on each symbol. So if you for example patched cmdline_proc_show the 
> > resulting directory in sysfs would be called cmdline_proc_show,1 because 
> > addr is never matched. Had old_addr been specified the name would have 
> > been probably correct, but not for sure.
> > 
> > This should be fixed as well.
> 
> Even worse, klp_init_func() can be called even if the object hasn't been
> loaded.  In that case there's no way to know what the value of n is, and
> therefore no way to reliably create the sysfs entry.

Ah, right.

> Should we create "func,n" in klp_init_object_loaded() instead of
> klp_init_func()?

So that the function entries in sysfs would be created only when the 
object is loaded? Well, why not, but in that case it could easily confuse 
the user. Object entry would be empty for not loaded object. I would not 
dare to propose to remove such object entries. It would make things worse. 
So maybe we could introduce an attribute in sysfs object entry which would 
say if the object is loaded or not. Or something like that. Hm, we can 
easily mess this up :)

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-03 16:09             ` Miroslav Benes
@ 2015-11-03 16:50               ` Josh Poimboeuf
  2015-11-03 20:42                   ` Chris J Arges
  2015-11-04  9:52                   ` Miroslav Benes
  0 siblings, 2 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 16:50 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Tue, Nov 03, 2015 at 05:09:48PM +0100, Miroslav Benes wrote:
> On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> 
> > On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
> > > On Mon, 2 Nov 2015, Chris J Arges wrote:
> > > 
> > > [...]
> > > 
> > > > +static int klp_get_func_pos_callback(void *data, const char *name,
> > > > +				      struct module *mod, unsigned long addr)
> > > > +{
> > > > +	struct klp_find_arg *args = data;
> > > > +
> > > > +	if ((mod && !args->objname) || (!mod && args->objname))
> > > > +		return 0;
> > > > +
> > > > +	if (strcmp(args->name, name))
> > > > +		return 0;
> > > > +
> > > > +	if (args->objname && strcmp(args->objname, mod->name))
> > > > +		return 0;
> > > > +
> > > > +	/* on address match, return 1 to break kallsyms_on_each_symbol loop */
> > > > +	if (args->addr == addr)
> > > > +		return 1;
> > > > +
> > > > +	/* if we don't match addr, count instance of named symbol */
> > > > +	args->count++;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static int klp_get_func_pos(struct klp_object *obj, struct klp_func *func)
> > > > +{
> > > > +	struct klp_find_arg args = {
> > > > +		.objname = obj->name,
> > > > +		.name = func->old_name,
> > > > +		.addr = func->old_addr,
> > > > +		.count = 0,
> > > > +	};
> > > > +
> > > > +	mutex_lock(&module_mutex);
> > > > +	kallsyms_on_each_symbol(klp_get_func_pos_callback, &args);
> > > > +	mutex_unlock(&module_mutex);
> > > > +
> > > > +	return args.count;
> > > > +}
> > > > +
> > > >  static int klp_init_func(struct klp_object *obj, struct klp_func *func)
> > > >  {
> > > >  	INIT_LIST_HEAD(&func->stack_node);
> > > >  	func->state = KLP_DISABLED;
> > > >  
> > > >  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> > > > -				    &obj->kobj, "%s", func->old_name);
> > > > +				    &obj->kobj, "%s,%d", func->old_name,
> > > > +				    klp_get_func_pos(obj, func));
> > > >  }
> > > 
> > > There is a problem which I missed before. klp_init_func() is called before 
> > > klp_find_verify_func_addr() in klp_init_object(). This means that 
> > > func->old_addr is either not verified yet or worse it is still 0. This 
> > > means that klp_get_func_pos_callback() never returns 1 and is thus called 
> > > on each symbol. So if you for example patched cmdline_proc_show the 
> > > resulting directory in sysfs would be called cmdline_proc_show,1 because 
> > > addr is never matched. Had old_addr been specified the name would have 
> > > been probably correct, but not for sure.
> > > 
> > > This should be fixed as well.
> > 
> > Even worse, klp_init_func() can be called even if the object hasn't been
> > loaded.  In that case there's no way to know what the value of n is, and
> > therefore no way to reliably create the sysfs entry.
> 
> Ah, right.
> 
> > Should we create "func,n" in klp_init_object_loaded() instead of
> > klp_init_func()?
> 
> So that the function entries in sysfs would be created only when the 
> object is loaded? Well, why not, but in that case it could easily confuse 
> the user.

Maybe, but I think it would be fine if we document it.  It should only
be relied on by tools, anyway.

> Object entry would be empty for not loaded object. I would not 
> dare to propose to remove such object entries. It would make things worse. 

Why would removing an empty object entry make things worse?

> So maybe we could introduce an attribute in sysfs object entry which would 
> say if the object is loaded or not. Or something like that.

Hm, I'm not sure I see how this would help.

> Hm, we can easily mess this up :)

Agreed 100% :-)

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 19:57               ` Jiri Kosina
  0 siblings, 0 replies; 104+ messages in thread
From: Jiri Kosina @ 2015-11-03 19:57 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Miroslav Benes, Chris J Arges, live-patching, jeyu,
	Josh Poimboeuf, Seth Jennings, Vojtech Pavlik, linux-api,
	linux-kernel

On Tue, 3 Nov 2015, Petr Mladek wrote:

> Also I would omit the suffix at all when it is the first occurrence. It 
> will cause that unique symbols will not be numbered.

That'd mean that the names (including suffixes) are not stable, because a 
particular name that has originally been unique can later be made 
non-unique when module brings in a conflicting name.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 19:57               ` Jiri Kosina
  0 siblings, 0 replies; 104+ messages in thread
From: Jiri Kosina @ 2015-11-03 19:57 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Miroslav Benes, Chris J Arges,
	live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Josh Poimboeuf, Seth Jennings,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue, 3 Nov 2015, Petr Mladek wrote:

> Also I would omit the suffix at all when it is the first occurrence. It 
> will cause that unique symbols will not be numbered.

That'd mean that the names (including suffixes) are not stable, because a 
particular name that has originally been unique can later be made 
non-unique when module brings in a conflicting name.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 20:06                 ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 20:06 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Petr Mladek, Miroslav Benes, Chris J Arges, live-patching, jeyu,
	Seth Jennings, Vojtech Pavlik, linux-api, linux-kernel

On Tue, Nov 03, 2015 at 08:57:24PM +0100, Jiri Kosina wrote:
> On Tue, 3 Nov 2015, Petr Mladek wrote:
> 
> > Also I would omit the suffix at all when it is the first occurrence. It 
> > will cause that unique symbols will not be numbered.
> 
> That'd mean that the names (including suffixes) are not stable, because a 
> particular name that has originally been unique can later be made 
> non-unique when module brings in a conflicting name.

The numbering (and uniqueness) is per-object, so the same symbol name
from another module would live in a separate namespace and wouldn't
create a conflict.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 20:06                 ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-03 20:06 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Petr Mladek, Miroslav Benes, Chris J Arges,
	live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Vojtech Pavlik,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue, Nov 03, 2015 at 08:57:24PM +0100, Jiri Kosina wrote:
> On Tue, 3 Nov 2015, Petr Mladek wrote:
> 
> > Also I would omit the suffix at all when it is the first occurrence. It 
> > will cause that unique symbols will not be numbered.
> 
> That'd mean that the names (including suffixes) are not stable, because a 
> particular name that has originally been unique can later be made 
> non-unique when module brings in a conflicting name.

The numbering (and uniqueness) is per-object, so the same symbol name
from another module would live in a separate namespace and wouldn't
create a conflict.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 20:42                   ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-03 20:42 UTC (permalink / raw)
  To: Josh Poimboeuf, Miroslav Benes
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On 11/03/2015 10:50 AM, Josh Poimboeuf wrote:
> On Tue, Nov 03, 2015 at 05:09:48PM +0100, Miroslav Benes wrote:
>> On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
>> 
>>> On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
>>>> On Mon, 2 Nov 2015, Chris J Arges wrote:
>>>> 
>>>> [...]
>>>> 
>>>>> +static int klp_get_func_pos_callback(void *data, const char
>>>>> *name, +				      struct module *mod, unsigned long addr) +{ 
>>>>> +	struct klp_find_arg *args = data; + +	if ((mod &&
>>>>> !args->objname) || (!mod && args->objname)) +		return 0; + +
>>>>> if (strcmp(args->name, name)) +		return 0; + +	if
>>>>> (args->objname && strcmp(args->objname, mod->name)) +		return
>>>>> 0; + +	/* on address match, return 1 to break
>>>>> kallsyms_on_each_symbol loop */ +	if (args->addr == addr) +
>>>>> return 1; + +	/* if we don't match addr, count instance of
>>>>> named symbol */ +	args->count++; + +	return 0; +} + +static
>>>>> int klp_get_func_pos(struct klp_object *obj, struct klp_func
>>>>> *func) +{ +	struct klp_find_arg args = { +		.objname =
>>>>> obj->name, +		.name = func->old_name, +		.addr =
>>>>> func->old_addr, +		.count = 0, +	}; + +
>>>>> mutex_lock(&module_mutex); +
>>>>> kallsyms_on_each_symbol(klp_get_func_pos_callback, &args); +
>>>>> mutex_unlock(&module_mutex); + +	return args.count; +} + 
>>>>> static int klp_init_func(struct klp_object *obj, struct
>>>>> klp_func *func) { INIT_LIST_HEAD(&func->stack_node); 
>>>>> func->state = KLP_DISABLED;
>>>>> 
>>>>> return kobject_init_and_add(&func->kobj, &klp_ktype_func, -
>>>>> &obj->kobj, "%s", func->old_name); +				    &obj->kobj,
>>>>> "%s,%d", func->old_name, +				    klp_get_func_pos(obj,
>>>>> func)); }
>>>> 
>>>> There is a problem which I missed before. klp_init_func() is
>>>> called before klp_find_verify_func_addr() in klp_init_object().
>>>> This means that func->old_addr is either not verified yet or
>>>> worse it is still 0. This means that
>>>> klp_get_func_pos_callback() never returns 1 and is thus called
>>>>  on each symbol. So if you for example patched
>>>> cmdline_proc_show the resulting directory in sysfs would be
>>>> called cmdline_proc_show,1 because addr is never matched. Had
>>>> old_addr been specified the name would have been probably
>>>> correct, but not for sure.
>>>> 
>>>> This should be fixed as well.
>>> 
>>> Even worse, klp_init_func() can be called even if the object
>>> hasn't been loaded.  In that case there's no way to know what the
>>> value of n is, and therefore no way to reliably create the sysfs
>>> entry.
>> 
>> Ah, right.
>> 
>>> Should we create "func,n" in klp_init_object_loaded() instead of 
>>> klp_init_func()?
>> 
>> So that the function entries in sysfs would be created only when
>> the object is loaded? Well, why not, but in that case it could
>> easily confuse the user.
> 
> Maybe, but I think it would be fine if we document it.  It should
> only be relied on by tools, anyway.
> 
>> Object entry would be empty for not loaded object. I would not dare
>> to propose to remove such object entries. It would make things
>> worse.
> 
> Why would removing an empty object entry make things worse?
> 
>> So maybe we could introduce an attribute in sysfs object entry
>> which would say if the object is loaded or not. Or something like
>> that.
> 
> Hm, I'm not sure I see how this would help.
> 
>> Hm, we can easily mess this up :)
> 
> Agreed 100% :-)
> 

Working on v3 with these suggestions.
- Documentation fixes
- create func,n in klp_init_object_loaded

I'll test unique and non-unique functions being patched. In addition
I'll test this when the object is vmlinux or a module (to test the
object being loaded later).

--chris

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-03 20:42                   ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-03 20:42 UTC (permalink / raw)
  To: Josh Poimboeuf, Miroslav Benes
  Cc: live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 11/03/2015 10:50 AM, Josh Poimboeuf wrote:
> On Tue, Nov 03, 2015 at 05:09:48PM +0100, Miroslav Benes wrote:
>> On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
>> 
>>> On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
>>>> On Mon, 2 Nov 2015, Chris J Arges wrote:
>>>> 
>>>> [...]
>>>> 
>>>>> +static int klp_get_func_pos_callback(void *data, const char
>>>>> *name, +				      struct module *mod, unsigned long addr) +{ 
>>>>> +	struct klp_find_arg *args = data; + +	if ((mod &&
>>>>> !args->objname) || (!mod && args->objname)) +		return 0; + +
>>>>> if (strcmp(args->name, name)) +		return 0; + +	if
>>>>> (args->objname && strcmp(args->objname, mod->name)) +		return
>>>>> 0; + +	/* on address match, return 1 to break
>>>>> kallsyms_on_each_symbol loop */ +	if (args->addr == addr) +
>>>>> return 1; + +	/* if we don't match addr, count instance of
>>>>> named symbol */ +	args->count++; + +	return 0; +} + +static
>>>>> int klp_get_func_pos(struct klp_object *obj, struct klp_func
>>>>> *func) +{ +	struct klp_find_arg args = { +		.objname =
>>>>> obj->name, +		.name = func->old_name, +		.addr =
>>>>> func->old_addr, +		.count = 0, +	}; + +
>>>>> mutex_lock(&module_mutex); +
>>>>> kallsyms_on_each_symbol(klp_get_func_pos_callback, &args); +
>>>>> mutex_unlock(&module_mutex); + +	return args.count; +} + 
>>>>> static int klp_init_func(struct klp_object *obj, struct
>>>>> klp_func *func) { INIT_LIST_HEAD(&func->stack_node); 
>>>>> func->state = KLP_DISABLED;
>>>>> 
>>>>> return kobject_init_and_add(&func->kobj, &klp_ktype_func, -
>>>>> &obj->kobj, "%s", func->old_name); +				    &obj->kobj,
>>>>> "%s,%d", func->old_name, +				    klp_get_func_pos(obj,
>>>>> func)); }
>>>> 
>>>> There is a problem which I missed before. klp_init_func() is
>>>> called before klp_find_verify_func_addr() in klp_init_object().
>>>> This means that func->old_addr is either not verified yet or
>>>> worse it is still 0. This means that
>>>> klp_get_func_pos_callback() never returns 1 and is thus called
>>>>  on each symbol. So if you for example patched
>>>> cmdline_proc_show the resulting directory in sysfs would be
>>>> called cmdline_proc_show,1 because addr is never matched. Had
>>>> old_addr been specified the name would have been probably
>>>> correct, but not for sure.
>>>> 
>>>> This should be fixed as well.
>>> 
>>> Even worse, klp_init_func() can be called even if the object
>>> hasn't been loaded.  In that case there's no way to know what the
>>> value of n is, and therefore no way to reliably create the sysfs
>>> entry.
>> 
>> Ah, right.
>> 
>>> Should we create "func,n" in klp_init_object_loaded() instead of 
>>> klp_init_func()?
>> 
>> So that the function entries in sysfs would be created only when
>> the object is loaded? Well, why not, but in that case it could
>> easily confuse the user.
> 
> Maybe, but I think it would be fine if we document it.  It should
> only be relied on by tools, anyway.
> 
>> Object entry would be empty for not loaded object. I would not dare
>> to propose to remove such object entries. It would make things
>> worse.
> 
> Why would removing an empty object entry make things worse?
> 
>> So maybe we could introduce an attribute in sysfs object entry
>> which would say if the object is loaded or not. Or something like
>> that.
> 
> Hm, I'm not sure I see how this would help.
> 
>> Hm, we can easily mess this up :)
> 
> Agreed 100% :-)
> 

Working on v3 with these suggestions.
- Documentation fixes
- create func,n in klp_init_object_loaded

I'll test unique and non-unique functions being patched. In addition
I'll test this when the object is vmlinux or a module (to test the
object being loaded later).

--chris

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-04  9:52                   ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-04  9:52 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Tue, 3 Nov 2015, Josh Poimboeuf wrote:

> On Tue, Nov 03, 2015 at 05:09:48PM +0100, Miroslav Benes wrote:
> > On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> > 
> > > On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
> > > > 
> > > > There is a problem which I missed before. klp_init_func() is called before 
> > > > klp_find_verify_func_addr() in klp_init_object(). This means that 
> > > > func->old_addr is either not verified yet or worse it is still 0. This 
> > > > means that klp_get_func_pos_callback() never returns 1 and is thus called 
> > > > on each symbol. So if you for example patched cmdline_proc_show the 
> > > > resulting directory in sysfs would be called cmdline_proc_show,1 because 
> > > > addr is never matched. Had old_addr been specified the name would have 
> > > > been probably correct, but not for sure.
> > > > 
> > > > This should be fixed as well.
> > > 
> > > Even worse, klp_init_func() can be called even if the object hasn't been
> > > loaded.  In that case there's no way to know what the value of n is, and
> > > therefore no way to reliably create the sysfs entry.
> > 
> > Ah, right.
> > 
> > > Should we create "func,n" in klp_init_object_loaded() instead of
> > > klp_init_func()?
> > 
> > So that the function entries in sysfs would be created only when the 
> > object is loaded? Well, why not, but in that case it could easily confuse 
> > the user.
> 
> Maybe, but I think it would be fine if we document it.  It should only
> be relied on by tools, anyway.

Agreed.

> > Object entry would be empty for not loaded object. I would not 
> > dare to propose to remove such object entries. It would make things worse. 
> 
> Why would removing an empty object entry make things worse?

I think it all comes down to a question whether the sysfs entries say what 
a patch is capable to patch or what this patch is currently patching in 
the system. I am inclined to the former so the removal would make me 
nervous. But I am not against the second approach. We are still in testing 
mode as far as sysfs is concerned so we can try even harsh changes and see 
how it's gonna go.

> > So maybe we could introduce an attribute in sysfs object entry which would 
> > say if the object is loaded or not. Or something like that.
> 
> Hm, I'm not sure I see how this would help.

Hopefully I cleared this up with the above.

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-04  9:52                   ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-04  9:52 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue, 3 Nov 2015, Josh Poimboeuf wrote:

> On Tue, Nov 03, 2015 at 05:09:48PM +0100, Miroslav Benes wrote:
> > On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> > 
> > > On Tue, Nov 03, 2015 at 11:52:08AM +0100, Miroslav Benes wrote:
> > > > 
> > > > There is a problem which I missed before. klp_init_func() is called before 
> > > > klp_find_verify_func_addr() in klp_init_object(). This means that 
> > > > func->old_addr is either not verified yet or worse it is still 0. This 
> > > > means that klp_get_func_pos_callback() never returns 1 and is thus called 
> > > > on each symbol. So if you for example patched cmdline_proc_show the 
> > > > resulting directory in sysfs would be called cmdline_proc_show,1 because 
> > > > addr is never matched. Had old_addr been specified the name would have 
> > > > been probably correct, but not for sure.
> > > > 
> > > > This should be fixed as well.
> > > 
> > > Even worse, klp_init_func() can be called even if the object hasn't been
> > > loaded.  In that case there's no way to know what the value of n is, and
> > > therefore no way to reliably create the sysfs entry.
> > 
> > Ah, right.
> > 
> > > Should we create "func,n" in klp_init_object_loaded() instead of
> > > klp_init_func()?
> > 
> > So that the function entries in sysfs would be created only when the 
> > object is loaded? Well, why not, but in that case it could easily confuse 
> > the user.
> 
> Maybe, but I think it would be fine if we document it.  It should only
> be relied on by tools, anyway.

Agreed.

> > Object entry would be empty for not loaded object. I would not 
> > dare to propose to remove such object entries. It would make things worse. 
> 
> Why would removing an empty object entry make things worse?

I think it all comes down to a question whether the sysfs entries say what 
a patch is capable to patch or what this patch is currently patching in 
the system. I am inclined to the former so the removal would make me 
nervous. But I am not against the second approach. We are still in testing 
mode as far as sysfs is concerned so we can try even harsh changes and see 
how it's gonna go.

> > So maybe we could introduce an attribute in sysfs object entry which would 
> > say if the object is loaded or not. Or something like that.
> 
> Hm, I'm not sure I see how this would help.

Hopefully I cleared this up with the above.

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-04  9:52                   ` Miroslav Benes
  (?)
@ 2015-11-04 16:03                   ` Josh Poimboeuf
  2015-11-04 16:17                       ` Chris J Arges
  2015-11-05 15:18                     ` Miroslav Benes
  -1 siblings, 2 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-04 16:03 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Wed, Nov 04, 2015 at 10:52:52AM +0100, Miroslav Benes wrote:
> On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> > > Object entry would be empty for not loaded object. I would not 
> > > dare to propose to remove such object entries. It would make things worse. 
> > 
> > Why would removing an empty object entry make things worse?
> 
> I think it all comes down to a question whether the sysfs entries say what 
> a patch is capable to patch or what this patch is currently patching in 
> the system. I am inclined to the former so the removal would make me 
> nervous. But I am not against the second approach. We are still in testing 
> mode as far as sysfs is concerned so we can try even harsh changes and see 
> how it's gonna go.

I see your point.  This approach only describes what is patched now, but
it doesn't describe what *will* be patched.  Ideally we could find a way
to describe both.

Speaking of harsh changes, here's an idea.

What if we require the patch author to supply the value of 'n' instead
of supplying the symbol address?  We could get rid of 'old_addr' as an
input in klp_func and and replace it with 'old_sympos' which has the
value of 'n'.  Or alternatively we could require old_name to be of the
format "func,n".

That would uniquely identify each patched function, even _before_ the
object is loaded.

It would also fix another big problem we have today, where there's no
way to disambiguate duplicate symbols in modules, for both function
addresses and for relocs.

It would simplify the code in other places as well: no special handling
for kASLR, no need for klp_verify_vmlinux_symbol() vs
klp_find_object_symbol().

A drawback is that it requires the patch author to do a little more due
diligence when filling out klp_func.  But we already require them to be
careful.

Thoughts?

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-04 16:17                       ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-04 16:17 UTC (permalink / raw)
  To: Josh Poimboeuf, Miroslav Benes
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel



On 11/04/2015 10:03 AM, Josh Poimboeuf wrote:
> On Wed, Nov 04, 2015 at 10:52:52AM +0100, Miroslav Benes wrote:
>> On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
>>>> Object entry would be empty for not loaded object. I would not 
>>>> dare to propose to remove such object entries. It would make things worse. 
>>>
>>> Why would removing an empty object entry make things worse?
>>
>> I think it all comes down to a question whether the sysfs entries say what 
>> a patch is capable to patch or what this patch is currently patching in 
>> the system. I am inclined to the former so the removal would make me 
>> nervous. But I am not against the second approach. We are still in testing 
>> mode as far as sysfs is concerned so we can try even harsh changes and see 
>> how it's gonna go.
> 
> I see your point.  This approach only describes what is patched now, but
> it doesn't describe what *will* be patched.  Ideally we could find a way
> to describe both.
> 
> Speaking of harsh changes, here's an idea.
> 
> What if we require the patch author to supply the value of 'n' instead
> of supplying the symbol address?  We could get rid of 'old_addr' as an
> input in klp_func and and replace it with 'old_sympos' which has the
> value of 'n'.  Or alternatively we could require old_name to be of the
> format "func,n".

I like the idea of old_sympos better than modifying the string.
In addition if no old_sympos is specified then it should default to 0,
since this will probably be the more common case.

> 
> That would uniquely identify each patched function, even _before_ the
> object is loaded.
> 
> It would also fix another big problem we have today, where there's no
> way to disambiguate duplicate symbols in modules, for both function
> addresses and for relocs.
> 
> It would simplify the code in other places as well: no special handling
> for kASLR, no need for klp_verify_vmlinux_symbol() vs
> klp_find_object_symbol().
> 
> A drawback is that it requires the patch author to do a little more due
> diligence when filling out klp_func.  But we already require them to be
> careful.
> 
> Thoughts?
> 

I'll hold off on my v3 for now. Very interesting discussion : ).
--chris


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
@ 2015-11-04 16:17                       ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-04 16:17 UTC (permalink / raw)
  To: Josh Poimboeuf, Miroslav Benes
  Cc: live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA



On 11/04/2015 10:03 AM, Josh Poimboeuf wrote:
> On Wed, Nov 04, 2015 at 10:52:52AM +0100, Miroslav Benes wrote:
>> On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
>>>> Object entry would be empty for not loaded object. I would not 
>>>> dare to propose to remove such object entries. It would make things worse. 
>>>
>>> Why would removing an empty object entry make things worse?
>>
>> I think it all comes down to a question whether the sysfs entries say what 
>> a patch is capable to patch or what this patch is currently patching in 
>> the system. I am inclined to the former so the removal would make me 
>> nervous. But I am not against the second approach. We are still in testing 
>> mode as far as sysfs is concerned so we can try even harsh changes and see 
>> how it's gonna go.
> 
> I see your point.  This approach only describes what is patched now, but
> it doesn't describe what *will* be patched.  Ideally we could find a way
> to describe both.
> 
> Speaking of harsh changes, here's an idea.
> 
> What if we require the patch author to supply the value of 'n' instead
> of supplying the symbol address?  We could get rid of 'old_addr' as an
> input in klp_func and and replace it with 'old_sympos' which has the
> value of 'n'.  Or alternatively we could require old_name to be of the
> format "func,n".

I like the idea of old_sympos better than modifying the string.
In addition if no old_sympos is specified then it should default to 0,
since this will probably be the more common case.

> 
> That would uniquely identify each patched function, even _before_ the
> object is loaded.
> 
> It would also fix another big problem we have today, where there's no
> way to disambiguate duplicate symbols in modules, for both function
> addresses and for relocs.
> 
> It would simplify the code in other places as well: no special handling
> for kASLR, no need for klp_verify_vmlinux_symbol() vs
> klp_find_object_symbol().
> 
> A drawback is that it requires the patch author to do a little more due
> diligence when filling out klp_func.  But we already require them to be
> careful.
> 
> Thoughts?
> 

I'll hold off on my v3 for now. Very interesting discussion : ).
--chris

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-04 16:03                   ` Josh Poimboeuf
  2015-11-04 16:17                       ` Chris J Arges
@ 2015-11-05 15:18                     ` Miroslav Benes
  2015-11-05 15:56                       ` Josh Poimboeuf
  1 sibling, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-05 15:18 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Wed, 4 Nov 2015, Josh Poimboeuf wrote:

> On Wed, Nov 04, 2015 at 10:52:52AM +0100, Miroslav Benes wrote:
> > On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> > > > Object entry would be empty for not loaded object. I would not 
> > > > dare to propose to remove such object entries. It would make things worse. 
> > > 
> > > Why would removing an empty object entry make things worse?
> > 
> > I think it all comes down to a question whether the sysfs entries say what 
> > a patch is capable to patch or what this patch is currently patching in 
> > the system. I am inclined to the former so the removal would make me 
> > nervous. But I am not against the second approach. We are still in testing 
> > mode as far as sysfs is concerned so we can try even harsh changes and see 
> > how it's gonna go.
> 
> I see your point.  This approach only describes what is patched now, but
> it doesn't describe what *will* be patched.  Ideally we could find a way
> to describe both.
> 
> Speaking of harsh changes, here's an idea.

Which is the very same you proposed last year when I tried to persuade you 
to get rid off old_addr and stuff. I called it crazy I remember :D. So 
here we are again...

> What if we require the patch author to supply the value of 'n' instead
> of supplying the symbol address?  We could get rid of 'old_addr' as an
> input in klp_func and and replace it with 'old_sympos' which has the
> value of 'n'.  Or alternatively we could require old_name to be of the
> format "func,n".
> 
> That would uniquely identify each patched function, even _before_ the
> object is loaded.

I find it reasonable and we should try it. I think that old_sympos should 
have this semantics

0 - default, preserve more or less current behaviour. If the symbol is 
    unique there is no problem. If it is not the patching would fail.
1, 2, ... - occurrence of the symbol in kallsyms.

The advantage is that if the user does not care and is certain that the 
symbol is unique he doesn't have to do anything. If the symbol is not 
unique he still has means how to solve it.

Does it make sense?

> It would also fix another big problem we have today, where there's no
> way to disambiguate duplicate symbols in modules, for both function
> addresses and for relocs.

True.

> It would simplify the code in other places as well: no special handling
> for kASLR, no need for klp_verify_vmlinux_symbol() vs
> klp_find_object_symbol().

Which would be great.

> A drawback is that it requires the patch author to do a little more due
> diligence when filling out klp_func.  But we already require them to be
> careful.

Yes, I don't think this should be a problem.

> Thoughts?

Yup, we should try it. I suppose that the order of the symbols in kallsyms 
table is stable for once-built kernel. It is the order of the symbols in 
the object files, isn't it? And since each livepatch module is built 
against the specific kernel there should be no issues with this.

Regards,
Miroslav


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-05 15:18                     ` Miroslav Benes
@ 2015-11-05 15:56                       ` Josh Poimboeuf
  2015-11-05 16:07                         ` Chris J Arges
  2015-11-09 16:16                           ` Chris J Arges
  0 siblings, 2 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-05 15:56 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Thu, Nov 05, 2015 at 04:18:12PM +0100, Miroslav Benes wrote:
> On Wed, 4 Nov 2015, Josh Poimboeuf wrote:
> 
> > On Wed, Nov 04, 2015 at 10:52:52AM +0100, Miroslav Benes wrote:
> > > On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> > > > > Object entry would be empty for not loaded object. I would not 
> > > > > dare to propose to remove such object entries. It would make things worse. 
> > > > 
> > > > Why would removing an empty object entry make things worse?
> > > 
> > > I think it all comes down to a question whether the sysfs entries say what 
> > > a patch is capable to patch or what this patch is currently patching in 
> > > the system. I am inclined to the former so the removal would make me 
> > > nervous. But I am not against the second approach. We are still in testing 
> > > mode as far as sysfs is concerned so we can try even harsh changes and see 
> > > how it's gonna go.
> > 
> > I see your point.  This approach only describes what is patched now, but
> > it doesn't describe what *will* be patched.  Ideally we could find a way
> > to describe both.
> > 
> > Speaking of harsh changes, here's an idea.
> 
> Which is the very same you proposed last year when I tried to persuade you 
> to get rid off old_addr and stuff. I called it crazy I remember :D. So 
> here we are again...

Ah, I knew I had entertained the idea before, but I forgot we discussed
it.  It is indeed a little crazy.  But this is live patching after all
;-)

> > What if we require the patch author to supply the value of 'n' instead
> > of supplying the symbol address?  We could get rid of 'old_addr' as an
> > input in klp_func and and replace it with 'old_sympos' which has the
> > value of 'n'.  Or alternatively we could require old_name to be of the
> > format "func,n".
> > 
> > That would uniquely identify each patched function, even _before_ the
> > object is loaded.
> 
> I find it reasonable and we should try it. I think that old_sympos should 
> have this semantics
> 
> 0 - default, preserve more or less current behaviour. If the symbol is 
>     unique there is no problem. If it is not the patching would fail.
> 1, 2, ... - occurrence of the symbol in kallsyms.
> 
> The advantage is that if the user does not care and is certain that the 
> symbol is unique he doesn't have to do anything. If the symbol is not 
> unique he still has means how to solve it.
> 
> Does it make sense?

Sounds good!

> > It would also fix another big problem we have today, where there's no
> > way to disambiguate duplicate symbols in modules, for both function
> > addresses and for relocs.
> 
> True.
> 
> > It would simplify the code in other places as well: no special handling
> > for kASLR, no need for klp_verify_vmlinux_symbol() vs
> > klp_find_object_symbol().
> 
> Which would be great.
> 
> > A drawback is that it requires the patch author to do a little more due
> > diligence when filling out klp_func.  But we already require them to be
> > careful.
> 
> Yes, I don't think this should be a problem.
> 
> > Thoughts?
> 
> Yup, we should try it. I suppose that the order of the symbols in kallsyms 
> table is stable for once-built kernel. It is the order of the symbols in 
> the object files, isn't it? And since each livepatch module is built 
> against the specific kernel there should be no issues with this.

The order of the symbols in an object's symbol table does appear to be
the same as the order in kallsyms (per-object).  So yeah, let's try it.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory
  2015-11-05 15:56                       ` Josh Poimboeuf
@ 2015-11-05 16:07                         ` Chris J Arges
  2015-11-09 16:16                           ` Chris J Arges
  1 sibling, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-05 16:07 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Miroslav Benes, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Thu, Nov 05, 2015 at 09:56:56AM -0600, Josh Poimboeuf wrote:
> On Thu, Nov 05, 2015 at 04:18:12PM +0100, Miroslav Benes wrote:
> > On Wed, 4 Nov 2015, Josh Poimboeuf wrote:
> > 
> > > On Wed, Nov 04, 2015 at 10:52:52AM +0100, Miroslav Benes wrote:
> > > > On Tue, 3 Nov 2015, Josh Poimboeuf wrote:
> > > > > > Object entry would be empty for not loaded object. I would not 
> > > > > > dare to propose to remove such object entries. It would make things worse. 
> > > > > 
> > > > > Why would removing an empty object entry make things worse?
> > > > 
> > > > I think it all comes down to a question whether the sysfs entries say what 
> > > > a patch is capable to patch or what this patch is currently patching in 
> > > > the system. I am inclined to the former so the removal would make me 
> > > > nervous. But I am not against the second approach. We are still in testing 
> > > > mode as far as sysfs is concerned so we can try even harsh changes and see 
> > > > how it's gonna go.
> > > 
> > > I see your point.  This approach only describes what is patched now, but
> > > it doesn't describe what *will* be patched.  Ideally we could find a way
> > > to describe both.
> > > 
> > > Speaking of harsh changes, here's an idea.
> > 
> > Which is the very same you proposed last year when I tried to persuade you 
> > to get rid off old_addr and stuff. I called it crazy I remember :D. So 
> > here we are again...
> 
> Ah, I knew I had entertained the idea before, but I forgot we discussed
> it.  It is indeed a little crazy.  But this is live patching after all
> ;-)
> 
> > > What if we require the patch author to supply the value of 'n' instead
> > > of supplying the symbol address?  We could get rid of 'old_addr' as an
> > > input in klp_func and and replace it with 'old_sympos' which has the
> > > value of 'n'.  Or alternatively we could require old_name to be of the
> > > format "func,n".
> > > 
> > > That would uniquely identify each patched function, even _before_ the
> > > object is loaded.
> > 
> > I find it reasonable and we should try it. I think that old_sympos should 
> > have this semantics
> > 
> > 0 - default, preserve more or less current behaviour. If the symbol is 
> >     unique there is no problem. If it is not the patching would fail.
> > 1, 2, ... - occurrence of the symbol in kallsyms.
> > 
> > The advantage is that if the user does not care and is certain that the 
> > symbol is unique he doesn't have to do anything. If the symbol is not 
> > unique he still has means how to solve it.
> > 
> > Does it make sense?
> 
> Sounds good!
> 
> > > It would also fix another big problem we have today, where there's no
> > > way to disambiguate duplicate symbols in modules, for both function
> > > addresses and for relocs.
> > 
> > True.
> > 
> > > It would simplify the code in other places as well: no special handling
> > > for kASLR, no need for klp_verify_vmlinux_symbol() vs
> > > klp_find_object_symbol().
> > 
> > Which would be great.
> > 
> > > A drawback is that it requires the patch author to do a little more due
> > > diligence when filling out klp_func.  But we already require them to be
> > > careful.
> > 
> > Yes, I don't think this should be a problem.
> > 
> > > Thoughts?
> > 
> > Yup, we should try it. I suppose that the order of the symbols in kallsyms 
> > table is stable for once-built kernel. It is the order of the symbols in 
> > the object files, isn't it? And since each livepatch module is built 
> > against the specific kernel there should be no issues with this.
> 
> The order of the symbols in an object's symbol table does appear to be
> the same as the order in kallsyms (per-object).  So yeah, let's try it.
> 
> -- 
> Josh
>

Great! Using this feedback to create the next patch. I'll post something in the
next few days.

--chris
 

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-09 16:16                           ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-09 16:16 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

In cases of duplicate symbols in vmlinux, old_sympos will be used to
disambiguate instead of old_addr. Normally old_sympos will be 0, and
default to only returning the first found instance of that symbol. If an
incorrect symbol position is specified then livepatching will fail.
Finally, old_addr is now an internal structure element and not to be
specified by the user.

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function.number>

The number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 ++-
 include/linux/livepatch.h                        | 20 ++++---
 kernel/livepatch/core.c                          | 66 ++++++++++++++++--------
 3 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..21b6bc1 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		number corresponding to the nth occurrence of the symbol name
+		in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..986e06d 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
+ * @old_sympos: a hint indicating which symbol position the old function
  *		can be found (optional, vmlinux patches only)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -47,17 +48,20 @@ struct klp_func {
 	/* external */
 	const char *old_name;
 	void *new_func;
+
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve duplicate
+	 * symbol names in the vmlinux object.  If this information is not
+	 * present, the first symbol located with kallsyms is used. This value
+	 * corresponds to the nth occurrence of the symbol name in kallsyms for
+	 * the patched object. If the name is not unique and old_sympos is not
+	 * provided, the patch application fails as there is no way to resolve
+	 * the ambiguity.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..1dd0d44 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -142,6 +142,7 @@ struct klp_find_arg {
 	 * name in the same object.
 	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -166,28 +167,39 @@ static int klp_find_callback(void *data, const char *name,
 	args->addr = addr;
 	args->count++;
 
+	/*
+	 * ensure count matches the symbol position
+	 */
+	if (args->pos == (args->count-1))
+		return 1;
+
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long *addr, unsigned long sympos)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found, then check that the symbol position
+	 * count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
-		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
-		       args.count, name, objname);
+	else if (sympos != (args.count - 1))
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
 	else {
 		*addr = args.addr;
 		return 0;
@@ -239,20 +251,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 static int klp_find_verify_func_addr(struct klp_object *obj,
 				     struct klp_func *func)
 {
+	int sympos = 0;
 	int ret;
 
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
+	if (func->old_sympos && !klp_is_module(obj))
+		sympos = func->old_sympos;
 
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
+	/*
+	 * Verify the symbol, find old_addr, and write it to the structure.
+	 * By default sympos will be 0 and thus will only look for the first
+	 * occurrence. If another value is specified then that will be used.
+	 */
+	ret = klp_find_object_symbol(obj->name, func->old_name,
+				     &func->old_addr, sympos);
 
 	return ret;
 }
@@ -277,7 +288,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	preempt_enable();
 
 	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	return klp_find_object_symbol(pmod->name, name, addr, 0);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     &reloc->val, 0);
 			if (ret)
 				return ret;
 		}
@@ -587,7 +598,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func,number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -732,8 +743,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
-	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+	return 0;
 }
 
 /* parts of the initialization that is done only when the object is loaded */
@@ -755,6 +765,18 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 			return ret;
 	}
 
+	/*
+	 * for each function initialize and add, old_sympos will be already
+	 * verified at this point
+	 */
+	klp_for_each_func(obj, func) {
+		ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 0);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-09 16:16                           ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-09 16:16 UTC (permalink / raw)
  To: live-patching-u79uwXL29TY76Z2rM5mHXA
  Cc: jeyu-H+wXaHxf7aLQT0dZR+AlfA, Chris J Arges, Josh Poimboeuf,
	Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

In cases of duplicate symbols in vmlinux, old_sympos will be used to
disambiguate instead of old_addr. Normally old_sympos will be 0, and
default to only returning the first found instance of that symbol. If an
incorrect symbol position is specified then livepatching will fail.
Finally, old_addr is now an internal structure element and not to be
specified by the user.

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function.number>

The number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 ++-
 include/linux/livepatch.h                        | 20 ++++---
 kernel/livepatch/core.c                          | 66 ++++++++++++++++--------
 3 files changed, 61 insertions(+), 31 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..21b6bc1 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		number corresponding to the nth occurrence of the symbol name
+		in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..986e06d 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
+ * @old_sympos: a hint indicating which symbol position the old function
  *		can be found (optional, vmlinux patches only)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -47,17 +48,20 @@ struct klp_func {
 	/* external */
 	const char *old_name;
 	void *new_func;
+
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve duplicate
+	 * symbol names in the vmlinux object.  If this information is not
+	 * present, the first symbol located with kallsyms is used. This value
+	 * corresponds to the nth occurrence of the symbol name in kallsyms for
+	 * the patched object. If the name is not unique and old_sympos is not
+	 * provided, the patch application fails as there is no way to resolve
+	 * the ambiguity.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..1dd0d44 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -142,6 +142,7 @@ struct klp_find_arg {
 	 * name in the same object.
 	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -166,28 +167,39 @@ static int klp_find_callback(void *data, const char *name,
 	args->addr = addr;
 	args->count++;
 
+	/*
+	 * ensure count matches the symbol position
+	 */
+	if (args->pos == (args->count-1))
+		return 1;
+
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long *addr, unsigned long sympos)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found, then check that the symbol position
+	 * count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
-		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
-		       args.count, name, objname);
+	else if (sympos != (args.count - 1))
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
 	else {
 		*addr = args.addr;
 		return 0;
@@ -239,20 +251,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 static int klp_find_verify_func_addr(struct klp_object *obj,
 				     struct klp_func *func)
 {
+	int sympos = 0;
 	int ret;
 
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
+	if (func->old_sympos && !klp_is_module(obj))
+		sympos = func->old_sympos;
 
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
+	/*
+	 * Verify the symbol, find old_addr, and write it to the structure.
+	 * By default sympos will be 0 and thus will only look for the first
+	 * occurrence. If another value is specified then that will be used.
+	 */
+	ret = klp_find_object_symbol(obj->name, func->old_name,
+				     &func->old_addr, sympos);
 
 	return ret;
 }
@@ -277,7 +288,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	preempt_enable();
 
 	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	return klp_find_object_symbol(pmod->name, name, addr, 0);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     &reloc->val, 0);
 			if (ret)
 				return ret;
 		}
@@ -587,7 +598,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func,number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -732,8 +743,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
-	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+	return 0;
 }
 
 /* parts of the initialization that is done only when the object is loaded */
@@ -755,6 +765,18 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 			return ret;
 	}
 
+	/*
+	 * for each function initialize and add, old_sympos will be already
+	 * verified at this point
+	 */
+	klp_for_each_func(obj, func) {
+		ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 0);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
  2015-11-09 16:16                           ` Chris J Arges
  (?)
@ 2015-11-09 20:56                           ` Josh Poimboeuf
  2015-11-09 23:01                               ` Chris J Arges
  -1 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-09 20:56 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

I'd recommend splitting this up into two separate patches:

1. introduce old_sympos
2. change the sysfs interface

On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
> In cases of duplicate symbols in vmlinux, old_sympos will be used to
> disambiguate instead of old_addr. Normally old_sympos will be 0, and
> default to only returning the first found instance of that symbol. If an
> incorrect symbol position is specified then livepatching will fail.

In the case of old_sympos == 0, instead of just returning the first
symbol it finds, I think it should ensure that the symbol is unique.  As
Miroslav suggested:

  0 - default, preserve more or less current behaviour. If the symbol is 
      unique there is no problem. If it is not the patching would fail.
  1, 2, ... - occurrence of the symbol in kallsyms.
  
  The advantage is that if the user does not care and is certain that the 
  symbol is unique he doesn't have to do anything. If the symbol is not 
  unique he still has means how to solve it.

> Finally, old_addr is now an internal structure element and not to be
> specified by the user.
> 
> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function.number>

Period should be changed to a comma.

> The number corresponds to the nth occurrence of the symbol name in
> kallsyms for the patched object.
> 
> An example of patching multiple symbols can be found here:
> 	https://github.com/dynup/kpatch/issues/493
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  Documentation/ABI/testing/sysfs-kernel-livepatch |  6 ++-
>  include/linux/livepatch.h                        | 20 ++++---
>  kernel/livepatch/core.c                          | 66 ++++++++++++++++--------
>  3 files changed, 61 insertions(+), 31 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> index 5bf42a8..21b6bc1 100644
> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> @@ -33,7 +33,7 @@ Description:
>  		The object directory contains subdirectories for each function
>  		that is patched within the object.
>  
> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> +What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
>  Date:		Nov 2014
>  KernelVersion:	3.19.0
>  Contact:	live-patching@vger.kernel.org
> @@ -41,4 +41,8 @@ Description:
>  		The function directory contains attributes regarding the
>  		properties and state of the patched function.
>  
> +		The directory name contains the patched function name and a
> +		number corresponding to the nth occurrence of the symbol name
> +		in kallsyms for the patched object.
> +
>  		There are currently no such attributes.
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 31db7a0..986e06d 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -37,8 +37,9 @@ enum klp_state {
>   * 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_addr:	a hint conveying at what address the old function
> + * @old_sympos: a hint indicating which symbol position the old function
>   *		can be found (optional, vmlinux patches only)

Why is old_sympos only checked for vmlinux patches only?  It's a
per-object count, so it should work for modules as well.

> + * @old_addr:	the address of the function being patched
>   * @kobj:	kobject for sysfs resources
>   * @state:	tracks function-level patch application state
>   * @stack_node:	list node for klp_ops func_stack list
> @@ -47,17 +48,20 @@ struct klp_func {
>  	/* external */
>  	const char *old_name;
>  	void *new_func;
> +
>  	/*
> -	 * The old_addr field is optional and can be used to resolve
> -	 * duplicate symbol names in the vmlinux object.  If this
> -	 * information is not present, the symbol is located by name
> -	 * with kallsyms. If the name is not unique and old_addr is
> -	 * not provided, the patch application fails as there is no
> -	 * way to resolve the ambiguity.
> +	 * The old_sympos field is optional and can be used to resolve duplicate
> +	 * symbol names in the vmlinux object.  If this information is not
> +	 * present, the first symbol located with kallsyms is used. This value
> +	 * corresponds to the nth occurrence of the symbol name in kallsyms for
> +	 * the patched object. If the name is not unique and old_sympos is not
> +	 * provided, the patch application fails as there is no way to resolve
> +	 * the ambiguity.
>  	 */
> -	unsigned long old_addr;
> +	unsigned long old_sympos;
>  
>  	/* internal */
> +	unsigned long old_addr;
>  	struct kobject kobj;
>  	enum klp_state state;
>  	struct list_head stack_node;
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..1dd0d44 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -142,6 +142,7 @@ struct klp_find_arg {
>  	 * name in the same object.
>  	 */
>  	unsigned long count;
> +	unsigned long pos;
>  };
>  
>  static int klp_find_callback(void *data, const char *name,
> @@ -166,28 +167,39 @@ static int klp_find_callback(void *data, const char *name,
>  	args->addr = addr;
>  	args->count++;
>  
> +	/*
> +	 * ensure count matches the symbol position
> +	 */
> +	if (args->pos == (args->count-1))
> +		return 1;
> +

The code can be simplified a bit if args->addr only gets set when
args->pos is a match.  Then klp_find_object_symbol() only needs to check
args.addr to see if a match was found.

>  	return 0;
>  }
>  
>  static int klp_find_object_symbol(const char *objname, const char *name,
> -				  unsigned long *addr)
> +				  unsigned long *addr, unsigned long sympos)
>  {
>  	struct klp_find_arg args = {
>  		.objname = objname,
>  		.name = name,
>  		.addr = 0,
> -		.count = 0
> +		.count = 0,
> +		.pos = sympos,
>  	};
>  
>  	mutex_lock(&module_mutex);
>  	kallsyms_on_each_symbol(klp_find_callback, &args);
>  	mutex_unlock(&module_mutex);
>  
> -	if (args.count == 0)
> +	/*
> +	 * Ensure an address was found, then check that the symbol position
> +	 * count matches sympos.
> +	 */
> +	if (args.addr == 0)
>  		pr_err("symbol '%s' not found in symbol table\n", name);
> -	else if (args.count > 1)
> -		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
> -		       args.count, name, objname);
> +	else if (sympos != (args.count - 1))
> +		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
> +		       sympos, name, objname ? objname : "vmlinux");
>  	else {
>  		*addr = args.addr;
>  		return 0;
> @@ -239,20 +251,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
>  static int klp_find_verify_func_addr(struct klp_object *obj,
>  				     struct klp_func *func)
>  {
> +	int sympos = 0;
>  	int ret;
>  
> -#if defined(CONFIG_RANDOMIZE_BASE)
> -	/* If KASLR has been enabled, adjust old_addr accordingly */
> -	if (kaslr_enabled() && func->old_addr)
> -		func->old_addr += kaslr_offset();
> -#endif
> +	if (func->old_sympos && !klp_is_module(obj))
> +		sympos = func->old_sympos;
>  
> -	if (!func->old_addr || klp_is_module(obj))
> -		ret = klp_find_object_symbol(obj->name, func->old_name,
> -					     &func->old_addr);
> -	else
> -		ret = klp_verify_vmlinux_symbol(func->old_name,
> -						func->old_addr);
> +	/*
> +	 * Verify the symbol, find old_addr, and write it to the structure.
> +	 * By default sympos will be 0 and thus will only look for the first
> +	 * occurrence. If another value is specified then that will be used.
> +	 */
> +	ret = klp_find_object_symbol(obj->name, func->old_name,
> +				     &func->old_addr, sympos);
>  
>  	return ret;
>  }
> @@ -277,7 +288,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>  	preempt_enable();
>  
>  	/* otherwise check if it's in another .o within the patch module */
> -	return klp_find_object_symbol(pmod->name, name, addr);
> +	return klp_find_object_symbol(pmod->name, name, addr, 0);
>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> @@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
>  			else
>  				ret = klp_find_object_symbol(obj->mod->name,
>  							     reloc->name,
> -							     &reloc->val);
> +							     &reloc->val, 0);

I think it would be a good idea to also add old_sympos to klp_reloc so
the relocation code is consistent with the klp_func symbol addressing.

>  			if (ret)
>  				return ret;
>  		}
> @@ -587,7 +598,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>   * /sys/kernel/livepatch/<patch>
>   * /sys/kernel/livepatch/<patch>/enabled
>   * /sys/kernel/livepatch/<patch>/<object>
> - * /sys/kernel/livepatch/<patch>/<object>/<func>
> + * /sys/kernel/livepatch/<patch>/<object>/<func,number>
>   */
>  
>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> @@ -732,8 +743,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
> -	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +	return 0;
>  }

The sysfs entry can still be created here, since the function name and
sympos are both already known.

>  
>  /* parts of the initialization that is done only when the object is loaded */
> @@ -755,6 +765,18 @@ static int klp_init_object_loaded(struct klp_patch *patch,
>  			return ret;
>  	}
>  
> +	/*
> +	 * for each function initialize and add, old_sympos will be already
> +	 * verified at this point
> +	 */
> +	klp_for_each_func(obj, func) {
> +		ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
> +				    &obj->kobj, "%s,%lu", func->old_name,
> +				    func->old_sympos ? func->old_sympos : 0);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	return 0;
>  }
>  
> -- 
> 1.9.1
> 

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-09 23:01                               ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-09 23:01 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On 11/09/2015 02:56 PM, Josh Poimboeuf wrote:
> I'd recommend splitting this up into two separate patches:
> 
> 1. introduce old_sympos
> 2. change the sysfs interface
> 
> On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
>> In cases of duplicate symbols in vmlinux, old_sympos will be used to
>> disambiguate instead of old_addr. Normally old_sympos will be 0, and
>> default to only returning the first found instance of that symbol. If an
>> incorrect symbol position is specified then livepatching will fail.
> 
> In the case of old_sympos == 0, instead of just returning the first
> symbol it finds, I think it should ensure that the symbol is unique.  As
> Miroslav suggested:
> 
>   0 - default, preserve more or less current behaviour. If the symbol is 
>       unique there is no problem. If it is not the patching would fail.
>   1, 2, ... - occurrence of the symbol in kallsyms.
>   
>   The advantage is that if the user does not care and is certain that the 
>   symbol is unique he doesn't have to do anything. If the symbol is not 
>   unique he still has means how to solve it.
> 

So one part that will be confusing here is as follows.

If '0' is specified for old_sympos, should the symbol be 'func_name,0'
or 'func_name,1' provided we have a unique symbol? We could also default
to 'what the user provides', but this seems odd.

Another option would be to use no postfix when 0 is given, and only
introduce the ',n' postfix if old_sympos is > 0.

--chris

>> Finally, old_addr is now an internal structure element and not to be
>> specified by the user.
>>
>> The following directory structure will allow for cases when the same
>> function name exists in a single object.
>> 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> 
> Period should be changed to a comma.
> 
>> The number corresponds to the nth occurrence of the symbol name in
>> kallsyms for the patched object.
>>
>> An example of patching multiple symbols can be found here:
>> 	https://github.com/dynup/kpatch/issues/493
>>
>> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
>> ---
>>  Documentation/ABI/testing/sysfs-kernel-livepatch |  6 ++-
>>  include/linux/livepatch.h                        | 20 ++++---
>>  kernel/livepatch/core.c                          | 66 ++++++++++++++++--------
>>  3 files changed, 61 insertions(+), 31 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
>> index 5bf42a8..21b6bc1 100644
>> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
>> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
>> @@ -33,7 +33,7 @@ Description:
>>  		The object directory contains subdirectories for each function
>>  		that is patched within the object.
>>  
>> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
>> +What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
>>  Date:		Nov 2014
>>  KernelVersion:	3.19.0
>>  Contact:	live-patching@vger.kernel.org
>> @@ -41,4 +41,8 @@ Description:
>>  		The function directory contains attributes regarding the
>>  		properties and state of the patched function.
>>  
>> +		The directory name contains the patched function name and a
>> +		number corresponding to the nth occurrence of the symbol name
>> +		in kallsyms for the patched object.
>> +
>>  		There are currently no such attributes.
>> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
>> index 31db7a0..986e06d 100644
>> --- a/include/linux/livepatch.h
>> +++ b/include/linux/livepatch.h
>> @@ -37,8 +37,9 @@ enum klp_state {
>>   * 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_addr:	a hint conveying at what address the old function
>> + * @old_sympos: a hint indicating which symbol position the old function
>>   *		can be found (optional, vmlinux patches only)
> 
> Why is old_sympos only checked for vmlinux patches only?  It's a
> per-object count, so it should work for modules as well.
> 
>> + * @old_addr:	the address of the function being patched
>>   * @kobj:	kobject for sysfs resources
>>   * @state:	tracks function-level patch application state
>>   * @stack_node:	list node for klp_ops func_stack list
>> @@ -47,17 +48,20 @@ struct klp_func {
>>  	/* external */
>>  	const char *old_name;
>>  	void *new_func;
>> +
>>  	/*
>> -	 * The old_addr field is optional and can be used to resolve
>> -	 * duplicate symbol names in the vmlinux object.  If this
>> -	 * information is not present, the symbol is located by name
>> -	 * with kallsyms. If the name is not unique and old_addr is
>> -	 * not provided, the patch application fails as there is no
>> -	 * way to resolve the ambiguity.
>> +	 * The old_sympos field is optional and can be used to resolve duplicate
>> +	 * symbol names in the vmlinux object.  If this information is not
>> +	 * present, the first symbol located with kallsyms is used. This value
>> +	 * corresponds to the nth occurrence of the symbol name in kallsyms for
>> +	 * the patched object. If the name is not unique and old_sympos is not
>> +	 * provided, the patch application fails as there is no way to resolve
>> +	 * the ambiguity.
>>  	 */
>> -	unsigned long old_addr;
>> +	unsigned long old_sympos;
>>  
>>  	/* internal */
>> +	unsigned long old_addr;
>>  	struct kobject kobj;
>>  	enum klp_state state;
>>  	struct list_head stack_node;
>> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
>> index 6e53441..1dd0d44 100644
>> --- a/kernel/livepatch/core.c
>> +++ b/kernel/livepatch/core.c
>> @@ -142,6 +142,7 @@ struct klp_find_arg {
>>  	 * name in the same object.
>>  	 */
>>  	unsigned long count;
>> +	unsigned long pos;
>>  };
>>  
>>  static int klp_find_callback(void *data, const char *name,
>> @@ -166,28 +167,39 @@ static int klp_find_callback(void *data, const char *name,
>>  	args->addr = addr;
>>  	args->count++;
>>  
>> +	/*
>> +	 * ensure count matches the symbol position
>> +	 */
>> +	if (args->pos == (args->count-1))
>> +		return 1;
>> +
> 
> The code can be simplified a bit if args->addr only gets set when
> args->pos is a match.  Then klp_find_object_symbol() only needs to check
> args.addr to see if a match was found.
> 
>>  	return 0;
>>  }
>>  
>>  static int klp_find_object_symbol(const char *objname, const char *name,
>> -				  unsigned long *addr)
>> +				  unsigned long *addr, unsigned long sympos)
>>  {
>>  	struct klp_find_arg args = {
>>  		.objname = objname,
>>  		.name = name,
>>  		.addr = 0,
>> -		.count = 0
>> +		.count = 0,
>> +		.pos = sympos,
>>  	};
>>  
>>  	mutex_lock(&module_mutex);
>>  	kallsyms_on_each_symbol(klp_find_callback, &args);
>>  	mutex_unlock(&module_mutex);
>>  
>> -	if (args.count == 0)
>> +	/*
>> +	 * Ensure an address was found, then check that the symbol position
>> +	 * count matches sympos.
>> +	 */
>> +	if (args.addr == 0)
>>  		pr_err("symbol '%s' not found in symbol table\n", name);
>> -	else if (args.count > 1)
>> -		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
>> -		       args.count, name, objname);
>> +	else if (sympos != (args.count - 1))
>> +		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
>> +		       sympos, name, objname ? objname : "vmlinux");
>>  	else {
>>  		*addr = args.addr;
>>  		return 0;
>> @@ -239,20 +251,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
>>  static int klp_find_verify_func_addr(struct klp_object *obj,
>>  				     struct klp_func *func)
>>  {
>> +	int sympos = 0;
>>  	int ret;
>>  
>> -#if defined(CONFIG_RANDOMIZE_BASE)
>> -	/* If KASLR has been enabled, adjust old_addr accordingly */
>> -	if (kaslr_enabled() && func->old_addr)
>> -		func->old_addr += kaslr_offset();
>> -#endif
>> +	if (func->old_sympos && !klp_is_module(obj))
>> +		sympos = func->old_sympos;
>>  
>> -	if (!func->old_addr || klp_is_module(obj))
>> -		ret = klp_find_object_symbol(obj->name, func->old_name,
>> -					     &func->old_addr);
>> -	else
>> -		ret = klp_verify_vmlinux_symbol(func->old_name,
>> -						func->old_addr);
>> +	/*
>> +	 * Verify the symbol, find old_addr, and write it to the structure.
>> +	 * By default sympos will be 0 and thus will only look for the first
>> +	 * occurrence. If another value is specified then that will be used.
>> +	 */
>> +	ret = klp_find_object_symbol(obj->name, func->old_name,
>> +				     &func->old_addr, sympos);
>>  
>>  	return ret;
>>  }
>> @@ -277,7 +288,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>>  	preempt_enable();
>>  
>>  	/* otherwise check if it's in another .o within the patch module */
>> -	return klp_find_object_symbol(pmod->name, name, addr);
>> +	return klp_find_object_symbol(pmod->name, name, addr, 0);
>>  }
>>  
>>  static int klp_write_object_relocations(struct module *pmod,
>> @@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
>>  			else
>>  				ret = klp_find_object_symbol(obj->mod->name,
>>  							     reloc->name,
>> -							     &reloc->val);
>> +							     &reloc->val, 0);
> 
> I think it would be a good idea to also add old_sympos to klp_reloc so
> the relocation code is consistent with the klp_func symbol addressing.
>

So you are thinking as an optional external field as well? I'll have to
look at this a bit more but makes sense to me.
--chris


>>  			if (ret)
>>  				return ret;
>>  		}
>> @@ -587,7 +598,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>>   * /sys/kernel/livepatch/<patch>
>>   * /sys/kernel/livepatch/<patch>/enabled
>>   * /sys/kernel/livepatch/<patch>/<object>
>> - * /sys/kernel/livepatch/<patch>/<object>/<func>
>> + * /sys/kernel/livepatch/<patch>/<object>/<func,number>
>>   */
>>  
>>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
>> @@ -732,8 +743,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>>  	INIT_LIST_HEAD(&func->stack_node);
>>  	func->state = KLP_DISABLED;
>>  
>> -	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
>> -				    &obj->kobj, "%s", func->old_name);
>> +	return 0;
>>  }
> 
> The sysfs entry can still be created here, since the function name and
> sympos are both already known.
> 
>>  
>>  /* parts of the initialization that is done only when the object is loaded */
>> @@ -755,6 +765,18 @@ static int klp_init_object_loaded(struct klp_patch *patch,
>>  			return ret;
>>  	}
>>  
>> +	/*
>> +	 * for each function initialize and add, old_sympos will be already
>> +	 * verified at this point
>> +	 */
>> +	klp_for_each_func(obj, func) {
>> +		ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
>> +				    &obj->kobj, "%s,%lu", func->old_name,
>> +				    func->old_sympos ? func->old_sympos : 0);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>>  	return 0;
>>  }
>>  
>> -- 
>> 1.9.1
>>
> 

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-09 23:01                               ` Chris J Arges
  0 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-09 23:01 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 11/09/2015 02:56 PM, Josh Poimboeuf wrote:
> I'd recommend splitting this up into two separate patches:
> 
> 1. introduce old_sympos
> 2. change the sysfs interface
> 
> On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
>> In cases of duplicate symbols in vmlinux, old_sympos will be used to
>> disambiguate instead of old_addr. Normally old_sympos will be 0, and
>> default to only returning the first found instance of that symbol. If an
>> incorrect symbol position is specified then livepatching will fail.
> 
> In the case of old_sympos == 0, instead of just returning the first
> symbol it finds, I think it should ensure that the symbol is unique.  As
> Miroslav suggested:
> 
>   0 - default, preserve more or less current behaviour. If the symbol is 
>       unique there is no problem. If it is not the patching would fail.
>   1, 2, ... - occurrence of the symbol in kallsyms.
>   
>   The advantage is that if the user does not care and is certain that the 
>   symbol is unique he doesn't have to do anything. If the symbol is not 
>   unique he still has means how to solve it.
> 

So one part that will be confusing here is as follows.

If '0' is specified for old_sympos, should the symbol be 'func_name,0'
or 'func_name,1' provided we have a unique symbol? We could also default
to 'what the user provides', but this seems odd.

Another option would be to use no postfix when 0 is given, and only
introduce the ',n' postfix if old_sympos is > 0.

--chris

>> Finally, old_addr is now an internal structure element and not to be
>> specified by the user.
>>
>> The following directory structure will allow for cases when the same
>> function name exists in a single object.
>> 	/sys/kernel/livepatch/<patch>/<object>/<function.number>
> 
> Period should be changed to a comma.
> 
>> The number corresponds to the nth occurrence of the symbol name in
>> kallsyms for the patched object.
>>
>> An example of patching multiple symbols can be found here:
>> 	https://github.com/dynup/kpatch/issues/493
>>
>> Signed-off-by: Chris J Arges <chris.j.arges-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
>> ---
>>  Documentation/ABI/testing/sysfs-kernel-livepatch |  6 ++-
>>  include/linux/livepatch.h                        | 20 ++++---
>>  kernel/livepatch/core.c                          | 66 ++++++++++++++++--------
>>  3 files changed, 61 insertions(+), 31 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
>> index 5bf42a8..21b6bc1 100644
>> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
>> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
>> @@ -33,7 +33,7 @@ Description:
>>  		The object directory contains subdirectories for each function
>>  		that is patched within the object.
>>  
>> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
>> +What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
>>  Date:		Nov 2014
>>  KernelVersion:	3.19.0
>>  Contact:	live-patching-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> @@ -41,4 +41,8 @@ Description:
>>  		The function directory contains attributes regarding the
>>  		properties and state of the patched function.
>>  
>> +		The directory name contains the patched function name and a
>> +		number corresponding to the nth occurrence of the symbol name
>> +		in kallsyms for the patched object.
>> +
>>  		There are currently no such attributes.
>> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
>> index 31db7a0..986e06d 100644
>> --- a/include/linux/livepatch.h
>> +++ b/include/linux/livepatch.h
>> @@ -37,8 +37,9 @@ enum klp_state {
>>   * 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_addr:	a hint conveying at what address the old function
>> + * @old_sympos: a hint indicating which symbol position the old function
>>   *		can be found (optional, vmlinux patches only)
> 
> Why is old_sympos only checked for vmlinux patches only?  It's a
> per-object count, so it should work for modules as well.
> 
>> + * @old_addr:	the address of the function being patched
>>   * @kobj:	kobject for sysfs resources
>>   * @state:	tracks function-level patch application state
>>   * @stack_node:	list node for klp_ops func_stack list
>> @@ -47,17 +48,20 @@ struct klp_func {
>>  	/* external */
>>  	const char *old_name;
>>  	void *new_func;
>> +
>>  	/*
>> -	 * The old_addr field is optional and can be used to resolve
>> -	 * duplicate symbol names in the vmlinux object.  If this
>> -	 * information is not present, the symbol is located by name
>> -	 * with kallsyms. If the name is not unique and old_addr is
>> -	 * not provided, the patch application fails as there is no
>> -	 * way to resolve the ambiguity.
>> +	 * The old_sympos field is optional and can be used to resolve duplicate
>> +	 * symbol names in the vmlinux object.  If this information is not
>> +	 * present, the first symbol located with kallsyms is used. This value
>> +	 * corresponds to the nth occurrence of the symbol name in kallsyms for
>> +	 * the patched object. If the name is not unique and old_sympos is not
>> +	 * provided, the patch application fails as there is no way to resolve
>> +	 * the ambiguity.
>>  	 */
>> -	unsigned long old_addr;
>> +	unsigned long old_sympos;
>>  
>>  	/* internal */
>> +	unsigned long old_addr;
>>  	struct kobject kobj;
>>  	enum klp_state state;
>>  	struct list_head stack_node;
>> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
>> index 6e53441..1dd0d44 100644
>> --- a/kernel/livepatch/core.c
>> +++ b/kernel/livepatch/core.c
>> @@ -142,6 +142,7 @@ struct klp_find_arg {
>>  	 * name in the same object.
>>  	 */
>>  	unsigned long count;
>> +	unsigned long pos;
>>  };
>>  
>>  static int klp_find_callback(void *data, const char *name,
>> @@ -166,28 +167,39 @@ static int klp_find_callback(void *data, const char *name,
>>  	args->addr = addr;
>>  	args->count++;
>>  
>> +	/*
>> +	 * ensure count matches the symbol position
>> +	 */
>> +	if (args->pos == (args->count-1))
>> +		return 1;
>> +
> 
> The code can be simplified a bit if args->addr only gets set when
> args->pos is a match.  Then klp_find_object_symbol() only needs to check
> args.addr to see if a match was found.
> 
>>  	return 0;
>>  }
>>  
>>  static int klp_find_object_symbol(const char *objname, const char *name,
>> -				  unsigned long *addr)
>> +				  unsigned long *addr, unsigned long sympos)
>>  {
>>  	struct klp_find_arg args = {
>>  		.objname = objname,
>>  		.name = name,
>>  		.addr = 0,
>> -		.count = 0
>> +		.count = 0,
>> +		.pos = sympos,
>>  	};
>>  
>>  	mutex_lock(&module_mutex);
>>  	kallsyms_on_each_symbol(klp_find_callback, &args);
>>  	mutex_unlock(&module_mutex);
>>  
>> -	if (args.count == 0)
>> +	/*
>> +	 * Ensure an address was found, then check that the symbol position
>> +	 * count matches sympos.
>> +	 */
>> +	if (args.addr == 0)
>>  		pr_err("symbol '%s' not found in symbol table\n", name);
>> -	else if (args.count > 1)
>> -		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
>> -		       args.count, name, objname);
>> +	else if (sympos != (args.count - 1))
>> +		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
>> +		       sympos, name, objname ? objname : "vmlinux");
>>  	else {
>>  		*addr = args.addr;
>>  		return 0;
>> @@ -239,20 +251,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
>>  static int klp_find_verify_func_addr(struct klp_object *obj,
>>  				     struct klp_func *func)
>>  {
>> +	int sympos = 0;
>>  	int ret;
>>  
>> -#if defined(CONFIG_RANDOMIZE_BASE)
>> -	/* If KASLR has been enabled, adjust old_addr accordingly */
>> -	if (kaslr_enabled() && func->old_addr)
>> -		func->old_addr += kaslr_offset();
>> -#endif
>> +	if (func->old_sympos && !klp_is_module(obj))
>> +		sympos = func->old_sympos;
>>  
>> -	if (!func->old_addr || klp_is_module(obj))
>> -		ret = klp_find_object_symbol(obj->name, func->old_name,
>> -					     &func->old_addr);
>> -	else
>> -		ret = klp_verify_vmlinux_symbol(func->old_name,
>> -						func->old_addr);
>> +	/*
>> +	 * Verify the symbol, find old_addr, and write it to the structure.
>> +	 * By default sympos will be 0 and thus will only look for the first
>> +	 * occurrence. If another value is specified then that will be used.
>> +	 */
>> +	ret = klp_find_object_symbol(obj->name, func->old_name,
>> +				     &func->old_addr, sympos);
>>  
>>  	return ret;
>>  }
>> @@ -277,7 +288,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>>  	preempt_enable();
>>  
>>  	/* otherwise check if it's in another .o within the patch module */
>> -	return klp_find_object_symbol(pmod->name, name, addr);
>> +	return klp_find_object_symbol(pmod->name, name, addr, 0);
>>  }
>>  
>>  static int klp_write_object_relocations(struct module *pmod,
>> @@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
>>  			else
>>  				ret = klp_find_object_symbol(obj->mod->name,
>>  							     reloc->name,
>> -							     &reloc->val);
>> +							     &reloc->val, 0);
> 
> I think it would be a good idea to also add old_sympos to klp_reloc so
> the relocation code is consistent with the klp_func symbol addressing.
>

So you are thinking as an optional external field as well? I'll have to
look at this a bit more but makes sense to me.
--chris


>>  			if (ret)
>>  				return ret;
>>  		}
>> @@ -587,7 +598,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>>   * /sys/kernel/livepatch/<patch>
>>   * /sys/kernel/livepatch/<patch>/enabled
>>   * /sys/kernel/livepatch/<patch>/<object>
>> - * /sys/kernel/livepatch/<patch>/<object>/<func>
>> + * /sys/kernel/livepatch/<patch>/<object>/<func,number>
>>   */
>>  
>>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
>> @@ -732,8 +743,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>>  	INIT_LIST_HEAD(&func->stack_node);
>>  	func->state = KLP_DISABLED;
>>  
>> -	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
>> -				    &obj->kobj, "%s", func->old_name);
>> +	return 0;
>>  }
> 
> The sysfs entry can still be created here, since the function name and
> sympos are both already known.
> 
>>  
>>  /* parts of the initialization that is done only when the object is loaded */
>> @@ -755,6 +765,18 @@ static int klp_init_object_loaded(struct klp_patch *patch,
>>  			return ret;
>>  	}
>>  
>> +	/*
>> +	 * for each function initialize and add, old_sympos will be already
>> +	 * verified at this point
>> +	 */
>> +	klp_for_each_func(obj, func) {
>> +		ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
>> +				    &obj->kobj, "%s,%lu", func->old_name,
>> +				    func->old_sympos ? func->old_sympos : 0);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>>  	return 0;
>>  }
>>  
>> -- 
>> 1.9.1
>>
> 

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
  2015-11-09 23:01                               ` Chris J Arges
  (?)
@ 2015-11-10  4:54                               ` Josh Poimboeuf
  2015-11-10  8:49                                 ` Miroslav Benes
  -1 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-10  4:54 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On Mon, Nov 09, 2015 at 05:01:18PM -0600, Chris J Arges wrote:
> On 11/09/2015 02:56 PM, Josh Poimboeuf wrote:
> > I'd recommend splitting this up into two separate patches:
> > 
> > 1. introduce old_sympos
> > 2. change the sysfs interface
> > 
> > On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
> >> In cases of duplicate symbols in vmlinux, old_sympos will be used to
> >> disambiguate instead of old_addr. Normally old_sympos will be 0, and
> >> default to only returning the first found instance of that symbol. If an
> >> incorrect symbol position is specified then livepatching will fail.
> > 
> > In the case of old_sympos == 0, instead of just returning the first
> > symbol it finds, I think it should ensure that the symbol is unique.  As
> > Miroslav suggested:
> > 
> >   0 - default, preserve more or less current behaviour. If the symbol is 
> >       unique there is no problem. If it is not the patching would fail.
> >   1, 2, ... - occurrence of the symbol in kallsyms.
> >   
> >   The advantage is that if the user does not care and is certain that the 
> >   symbol is unique he doesn't have to do anything. If the symbol is not 
> >   unique he still has means how to solve it.
> > 
> 
> So one part that will be confusing here is as follows.
> 
> If '0' is specified for old_sympos, should the symbol be 'func_name,0'
> or 'func_name,1' provided we have a unique symbol? We could also default
> to 'what the user provides', but this seems odd.

I don't feel strongly either way, but I think using the same number the
user provides is fine, since it makes the sysfs interface consistent
with the old_sympos usage.

> Another option would be to use no postfix when 0 is given, and only
> introduce the ',n' postfix if old_sympos is > 0.

IMO always having a suffix is good, as it makes parsing less surprising
and less error-prone.

> >>  static int klp_write_object_relocations(struct module *pmod,
> >> @@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
> >>  			else
> >>  				ret = klp_find_object_symbol(obj->mod->name,
> >>  							     reloc->name,
> >> -							     &reloc->val);
> >> +							     &reloc->val, 0);
> > 
> > I think it would be a good idea to also add old_sympos to klp_reloc so
> > the relocation code is consistent with the klp_func symbol addressing.
> >
> 
> So you are thinking as an optional external field as well? I'll have to
> look at this a bit more but makes sense to me.

Yeah, the semantics would be the same as klp_func.old_sympos.  We could
add a new klp_reloc.sympos and make klp_reloc.val a private field.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
  2015-11-10  4:54                               ` Josh Poimboeuf
@ 2015-11-10  8:49                                 ` Miroslav Benes
  2015-11-10 13:40                                     ` Josh Poimboeuf
  0 siblings, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-10  8:49 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Mon, 9 Nov 2015, Josh Poimboeuf wrote:

> On Mon, Nov 09, 2015 at 05:01:18PM -0600, Chris J Arges wrote:
> > On 11/09/2015 02:56 PM, Josh Poimboeuf wrote:
> > > I'd recommend splitting this up into two separate patches:
> > > 
> > > 1. introduce old_sympos
> > > 2. change the sysfs interface
> > > 
> > > On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
> > >> In cases of duplicate symbols in vmlinux, old_sympos will be used to
> > >> disambiguate instead of old_addr. Normally old_sympos will be 0, and
> > >> default to only returning the first found instance of that symbol. If an
> > >> incorrect symbol position is specified then livepatching will fail.
> > > 
> > > In the case of old_sympos == 0, instead of just returning the first
> > > symbol it finds, I think it should ensure that the symbol is unique.  As
> > > Miroslav suggested:
> > > 
> > >   0 - default, preserve more or less current behaviour. If the symbol is 
> > >       unique there is no problem. If it is not the patching would fail.
> > >   1, 2, ... - occurrence of the symbol in kallsyms.
> > >   
> > >   The advantage is that if the user does not care and is certain that the 
> > >   symbol is unique he doesn't have to do anything. If the symbol is not 
> > >   unique he still has means how to solve it.
> > > 
> > 
> > So one part that will be confusing here is as follows.
> > 
> > If '0' is specified for old_sympos, should the symbol be 'func_name,0'
> > or 'func_name,1' provided we have a unique symbol? We could also default
> > to 'what the user provides', but this seems odd.
> 
> I don't feel strongly either way, but I think using the same number the
> user provides is fine, since it makes the sysfs interface consistent
> with the old_sympos usage.

I think it should be func_name,1 even if '0' is specified and the symbol 
is unique. Because if we say that 1, 2, ... is the occurrence of the 
symbol in kallsyms it should stay that way everywhere. Hence for 
old_sympos == 0 it is func_name,1 in sysfs; for 1 it is still func_name,1; 
for 2 it is func_name,2 and so on.

And I'd add this to sysfs documentation.

> > Another option would be to use no postfix when 0 is given, and only
> > introduce the ',n' postfix if old_sympos is > 0.
> 
> IMO always having a suffix is good, as it makes parsing less surprising
> and less error-prone.

Agreed.

> > >>  static int klp_write_object_relocations(struct module *pmod,
> > >> @@ -307,7 +318,7 @@ static int klp_write_object_relocations(struct module *pmod,
> > >>  			else
> > >>  				ret = klp_find_object_symbol(obj->mod->name,
> > >>  							     reloc->name,
> > >> -							     &reloc->val);
> > >> +							     &reloc->val, 0);
> > > 
> > > I think it would be a good idea to also add old_sympos to klp_reloc so
> > > the relocation code is consistent with the klp_func symbol addressing.
> > >
> > 
> > So you are thinking as an optional external field as well? I'll have to
> > look at this a bit more but makes sense to me.
> 
> Yeah, the semantics would be the same as klp_func.old_sympos.  We could
> add a new klp_reloc.sympos and make klp_reloc.val a private field.

Agreed as well.

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
  2015-11-09 16:16                           ` Chris J Arges
  (?)
  (?)
@ 2015-11-10  9:02                           ` Miroslav Benes
  -1 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-10  9:02 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Mon, 9 Nov 2015, Chris J Arges wrote:

> In cases of duplicate symbols in vmlinux, old_sympos will be used to
> disambiguate instead of old_addr. Normally old_sympos will be 0, and
> default to only returning the first found instance of that symbol. If an
> incorrect symbol position is specified then livepatching will fail.
> Finally, old_addr is now an internal structure element and not to be
> specified by the user.

Hi,

Josh has already mentioned it, but in this case '0' would be same as '1'. 
'0' should fail if the symbol is ambiguous.

Few more things follow, but Josh pointed out the issues.

[...]

> @@ -239,20 +251,19 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
>  static int klp_find_verify_func_addr(struct klp_object *obj,
>  				     struct klp_func *func)
>  {
> +	int sympos = 0;
>  	int ret;
>  
> -#if defined(CONFIG_RANDOMIZE_BASE)
> -	/* If KASLR has been enabled, adjust old_addr accordingly */
> -	if (kaslr_enabled() && func->old_addr)
> -		func->old_addr += kaslr_offset();
> -#endif
> +	if (func->old_sympos && !klp_is_module(obj))
> +		sympos = func->old_sympos;

We need to deal with ambiguity in modules as well. 

Also, maybe the function could be renamed, because there would be no 
verification here in the future.

>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> @@ -732,8 +743,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
> -	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +	return 0;
>  }
>  
>  /* parts of the initialization that is done only when the object is loaded */
> @@ -755,6 +765,18 @@ static int klp_init_object_loaded(struct klp_patch *patch,
>  			return ret;
>  	}
>  
> +	/*
> +	 * for each function initialize and add, old_sympos will be already
> +	 * verified at this point
> +	 */
> +	klp_for_each_func(obj, func) {
> +		ret = kobject_init_and_add(&func->kobj, &klp_ktype_func,
> +				    &obj->kobj, "%s,%lu", func->old_name,
> +				    func->old_sympos ? func->old_sympos : 0);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	return 0;
>  }

There is a problem with error handling in klp_init_object() after the 
change. 

free:
        klp_free_funcs_limited(obj, func);
        kobject_put(&obj->kobj);
        return ret;

This snippet ensures that all already created sysfs func entries are 
destroyed. 'func' is the function which klp_init_func() failed for (or 
'{}' if nothing failed). When you move kobject_init_and_add() with the 
loop to klp_init_object_loaded(), we do not know where the exact problem 
was in klp_init_object(). So I agree with Josh that it can stay in 
klp_init_func(). old_sympos is defined and if the following 
klp_find_verify_func_addr() fails (for example when old_sympos is '0' and 
the symbol is not unique) we deal with it here in klp_init_object() 
correctly.

Thanks,
Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-10 13:40                                     ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-10 13:40 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

On Tue, Nov 10, 2015 at 09:49:09AM +0100, Miroslav Benes wrote:
> On Mon, 9 Nov 2015, Josh Poimboeuf wrote:
> 
> > On Mon, Nov 09, 2015 at 05:01:18PM -0600, Chris J Arges wrote:
> > > On 11/09/2015 02:56 PM, Josh Poimboeuf wrote:
> > > > I'd recommend splitting this up into two separate patches:
> > > > 
> > > > 1. introduce old_sympos
> > > > 2. change the sysfs interface
> > > > 
> > > > On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
> > > >> In cases of duplicate symbols in vmlinux, old_sympos will be used to
> > > >> disambiguate instead of old_addr. Normally old_sympos will be 0, and
> > > >> default to only returning the first found instance of that symbol. If an
> > > >> incorrect symbol position is specified then livepatching will fail.
> > > > 
> > > > In the case of old_sympos == 0, instead of just returning the first
> > > > symbol it finds, I think it should ensure that the symbol is unique.  As
> > > > Miroslav suggested:
> > > > 
> > > >   0 - default, preserve more or less current behaviour. If the symbol is 
> > > >       unique there is no problem. If it is not the patching would fail.
> > > >   1, 2, ... - occurrence of the symbol in kallsyms.
> > > >   
> > > >   The advantage is that if the user does not care and is certain that the 
> > > >   symbol is unique he doesn't have to do anything. If the symbol is not 
> > > >   unique he still has means how to solve it.
> > > > 
> > > 
> > > So one part that will be confusing here is as follows.
> > > 
> > > If '0' is specified for old_sympos, should the symbol be 'func_name,0'
> > > or 'func_name,1' provided we have a unique symbol? We could also default
> > > to 'what the user provides', but this seems odd.
> > 
> > I don't feel strongly either way, but I think using the same number the
> > user provides is fine, since it makes the sysfs interface consistent
> > with the old_sympos usage.
> 
> I think it should be func_name,1 even if '0' is specified and the symbol 
> is unique. Because if we say that 1, 2, ... is the occurrence of the 
> symbol in kallsyms it should stay that way everywhere. Hence for 
> old_sympos == 0 it is func_name,1 in sysfs; for 1 it is still func_name,1; 
> for 2 it is func_name,2 and so on.
> 
> And I'd add this to sysfs documentation.

That makes sense, sounds fine to me.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v3] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-10 13:40                                     ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-10 13:40 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Tue, Nov 10, 2015 at 09:49:09AM +0100, Miroslav Benes wrote:
> On Mon, 9 Nov 2015, Josh Poimboeuf wrote:
> 
> > On Mon, Nov 09, 2015 at 05:01:18PM -0600, Chris J Arges wrote:
> > > On 11/09/2015 02:56 PM, Josh Poimboeuf wrote:
> > > > I'd recommend splitting this up into two separate patches:
> > > > 
> > > > 1. introduce old_sympos
> > > > 2. change the sysfs interface
> > > > 
> > > > On Mon, Nov 09, 2015 at 10:16:05AM -0600, Chris J Arges wrote:
> > > >> In cases of duplicate symbols in vmlinux, old_sympos will be used to
> > > >> disambiguate instead of old_addr. Normally old_sympos will be 0, and
> > > >> default to only returning the first found instance of that symbol. If an
> > > >> incorrect symbol position is specified then livepatching will fail.
> > > > 
> > > > In the case of old_sympos == 0, instead of just returning the first
> > > > symbol it finds, I think it should ensure that the symbol is unique.  As
> > > > Miroslav suggested:
> > > > 
> > > >   0 - default, preserve more or less current behaviour. If the symbol is 
> > > >       unique there is no problem. If it is not the patching would fail.
> > > >   1, 2, ... - occurrence of the symbol in kallsyms.
> > > >   
> > > >   The advantage is that if the user does not care and is certain that the 
> > > >   symbol is unique he doesn't have to do anything. If the symbol is not 
> > > >   unique he still has means how to solve it.
> > > > 
> > > 
> > > So one part that will be confusing here is as follows.
> > > 
> > > If '0' is specified for old_sympos, should the symbol be 'func_name,0'
> > > or 'func_name,1' provided we have a unique symbol? We could also default
> > > to 'what the user provides', but this seems odd.
> > 
> > I don't feel strongly either way, but I think using the same number the
> > user provides is fine, since it makes the sysfs interface consistent
> > with the old_sympos usage.
> 
> I think it should be func_name,1 even if '0' is specified and the symbol 
> is unique. Because if we say that 1, 2, ... is the occurrence of the 
> symbol in kallsyms it should stay that way everywhere. Hence for 
> old_sympos == 0 it is func_name,1 in sysfs; for 1 it is still func_name,1; 
> for 2 it is func_name,2 and so on.
> 
> And I'd add this to sysfs documentation.

That makes sense, sounds fine to me.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func
       [not found]                 ` <1447259366-7055-1-git-send-email-chris.j.arges@canonical.com>
@ 2015-11-11 16:28                   ` Chris J Arges
  2015-11-11 17:43                     ` Josh Poimboeuf
  2015-11-12 10:22                     ` Miroslav Benes
  2015-11-11 16:29                   ` [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc Chris J Arges
                                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-11 16:28 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

In cases of duplicate symbols, old_sympos will be used to disambiguate
instead of old_addr. By default old_sympos will be 0, and patching will
only succeed if the symbol is unique. Specifying a positive value will
ensure that occurrence of the symbol will be used for patching if it is
valid. Finally, old_addr is now an internal structure element and not to
be specified by the user.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h | 20 ++++++++++--------
 kernel/livepatch/core.c   | 53 +++++++++++++++++++++++------------------------
 2 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..df7b752 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
- *		can be found (optional, vmlinux patches only)
+ * @old_sympos: a hint indicating which symbol position the old function
+ *		can be found (optional)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -47,17 +48,18 @@ struct klp_func {
 	/* external */
 	const char *old_name;
 	void *new_func;
+
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve
+	 * duplicate symbol names in livepatch objects. If this field is zero,
+	 * it is expected the symbol is unique, otherwise patching fails. If
+	 * this value is greater than zero then that occurrence of the symbol
+	 * in kallsyms is used.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..26f9778 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -142,6 +142,7 @@ struct klp_find_arg {
 	 * name in the same object.
 	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -159,36 +160,45 @@ static int klp_find_callback(void *data, const char *name,
 		return 0;
 
 	/*
-	 * args->addr might be overwritten if another match is found
-	 * but klp_find_object_symbol() handles this and only returns the
-	 * addr if count == 1.
+	 * increment and assign address, return only if checking pos and
+	 * it matches count.
 	 */
-	args->addr = addr;
 	args->count++;
+	args->addr = addr;
+	if ((args->pos > 0) && (args->count == args->pos))
+		return 1;
 
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long *addr, unsigned long sympos)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
+	 * otherwise ensure the symbol position count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
+	else if (args.count > 1 && sympos == 0) {
 		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 		       args.count, name, objname);
-	else {
+	} else if (sympos != args.count && sympos > 0) {
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
+	} else {
 		*addr = args.addr;
 		return 0;
 	}
@@ -239,22 +249,11 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 static int klp_find_verify_func_addr(struct klp_object *obj,
 				     struct klp_func *func)
 {
-	int ret;
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
-
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
-
-	return ret;
+	/*
+	 * Verify the symbol, find old_addr, and write it to the structure.
+	 */
+	return klp_find_object_symbol(obj->name, func->old_name,
+				      &func->old_addr, func->old_sympos);
 }
 
 /*
@@ -277,7 +276,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	preempt_enable();
 
 	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	return klp_find_object_symbol(pmod->name, name, addr, 0);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +306,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     &reloc->val, 0);
 			if (ret)
 				return ret;
 		}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
       [not found]                 ` <1447259366-7055-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-11 16:28                   ` [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-11 16:29                   ` Chris J Arges
  2015-11-11 16:39                     ` Chris J Arges
                                       ` (2 more replies)
  2015-11-11 16:29                   ` [PATCH 3/3 v4] livepatch: old_name,number scheme in livepatch sysfs directory Chris J Arges
       [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
  3 siblings, 3 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-11 16:29 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

In cases of duplicate symbols, sympos will be used to disambiguate instead
of val. By default old_sympos will be 0, and patching will only succeed if
the symbol is unique. Specifying a positive value will ensure that
occurrence of the symbol will be used for patching if it is valid.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  5 ++--
 kernel/livepatch/core.c   | 74 ++++++++++-------------------------------------
 2 files changed, 18 insertions(+), 61 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index df7b752..fb968a2 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -68,8 +68,8 @@ struct klp_func {
 /**
  * struct klp_reloc - relocation structure for live patching
  * @loc:	address where the relocation will be written
- * @val:	address of the referenced symbol (optional,
- *		vmlinux	patches only)
+ * @val:	address of the referenced symbol
+ * @sympos:     position in kallsyms to disambiguate symbols (optional)
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
@@ -78,6 +78,7 @@ struct klp_func {
 struct klp_reloc {
 	unsigned long loc;
 	unsigned long val;
+	unsigned long sympos;
 	unsigned long type;
 	const char *name;
 	int addend;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 26f9778..4eb8691 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -207,45 +207,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
 	return -EINVAL;
 }
 
-struct klp_verify_args {
-	const char *name;
-	const unsigned long addr;
-};
-
-static int klp_verify_callback(void *data, const char *name,
-			       struct module *mod, unsigned long addr)
-{
-	struct klp_verify_args *args = data;
-
-	if (!mod &&
-	    !strcmp(args->name, name) &&
-	    args->addr == addr)
-		return 1;
-
-	return 0;
-}
-
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
-{
-	struct klp_verify_args args = {
-		.name = name,
-		.addr = addr,
-	};
-	int ret;
-
-	mutex_lock(&module_mutex);
-	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
-	mutex_unlock(&module_mutex);
-
-	if (!ret) {
-		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
-			name, addr);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int klp_find_verify_func_addr(struct klp_object *obj,
 				     struct klp_func *func)
 {
@@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
  * object is either vmlinux or the kmod being patched).
  */
 static int klp_find_external_symbol(struct module *pmod, const char *name,
-				    unsigned long *addr)
+				    unsigned long *addr, unsigned long sympos)
 {
 	const struct kernel_symbol *sym;
 
@@ -276,7 +237,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	preempt_enable();
 
 	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr, 0);
+	return klp_find_object_symbol(pmod->name, name, addr, sympos);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -292,24 +253,19 @@ static int klp_write_object_relocations(struct module *pmod,
 		return -EINVAL;
 
 	for (reloc = obj->relocs; reloc->name; reloc++) {
-		if (!klp_is_module(obj)) {
-			ret = klp_verify_vmlinux_symbol(reloc->name,
-							reloc->val);
-			if (ret)
-				return ret;
-		} else {
-			/* module, reloc->val needs to be discovered */
-			if (reloc->external)
-				ret = klp_find_external_symbol(pmod,
-							       reloc->name,
-							       &reloc->val);
-			else
-				ret = klp_find_object_symbol(obj->mod->name,
-							     reloc->name,
-							     &reloc->val, 0);
-			if (ret)
-				return ret;
-		}
+		/* reloc->val needs to be discovered */
+		if (reloc->external)
+			ret = klp_find_external_symbol(pmod,
+						       reloc->name,
+						       &reloc->val,
+						       reloc->sympos);
+		else
+			ret = klp_find_object_symbol(obj->mod->name,
+						     reloc->name,
+						     &reloc->val,
+						     reloc->sympos);
+		if (ret)
+			return ret;
 		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
 					     reloc->val + reloc->addend);
 		if (ret) {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 3/3 v4] livepatch: old_name,number scheme in livepatch sysfs directory
       [not found]                 ` <1447259366-7055-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-11 16:28                   ` [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-11 16:29                   ` [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-11 16:29                   ` Chris J Arges
  2015-11-11 18:01                       ` Josh Poimboeuf
       [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
  3 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-11 16:29 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function,number>

The number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
 kernel/livepatch/core.c                          | 10 ++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..21b6bc1 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		number corresponding to the nth occurrence of the symbol name
+		in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 4eb8691..ed2cbbf 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -542,7 +542,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<func,number>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -687,8 +687,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
+	/* The format for the sysfs directory is <func,number> where number is
+	 * the occurrence of this symbol in kallsyms. If the user selects 0 for
+	 * old_sympos, then 1 will be used since a unique symbol will be the
+	 * first occurrence.
+	 */
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 1);
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-11 16:29                   ` [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-11 16:39                     ` Chris J Arges
  2015-11-11 17:57                     ` Josh Poimboeuf
  2015-11-12 10:23                     ` Miroslav Benes
  2 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-11 16:39 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-kernel

On 11/11/2015 10:29 AM, Chris J Arges wrote:
> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default old_sympos will be 0, and patching will only succeed if

Minor typo. old_sympos, should just be sympos.
--chris

> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol will be used for patching if it is valid.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  include/linux/livepatch.h |  5 ++--
>  kernel/livepatch/core.c   | 74 ++++++++++-------------------------------------
>  2 files changed, 18 insertions(+), 61 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index df7b752..fb968a2 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -68,8 +68,8 @@ struct klp_func {
>  /**
>   * struct klp_reloc - relocation structure for live patching
>   * @loc:	address where the relocation will be written
> - * @val:	address of the referenced symbol (optional,
> - *		vmlinux	patches only)
> + * @val:	address of the referenced symbol
> + * @sympos:     position in kallsyms to disambiguate symbols (optional)
>   * @type:	ELF relocation type
>   * @name:	name of the referenced symbol (for lookup/verification)
>   * @addend:	offset from the referenced symbol
> @@ -78,6 +78,7 @@ struct klp_func {
>  struct klp_reloc {
>  	unsigned long loc;
>  	unsigned long val;
> +	unsigned long sympos;
>  	unsigned long type;
>  	const char *name;
>  	int addend;
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 26f9778..4eb8691 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -207,45 +207,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
>  	return -EINVAL;
>  }
>  
> -struct klp_verify_args {
> -	const char *name;
> -	const unsigned long addr;
> -};
> -
> -static int klp_verify_callback(void *data, const char *name,
> -			       struct module *mod, unsigned long addr)
> -{
> -	struct klp_verify_args *args = data;
> -
> -	if (!mod &&
> -	    !strcmp(args->name, name) &&
> -	    args->addr == addr)
> -		return 1;
> -
> -	return 0;
> -}
> -
> -static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
> -{
> -	struct klp_verify_args args = {
> -		.name = name,
> -		.addr = addr,
> -	};
> -	int ret;
> -
> -	mutex_lock(&module_mutex);
> -	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
> -	mutex_unlock(&module_mutex);
> -
> -	if (!ret) {
> -		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
> -			name, addr);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  static int klp_find_verify_func_addr(struct klp_object *obj,
>  				     struct klp_func *func)
>  {
> @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
>   * object is either vmlinux or the kmod being patched).
>   */
>  static int klp_find_external_symbol(struct module *pmod, const char *name,
> -				    unsigned long *addr)
> +				    unsigned long *addr, unsigned long sympos)
>  {
>  	const struct kernel_symbol *sym;
>  
> @@ -276,7 +237,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>  	preempt_enable();
>  
>  	/* otherwise check if it's in another .o within the patch module */
> -	return klp_find_object_symbol(pmod->name, name, addr, 0);
> +	return klp_find_object_symbol(pmod->name, name, addr, sympos);
>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> @@ -292,24 +253,19 @@ static int klp_write_object_relocations(struct module *pmod,
>  		return -EINVAL;
>  
>  	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     &reloc->val, 0);
> -			if (ret)
> -				return ret;
> -		}
> +		/* reloc->val needs to be discovered */
> +		if (reloc->external)
> +			ret = klp_find_external_symbol(pmod,
> +						       reloc->name,
> +						       &reloc->val,
> +						       reloc->sympos);
> +		else
> +			ret = klp_find_object_symbol(obj->mod->name,
> +						     reloc->name,
> +						     &reloc->val,
> +						     reloc->sympos);
> +		if (ret)
> +			return ret;
>  		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
>  					     reloc->val + reloc->addend);
>  		if (ret) {
> 

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-11 16:28                   ` [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-11 17:43                     ` Josh Poimboeuf
  2015-11-12 10:22                     ` Miroslav Benes
  1 sibling, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-11 17:43 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-kernel

On Wed, Nov 11, 2015 at 10:28:59AM -0600, Chris J Arges wrote:
> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol will be used for patching if it is
> valid. Finally, old_addr is now an internal structure element and not to
> be specified by the user.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  include/linux/livepatch.h | 20 ++++++++++--------
>  kernel/livepatch/core.c   | 53 +++++++++++++++++++++++------------------------
>  2 files changed, 37 insertions(+), 36 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 31db7a0..df7b752 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -37,8 +37,9 @@ enum klp_state {
>   * 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_addr:	a hint conveying at what address the old function
> - *		can be found (optional, vmlinux patches only)
> + * @old_sympos: a hint indicating which symbol position the old function
> + *		can be found (optional)
> + * @old_addr:	the address of the function being patched
>   * @kobj:	kobject for sysfs resources
>   * @state:	tracks function-level patch application state
>   * @stack_node:	list node for klp_ops func_stack list
> @@ -47,17 +48,18 @@ struct klp_func {
>  	/* external */
>  	const char *old_name;
>  	void *new_func;
> +
>  	/*
> -	 * The old_addr field is optional and can be used to resolve
> -	 * duplicate symbol names in the vmlinux object.  If this
> -	 * information is not present, the symbol is located by name
> -	 * with kallsyms. If the name is not unique and old_addr is
> -	 * not provided, the patch application fails as there is no
> -	 * way to resolve the ambiguity.
> +	 * The old_sympos field is optional and can be used to resolve
> +	 * duplicate symbol names in livepatch objects. If this field is zero,
> +	 * it is expected the symbol is unique, otherwise patching fails. If
> +	 * this value is greater than zero then that occurrence of the symbol
> +	 * in kallsyms is used.

I would clarify this:

...occurrence of the symbol in kallsyms *for the given object* is used.

>  	 */
> -	unsigned long old_addr;
> +	unsigned long old_sympos;
>  
>  	/* internal */
> +	unsigned long old_addr;
>  	struct kobject kobj;
>  	enum klp_state state;
>  	struct list_head stack_node;
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..26f9778 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -142,6 +142,7 @@ struct klp_find_arg {
>  	 * name in the same object.
>  	 */
>  	unsigned long count;
> +	unsigned long pos;

There's a comment above this that says:

	/*
	 * If count == 0, the symbol was not found. If count == 1, a unique
	 * match was found and addr is set.  If count > 1, there is
	 * unresolvable ambiguity among "count" number of symbols with the same
	 * name in the same object.
	 */

That comment is no longer accurate and can probably be removed since IMO
the purpose of 'count' is obvious.

>  };
>  
>  static int klp_find_callback(void *data, const char *name,
> @@ -159,36 +160,45 @@ static int klp_find_callback(void *data, const char *name,
>  		return 0;
>  
>  	/*
> -	 * args->addr might be overwritten if another match is found
> -	 * but klp_find_object_symbol() handles this and only returns the
> -	 * addr if count == 1.
> +	 * increment and assign address, return only if checking pos and
> +	 * it matches count.
>  	 */
> -	args->addr = addr;
>  	args->count++;
> +	args->addr = addr;
> +	if ((args->pos > 0) && (args->count == args->pos))
> +		return 1;
>  
>  	return 0;
>  }
>  
>  static int klp_find_object_symbol(const char *objname, const char *name,
> -				  unsigned long *addr)
> +				  unsigned long *addr, unsigned long sympos)
>  {
>  	struct klp_find_arg args = {
>  		.objname = objname,
>  		.name = name,
>  		.addr = 0,
> -		.count = 0
> +		.count = 0,
> +		.pos = sympos,
>  	};
>  
>  	mutex_lock(&module_mutex);
>  	kallsyms_on_each_symbol(klp_find_callback, &args);
>  	mutex_unlock(&module_mutex);
>  
> -	if (args.count == 0)
> +	/*
> +	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
> +	 * otherwise ensure the symbol position count matches sympos.
> +	 */
> +	if (args.addr == 0)
>  		pr_err("symbol '%s' not found in symbol table\n", name);
> -	else if (args.count > 1)
> +	else if (args.count > 1 && sympos == 0) {
>  		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
>  		       args.count, name, objname);
> -	else {
> +	} else if (sympos != args.count && sympos > 0) {
> +		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
> +		       sympos, name, objname ? objname : "vmlinux");
> +	} else {
>  		*addr = args.addr;
>  		return 0;
>  	}
> @@ -239,22 +249,11 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
>  static int klp_find_verify_func_addr(struct klp_object *obj,
>  				     struct klp_func *func)
>  {
> -	int ret;
> -
> -#if defined(CONFIG_RANDOMIZE_BASE)
> -	/* If KASLR has been enabled, adjust old_addr accordingly */
> -	if (kaslr_enabled() && func->old_addr)
> -		func->old_addr += kaslr_offset();
> -#endif
> -
> -	if (!func->old_addr || klp_is_module(obj))
> -		ret = klp_find_object_symbol(obj->name, func->old_name,
> -					     &func->old_addr);
> -	else
> -		ret = klp_verify_vmlinux_symbol(func->old_name,
> -						func->old_addr);
> -
> -	return ret;
> +	/*
> +	 * Verify the symbol, find old_addr, and write it to the structure.
> +	 */
> +	return klp_find_object_symbol(obj->name, func->old_name,
> +				      &func->old_addr, func->old_sympos);

klp_find_verify_func_addr() is no longer correctly named and can
probably be removed since klp_init_object_loaded() can call
klp_find_object_symbol() directly.

>  }
>  
>  /*
> @@ -277,7 +276,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>  	preempt_enable();
>  
>  	/* otherwise check if it's in another .o within the patch module */
> -	return klp_find_object_symbol(pmod->name, name, addr);
> +	return klp_find_object_symbol(pmod->name, name, addr, 0);
>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> @@ -307,7 +306,7 @@ static int klp_write_object_relocations(struct module *pmod,
>  			else
>  				ret = klp_find_object_symbol(obj->mod->name,
>  							     reloc->name,
> -							     &reloc->val);
> +							     &reloc->val, 0);
>  			if (ret)
>  				return ret;
>  		}
> -- 
> 1.9.1
> 

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-11 16:29                   ` [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc Chris J Arges
  2015-11-11 16:39                     ` Chris J Arges
@ 2015-11-11 17:57                     ` Josh Poimboeuf
  2015-11-12 14:31                       ` Petr Mladek
  2015-11-12 10:23                     ` Miroslav Benes
  2 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-11 17:57 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-kernel

On Wed, Nov 11, 2015 at 10:29:00AM -0600, Chris J Arges wrote:
> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default old_sympos will be 0, and patching will only succeed if
> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol will be used for patching if it is valid.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  include/linux/livepatch.h |  5 ++--
>  kernel/livepatch/core.c   | 74 ++++++++++-------------------------------------
>  2 files changed, 18 insertions(+), 61 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index df7b752..fb968a2 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -68,8 +68,8 @@ struct klp_func {
>  /**
>   * struct klp_reloc - relocation structure for live patching
>   * @loc:	address where the relocation will be written
> - * @val:	address of the referenced symbol (optional,
> - *		vmlinux	patches only)
> + * @val:	address of the referenced symbol
> + * @sympos:     position in kallsyms to disambiguate symbols (optional)
>   * @type:	ELF relocation type
>   * @name:	name of the referenced symbol (for lookup/verification)
>   * @addend:	offset from the referenced symbol
> @@ -78,6 +78,7 @@ struct klp_func {
>  struct klp_reloc {
>  	unsigned long loc;
>  	unsigned long val;
> +	unsigned long sympos;
>  	unsigned long type;
>  	const char *name;
>  	int addend;

I think 'val' can be removed from this struct, since it's now basically
just a private variable of klp_write_object_relocations().

> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 26f9778..4eb8691 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -207,45 +207,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
>  	return -EINVAL;
>  }
>  
> -struct klp_verify_args {
> -	const char *name;
> -	const unsigned long addr;
> -};
> -
> -static int klp_verify_callback(void *data, const char *name,
> -			       struct module *mod, unsigned long addr)
> -{
> -	struct klp_verify_args *args = data;
> -
> -	if (!mod &&
> -	    !strcmp(args->name, name) &&
> -	    args->addr == addr)
> -		return 1;
> -
> -	return 0;
> -}
> -
> -static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
> -{
> -	struct klp_verify_args args = {
> -		.name = name,
> -		.addr = addr,
> -	};
> -	int ret;
> -
> -	mutex_lock(&module_mutex);
> -	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
> -	mutex_unlock(&module_mutex);
> -
> -	if (!ret) {
> -		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
> -			name, addr);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  static int klp_find_verify_func_addr(struct klp_object *obj,
>  				     struct klp_func *func)
>  {
> @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
>   * object is either vmlinux or the kmod being patched).
>   */
>  static int klp_find_external_symbol(struct module *pmod, const char *name,
> -				    unsigned long *addr)
> +				    unsigned long *addr, unsigned long sympos)
>  {
>  	const struct kernel_symbol *sym;
>  

For "external" symbols, the object isn't specified by the user, and
since sympos is per-object, the value of sympos is undefined.   Instead
I think it should always pass 0 to klp_find_object_symbol() below.

In line with that, since reloc->external and reloc->sympos don't mix,
maybe klp_write_object_relocations() should return -EINVAL if external
is set and sympos is non-zero.

> @@ -276,7 +237,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>  	preempt_enable();
>  
>  	/* otherwise check if it's in another .o within the patch module */
> -	return klp_find_object_symbol(pmod->name, name, addr, 0);
> +	return klp_find_object_symbol(pmod->name, name, addr, sympos);
>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> @@ -292,24 +253,19 @@ static int klp_write_object_relocations(struct module *pmod,
>  		return -EINVAL;
>  
>  	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     &reloc->val, 0);
> -			if (ret)
> -				return ret;
> -		}
> +		/* reloc->val needs to be discovered */
> +		if (reloc->external)
> +			ret = klp_find_external_symbol(pmod,
> +						       reloc->name,
> +						       &reloc->val,
> +						       reloc->sympos);
> +		else
> +			ret = klp_find_object_symbol(obj->mod->name,
> +						     reloc->name,
> +						     &reloc->val,
> +						     reloc->sympos);
> +		if (ret)
> +			return ret;
>  		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
>  					     reloc->val + reloc->addend);
>  		if (ret) {
> -- 
> 1.9.1

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 3/3 v4] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-11 18:01                       ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-11 18:01 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-api, linux-kernel

On Wed, Nov 11, 2015 at 10:29:01AM -0600, Chris J Arges wrote:
> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function,number>
> 
> The number corresponds to the nth occurrence of the symbol name in
> kallsyms for the patched object.
> 
> An example of patching multiple symbols can be found here:
> 	https://github.com/dynup/kpatch/issues/493

Instead of 'function,number' here and everywhere else, maybe
'function,sympos' would be a little clearer.

Also, s/old_name/function/ in the patch subject to be consistent.

> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
>  kernel/livepatch/core.c                          | 10 ++++++++--
>  2 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> index 5bf42a8..21b6bc1 100644
> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> @@ -33,7 +33,7 @@ Description:
>  		The object directory contains subdirectories for each function
>  		that is patched within the object.
>  
> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> +What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
>  Date:		Nov 2014
>  KernelVersion:	3.19.0
>  Contact:	live-patching@vger.kernel.org
> @@ -41,4 +41,8 @@ Description:
>  		The function directory contains attributes regarding the
>  		properties and state of the patched function.
>  
> +		The directory name contains the patched function name and a
> +		number corresponding to the nth occurrence of the symbol name
> +		in kallsyms for the patched object.
> +
>  		There are currently no such attributes.
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 4eb8691..ed2cbbf 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -542,7 +542,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>   * /sys/kernel/livepatch/<patch>
>   * /sys/kernel/livepatch/<patch>/enabled
>   * /sys/kernel/livepatch/<patch>/<object>
> - * /sys/kernel/livepatch/<patch>/<object>/<func>
> + * /sys/kernel/livepatch/<patch>/<object>/<func,number>
>   */
>  
>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> @@ -687,8 +687,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
> +	/* The format for the sysfs directory is <func,number> where number is
> +	 * the occurrence of this symbol in kallsyms. If the user selects 0 for

... of this symbol in kallsyms *for the patched object*.

> +	 * old_sympos, then 1 will be used since a unique symbol will be the
> +	 * first occurrence.
> +	 */
>  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +				    &obj->kobj, "%s,%lu", func->old_name,
> +				    func->old_sympos ? func->old_sympos : 1);
>  }
>  
>  /* parts of the initialization that is done only when the object is loaded */
> -- 
> 1.9.1

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 3/3 v4] livepatch: old_name,number scheme in livepatch sysfs directory
@ 2015-11-11 18:01                       ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-11 18:01 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching-u79uwXL29TY76Z2rM5mHXA,
	jeyu-H+wXaHxf7aLQT0dZR+AlfA, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Wed, Nov 11, 2015 at 10:29:01AM -0600, Chris J Arges wrote:
> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function,number>
> 
> The number corresponds to the nth occurrence of the symbol name in
> kallsyms for the patched object.
> 
> An example of patching multiple symbols can be found here:
> 	https://github.com/dynup/kpatch/issues/493

Instead of 'function,number' here and everywhere else, maybe
'function,sympos' would be a little clearer.

Also, s/old_name/function/ in the patch subject to be consistent.

> Signed-off-by: Chris J Arges <chris.j.arges-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
> ---
>  Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
>  kernel/livepatch/core.c                          | 10 ++++++++--
>  2 files changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
> index 5bf42a8..21b6bc1 100644
> --- a/Documentation/ABI/testing/sysfs-kernel-livepatch
> +++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
> @@ -33,7 +33,7 @@ Description:
>  		The object directory contains subdirectories for each function
>  		that is patched within the object.
>  
> -What:		/sys/kernel/livepatch/<patch>/<object>/<function>
> +What:		/sys/kernel/livepatch/<patch>/<object>/<function,number>
>  Date:		Nov 2014
>  KernelVersion:	3.19.0
>  Contact:	live-patching-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> @@ -41,4 +41,8 @@ Description:
>  		The function directory contains attributes regarding the
>  		properties and state of the patched function.
>  
> +		The directory name contains the patched function name and a
> +		number corresponding to the nth occurrence of the symbol name
> +		in kallsyms for the patched object.
> +
>  		There are currently no such attributes.
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 4eb8691..ed2cbbf 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -542,7 +542,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
>   * /sys/kernel/livepatch/<patch>
>   * /sys/kernel/livepatch/<patch>/enabled
>   * /sys/kernel/livepatch/<patch>/<object>
> - * /sys/kernel/livepatch/<patch>/<object>/<func>
> + * /sys/kernel/livepatch/<patch>/<object>/<func,number>
>   */
>  
>  static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
> @@ -687,8 +687,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
>  	INIT_LIST_HEAD(&func->stack_node);
>  	func->state = KLP_DISABLED;
>  
> +	/* The format for the sysfs directory is <func,number> where number is
> +	 * the occurrence of this symbol in kallsyms. If the user selects 0 for

... of this symbol in kallsyms *for the patched object*.

> +	 * old_sympos, then 1 will be used since a unique symbol will be the
> +	 * first occurrence.
> +	 */
>  	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
> -				    &obj->kobj, "%s", func->old_name);
> +				    &obj->kobj, "%s,%lu", func->old_name,
> +				    func->old_sympos ? func->old_sympos : 1);
>  }
>  
>  /* parts of the initialization that is done only when the object is loaded */
> -- 
> 1.9.1

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-11 16:28                   ` [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-11 17:43                     ` Josh Poimboeuf
@ 2015-11-12 10:22                     ` Miroslav Benes
  1 sibling, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-12 10:22 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel


Next to Josh's remarks I have some more (mainly nitpicks, so it is often 
up to you).

On Wed, 11 Nov 2015, Chris J Arges wrote:

> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol will be used for patching if it is

"...occurrence of the symbol in kallsyms for the patched object will 
be used..."

Just to have it even in the changelog for clarity.

> valid. Finally, old_addr is now an internal structure element and not to
> be specified by the user.


> @@ -159,36 +160,45 @@ static int klp_find_callback(void *data, const char *name,
>  		return 0;
>  
>  	/*
> -	 * args->addr might be overwritten if another match is found
> -	 * but klp_find_object_symbol() handles this and only returns the
> -	 * addr if count == 1.
> +	 * increment and assign address, return only if checking pos and
> +	 * it matches count.
>  	 */
> -	args->addr = addr;
>  	args->count++;
> +	args->addr = addr;

I guess that this row swap is remnant of a rebase. Anyway it is 
superfluous.

> +	if ((args->pos > 0) && (args->count == args->pos))
> +		return 1;

We could add an optimization here. If args->pos == 0 and args->count > 1 
we can return 1, because the symbol is not unique. The case is then 
correctly handled in klp_find_object_symbol. There is no need to walk 
through the rest of kallsyms.

Thanks,
Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-11 16:29                   ` [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc Chris J Arges
  2015-11-11 16:39                     ` Chris J Arges
  2015-11-11 17:57                     ` Josh Poimboeuf
@ 2015-11-12 10:23                     ` Miroslav Benes
  2 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-12 10:23 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Wed, 11 Nov 2015, Chris J Arges wrote:

> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default old_sympos will be 0, and patching will only succeed if
> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol will be used for patching if it is valid.

Again "...occurrence of the symbol in kallsyms for the patched object 
will be used..."

>  2 files changed, 18 insertions(+), 61 deletions(-)

And this is indeed great.

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-11 17:57                     ` Josh Poimboeuf
@ 2015-11-12 14:31                       ` Petr Mladek
  2015-11-12 19:19                         ` Josh Poimboeuf
  0 siblings, 1 reply; 104+ messages in thread
From: Petr Mladek @ 2015-11-12 14:31 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Wed 2015-11-11 11:57:31, Josh Poimboeuf wrote:
> On Wed, Nov 11, 2015 at 10:29:00AM -0600, Chris J Arges wrote:
> > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > index 26f9778..4eb8691 100644
> > --- a/kernel/livepatch/core.c
> > +++ b/kernel/livepatch/core.c
> > @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
> >   * object is either vmlinux or the kmod being patched).
> >   */
> >  static int klp_find_external_symbol(struct module *pmod, const char *name,
> > -				    unsigned long *addr)
> > +				    unsigned long *addr, unsigned long sympos)
> >  {
> >  	const struct kernel_symbol *sym;
> >  
> 
> For "external" symbols, the object isn't specified by the user, and
> since sympos is per-object, the value of sympos is undefined.   Instead
> I think it should always pass 0 to klp_find_object_symbol() below.

Heh, I always had troubles to understand the meaning of
this external stuff.

> In line with that, since reloc->external and reloc->sympos don't mix,
> maybe klp_write_object_relocations() should return -EINVAL if external
> is set and sympos is non-zero.
> 
> > @@ -276,7 +237,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
> >  	preempt_enable();
> >  
> >  	/* otherwise check if it's in another .o within the patch module */
> > -	return klp_find_object_symbol(pmod->name, name, addr, 0);
> > +	return klp_find_object_symbol(pmod->name, name, addr, sympos);
> >  }

Please, do you have an example when this code will be used?
Do we really need to relocate symbols within the patch module this
way?

My understanding is that it would be used to relocate symbols
between various .o files that are used to produce the patch module.
IMHO, the only situation is that you want to access a static
symbol from another .o file. But this is not used in normal modules.
It does not look like a real life scenario.

It is indepednt on this patch set but it might make it easier.
What about doing this cleaup, first?


>From 095f74fb92205177b138bb6215e4e5fd59dca8db Mon Sep 17 00:00:00 2001
From: Petr Mladek <pmladek@suse.com>
Date: Thu, 12 Nov 2015 15:11:00 +0100
Subject: [PATCH] livepatch: Simplify code for relocated external symbols

The livepatch module might be linked from several .o files.
All symbols that need to be shared between these .o files
should be exported. This is a normal programming practice.
I do not see any reason to access static symbols between
these .o files.

This patch removes the search for the static symbols within
the livepatch module. It makes it easier to understand
the meaning of the external flag and klp_find_external_symbol()
function.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 include/linux/livepatch.h |  3 ++-
 kernel/livepatch/core.c   | 12 +++++-------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a05dd36..77b84732ee05 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -71,7 +71,8 @@ struct klp_func {
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
- * @external:	symbol is either exported or within the live patch module itself
+ * @external:	set for external symbols that are accessed from this object
+ *		but defined outside; they must be exported
  */
 struct klp_reloc {
 	unsigned long loc;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e5344112419..138f11420883 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -258,26 +258,24 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
 }
 
 /*
- * external symbols are located outside the parent object (where the parent
- * object is either vmlinux or the kmod being patched).
+ * External symbols are exported symbols that are defined outside both
+ * the patched object and the patch.
  */
 static int klp_find_external_symbol(struct module *pmod, const char *name,
 				    unsigned long *addr)
 {
 	const struct kernel_symbol *sym;
+	int ret = -EINVAL;
 
-	/* first, check if it's an exported symbol */
 	preempt_disable();
 	sym = find_symbol(name, NULL, NULL, true, true);
 	if (sym) {
 		*addr = sym->value;
-		preempt_enable();
-		return 0;
+		ret = 0;
 	}
 	preempt_enable();
 
-	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	return ret;
 }
 
 static int klp_write_object_relocations(struct module *pmod,
-- 
1.8.5.6


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func
       [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
@ 2015-11-12 16:59                     ` Chris J Arges
  2015-11-12 19:45                       ` Josh Poimboeuf
                                         ` (3 more replies)
  2015-11-12 16:59                     ` [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols Chris J Arges
                                       ` (3 subsequent siblings)
  4 siblings, 4 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-12 16:59 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

In cases of duplicate symbols, old_sympos will be used to disambiguate
instead of old_addr. By default old_sympos will be 0, and patching will
only succeed if the symbol is unique. Specifying a positive value will
ensure that occurrence of the symbol in kallsyms for the patched object
will be used for patching if it is valid.

In addition, make old_addr an internal structure field not to be specified
by the user. Finally, remove klp_find_verify_func_addr as it can be
replaced by klp_find_object_symbol directly.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h | 20 ++++++++-------
 kernel/livepatch/core.c   | 65 ++++++++++++++++++++---------------------------
 2 files changed, 38 insertions(+), 47 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..3d18dff 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
- *		can be found (optional, vmlinux patches only)
+ * @old_sympos: a hint indicating which symbol position the old function
+ *		can be found (optional)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -47,17 +48,18 @@ struct klp_func {
 	/* external */
 	const char *old_name;
 	void *new_func;
+
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve
+	 * duplicate symbol names in livepatch objects. If this field is zero,
+	 * it is expected the symbol is unique, otherwise patching fails. If
+	 * this value is greater than zero then that occurrence of the symbol
+	 * in kallsyms for the given object is used.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..479d75e 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -135,13 +135,8 @@ struct klp_find_arg {
 	const char *objname;
 	const char *name;
 	unsigned long addr;
-	/*
-	 * If count == 0, the symbol was not found. If count == 1, a unique
-	 * match was found and addr is set.  If count > 1, there is
-	 * unresolvable ambiguity among "count" number of symbols with the same
-	 * name in the same object.
-	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -159,36 +154,46 @@ static int klp_find_callback(void *data, const char *name,
 		return 0;
 
 	/*
-	 * args->addr might be overwritten if another match is found
-	 * but klp_find_object_symbol() handles this and only returns the
-	 * addr if count == 1.
+	 * Increment and assign the address. Return 1 when the desired symbol
+	 * position is found or the search for a unique symbol fails.
 	 */
 	args->addr = addr;
 	args->count++;
+	if (((args->pos > 0) && (args->count == args->pos)) ||
+	    ((args->pos == 0) && (args->count > 1)))
+		return 1;
 
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long *addr, unsigned long sympos)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
+	 * otherwise ensure the symbol position count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
+	else if (args.count > 1 && sympos == 0) {
 		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 		       args.count, name, objname);
-	else {
+	} else if (sympos != args.count && sympos > 0) {
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
+	} else {
 		*addr = args.addr;
 		return 0;
 	}
@@ -236,27 +241,6 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 	return 0;
 }
 
-static int klp_find_verify_func_addr(struct klp_object *obj,
-				     struct klp_func *func)
-{
-	int ret;
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
-
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
-
-	return ret;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -277,7 +261,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	preempt_enable();
 
 	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	return klp_find_object_symbol(pmod->name, name, addr, 0);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +291,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     &reloc->val, 0);
 			if (ret)
 				return ret;
 		}
@@ -749,8 +733,13 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 			return ret;
 	}
 
+	/*
+	 * Verify the symbol, find old_addr, and write it to the structure.
+	 */
 	klp_for_each_func(obj, func) {
-		ret = klp_find_verify_func_addr(obj, func);
+		ret = klp_find_object_symbol(obj->name, func->old_name,
+					     &func->old_addr,
+					     func->old_sympos);
 		if (ret)
 			return ret;
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols
       [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-12 16:59                     ` Chris J Arges
  2015-11-13 10:24                       ` Miroslav Benes
  2015-11-12 16:59                     ` [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
                                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-12 16:59 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Petr Mladek, Chris J Arges, Josh Poimboeuf, Seth Jennings,
	Jiri Kosina, Vojtech Pavlik, linux-kernel

From: Petr Mladek <pmladek@suse.com>

The livepatch module might be linked from several .o files.
All symbols that need to be shared between these .o files
should be exported. This is a normal programming practice.
I do not see any reason to access static symbols between
these .o files.

This patch removes the search for the static symbols within
the livepatch module. It makes it easier to understand
the meaning of the external flag and klp_find_external_symbol()
function.

Signed-off-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  3 ++-
 kernel/livepatch/core.c   | 12 +++++-------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 3d18dff..9808dd4 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -73,7 +73,8 @@ struct klp_func {
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
- * @external:	symbol is either exported or within the live patch module itself
+ * @external:	set for external symbols that are accessed from this object
+ *		but defined outside; they must be exported
  */
 struct klp_reloc {
 	unsigned long loc;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 479d75e..4cd079c 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -242,26 +242,24 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 }
 
 /*
- * external symbols are located outside the parent object (where the parent
- * object is either vmlinux or the kmod being patched).
+ * External symbols are exported symbols that are defined outside both
+ * the patched object and the patch.
  */
 static int klp_find_external_symbol(struct module *pmod, const char *name,
 				    unsigned long *addr)
 {
 	const struct kernel_symbol *sym;
+	int ret = -EINVAL;
 
-	/* first, check if it's an exported symbol */
 	preempt_disable();
 	sym = find_symbol(name, NULL, NULL, true, true);
 	if (sym) {
 		*addr = sym->value;
-		preempt_enable();
-		return 0;
+		ret = 0;
 	}
 	preempt_enable();
 
-	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr, 0);
+	return ret;
 }
 
 static int klp_write_object_relocations(struct module *pmod,
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc
       [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-12 16:59                     ` [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols Chris J Arges
@ 2015-11-12 16:59                     ` Chris J Arges
  2015-11-12 19:50                       ` Josh Poimboeuf
  2015-11-13 16:42                       ` Petr Mladek
  2015-11-12 16:59                     ` [PATCH 4/4 v5] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
       [not found]                     ` <1447431804-18786-1-git-send-email-chris.j.arges@canonical.com>
  4 siblings, 2 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-12 16:59 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

In cases of duplicate symbols, sympos will be used to disambiguate instead
of val. By default sympos will be 0, and patching will only succeed if
the symbol is unique. Specifying a positive value will ensure that
occurrence of the symbol in kallsyms for the patched object will be used
for patching if it is valid.

Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
as they are no longer used.

>From the klp_reloc structure remove val, as it can be refactored as a
local variable in klp_write_object_relocations.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  5 ++-
 kernel/livepatch/core.c   | 81 +++++++++++++----------------------------------
 2 files changed, 24 insertions(+), 62 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 9808dd4..9149de4 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -68,8 +68,7 @@ struct klp_func {
 /**
  * struct klp_reloc - relocation structure for live patching
  * @loc:	address where the relocation will be written
- * @val:	address of the referenced symbol (optional,
- *		vmlinux	patches only)
+ * @sympos:	position in kallsyms to disambiguate symbols (optional)
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
@@ -78,7 +77,7 @@ struct klp_func {
  */
 struct klp_reloc {
 	unsigned long loc;
-	unsigned long val;
+	unsigned long sympos;
 	unsigned long type;
 	const char *name;
 	int addend;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 4cd079c..071895f 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -202,45 +202,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
 	return -EINVAL;
 }
 
-struct klp_verify_args {
-	const char *name;
-	const unsigned long addr;
-};
-
-static int klp_verify_callback(void *data, const char *name,
-			       struct module *mod, unsigned long addr)
-{
-	struct klp_verify_args *args = data;
-
-	if (!mod &&
-	    !strcmp(args->name, name) &&
-	    args->addr == addr)
-		return 1;
-
-	return 0;
-}
-
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
-{
-	struct klp_verify_args args = {
-		.name = name,
-		.addr = addr,
-	};
-	int ret;
-
-	mutex_lock(&module_mutex);
-	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
-	mutex_unlock(&module_mutex);
-
-	if (!ret) {
-		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
-			name, addr);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /*
  * External symbols are exported symbols that are defined outside both
  * the patched object and the patch.
@@ -266,6 +227,7 @@ static int klp_write_object_relocations(struct module *pmod,
 					struct klp_object *obj)
 {
 	int ret;
+	unsigned long val;
 	struct klp_reloc *reloc;
 
 	if (WARN_ON(!klp_is_object_loaded(obj)))
@@ -275,29 +237,30 @@ static int klp_write_object_relocations(struct module *pmod,
 		return -EINVAL;
 
 	for (reloc = obj->relocs; reloc->name; reloc++) {
-		if (!klp_is_module(obj)) {
-			ret = klp_verify_vmlinux_symbol(reloc->name,
-							reloc->val);
-			if (ret)
-				return ret;
-		} else {
-			/* module, reloc->val needs to be discovered */
-			if (reloc->external)
-				ret = klp_find_external_symbol(pmod,
-							       reloc->name,
-							       &reloc->val);
-			else
-				ret = klp_find_object_symbol(obj->mod->name,
-							     reloc->name,
-							     &reloc->val, 0);
-			if (ret)
-				return ret;
-		}
+		/* discover the address of the referenced symbol */
+		if (reloc->external) {
+			/*
+			 * external symbols aren't specified by the user
+			 * therefore sympos should not be used
+			 */
+			if (reloc->sympos) {
+				pr_err("symbol '%s' is external and has sympos %lu\n",
+				       reloc->name, reloc->sympos);
+				return -EINVAL;
+			}
+			ret = klp_find_external_symbol(pmod, reloc->name, &val);
+		} else
+			ret = klp_find_object_symbol(obj->mod->name,
+						     reloc->name,
+						     &val,
+						     reloc->sympos);
+		if (ret)
+			return ret;
 		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
-					     reloc->val + reloc->addend);
+					     val + reloc->addend);
 		if (ret) {
 			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
-			       reloc->name, reloc->val, ret);
+			       reloc->name, val, ret);
 			return ret;
 		}
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 4/4 v5] livepatch: function,sympos scheme in livepatch sysfs directory
       [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
                                       ` (2 preceding siblings ...)
  2015-11-12 16:59                     ` [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-12 16:59                     ` Chris J Arges
       [not found]                     ` <1447431804-18786-1-git-send-email-chris.j.arges@canonical.com>
  4 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-12 16:59 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function,sympos>

The sympos number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
 kernel/livepatch/core.c                          | 10 ++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..da87f43 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,sympos>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		sympos number corresponding to the nth occurrence of the symbol
+		name in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 071895f..4a59402 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -532,7 +532,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -677,8 +677,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
+	/* The format for the sysfs directory is <function,sympos> where sympos
+	 * is the nth occurrence of this symbol in kallsyms for the patched
+	 * object. If the user selects 0 for old_sympos, then 1 will be used
+	 * since a unique symbol will be the first occurrence.
+	 */
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 1);
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-12 14:31                       ` Petr Mladek
@ 2015-11-12 19:19                         ` Josh Poimboeuf
  2015-11-13 13:54                           ` Petr Mladek
  0 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-12 19:19 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Thu, Nov 12, 2015 at 03:31:58PM +0100, Petr Mladek wrote:
> On Wed 2015-11-11 11:57:31, Josh Poimboeuf wrote:
> > On Wed, Nov 11, 2015 at 10:29:00AM -0600, Chris J Arges wrote:
> > > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > > index 26f9778..4eb8691 100644
> > > --- a/kernel/livepatch/core.c
> > > +++ b/kernel/livepatch/core.c
> > > @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
> > >   * object is either vmlinux or the kmod being patched).
> > >   */
> > >  static int klp_find_external_symbol(struct module *pmod, const char *name,
> > > -				    unsigned long *addr)
> > > +				    unsigned long *addr, unsigned long sympos)
> > >  {
> > >  	const struct kernel_symbol *sym;
> > >  
> > 
> > For "external" symbols, the object isn't specified by the user, and
> > since sympos is per-object, the value of sympos is undefined.   Instead
> > I think it should always pass 0 to klp_find_object_symbol() below.
> 
> Heh, I always had troubles to understand the meaning of
> this external stuff.
> 
> > In line with that, since reloc->external and reloc->sympos don't mix,
> > maybe klp_write_object_relocations() should return -EINVAL if external
> > is set and sympos is non-zero.
> > 
> > > @@ -276,7 +237,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
> > >  	preempt_enable();
> > >  
> > >  	/* otherwise check if it's in another .o within the patch module */
> > > -	return klp_find_object_symbol(pmod->name, name, addr, 0);
> > > +	return klp_find_object_symbol(pmod->name, name, addr, sympos);
> > >  }
> 
> Please, do you have an example when this code will be used?
> Do we really need to relocate symbols within the patch module this
> way?
> 
> My understanding is that it would be used to relocate symbols
> between various .o files that are used to produce the patch module.
> IMHO, the only situation is that you want to access a static
> symbol from another .o file. But this is not used in normal modules.
> It does not look like a real life scenario.

I think I originated the 'external' concept, but I'm also not a fan of
it.  If we can find a way to get rid of it or improve it, that would be
great.

There are two cases for external symbols:

1. Accessing a global symbol in another .o file in the patch module.
   For an example of a patch which does this, see:

     https://github.com/dynup/kpatch/blob/master/test/integration/f22/module-call-external.patch

   In that example, notice that kpatch_string() function is global (not
   static), and is not exported.  It *is* actually a real world
   scenario.

   But I do think we're currently handling it wrong.  kpatch-build isn't
   smart enough to determine the difference between the use of an
   exported symbol and a global one that's in another .o in the module.
   We can probably fix that by looking at Module.symvers.  So I think we
   can get rid of this case.

2. Accessing an exported symbol which lives in a module.

   With Chris's patches, we now don't have any ambiguity for specifying
   module symbols, so I think we can get rid of this case too.

So I *think* we can get rid of 'external' completely.  But I could be
overlooking something.  I'd rather implement the change in kpatch-build
first to make 100% sure we can actually get rid of it.

Also, I'd ask that we hold off on this patch for now until we get a
chance to add support for it in kpatch-build.  Then at that point we can
just remove all the 'external' stuff.

> It is indepednt on this patch set but it might make it easier.
> What about doing this cleaup, first?
> 
> 
> From 095f74fb92205177b138bb6215e4e5fd59dca8db Mon Sep 17 00:00:00 2001
> From: Petr Mladek <pmladek@suse.com>
> Date: Thu, 12 Nov 2015 15:11:00 +0100
> Subject: [PATCH] livepatch: Simplify code for relocated external symbols
> 
> The livepatch module might be linked from several .o files.
> All symbols that need to be shared between these .o files
> should be exported. This is a normal programming practice.
> I do not see any reason to access static symbols between
> these .o files.
> 
> This patch removes the search for the static symbols within
> the livepatch module. It makes it easier to understand
> the meaning of the external flag and klp_find_external_symbol()
> function.
> 
> Signed-off-by: Petr Mladek <pmladek@suse.com>
> ---
>  include/linux/livepatch.h |  3 ++-
>  kernel/livepatch/core.c   | 12 +++++-------
>  2 files changed, 7 insertions(+), 8 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 31db7a05dd36..77b84732ee05 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -71,7 +71,8 @@ struct klp_func {
>   * @type:	ELF relocation type
>   * @name:	name of the referenced symbol (for lookup/verification)
>   * @addend:	offset from the referenced symbol
> - * @external:	symbol is either exported or within the live patch module itself
> + * @external:	set for external symbols that are accessed from this object
> + *		but defined outside; they must be exported
>   */
>  struct klp_reloc {
>  	unsigned long loc;
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e5344112419..138f11420883 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -258,26 +258,24 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
>  }
>  
>  /*
> - * external symbols are located outside the parent object (where the parent
> - * object is either vmlinux or the kmod being patched).
> + * External symbols are exported symbols that are defined outside both
> + * the patched object and the patch.
>   */
>  static int klp_find_external_symbol(struct module *pmod, const char *name,
>  				    unsigned long *addr)
>  {
>  	const struct kernel_symbol *sym;
> +	int ret = -EINVAL;
>  
> -	/* first, check if it's an exported symbol */
>  	preempt_disable();
>  	sym = find_symbol(name, NULL, NULL, true, true);
>  	if (sym) {
>  		*addr = sym->value;
> -		preempt_enable();
> -		return 0;
> +		ret = 0;
>  	}
>  	preempt_enable();
>  
> -	/* otherwise check if it's in another .o within the patch module */
> -	return klp_find_object_symbol(pmod->name, name, addr);
> +	return ret;
>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> -- 
> 1.8.5.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe live-patching" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-12 19:45                       ` Josh Poimboeuf
  2015-11-13  9:56                       ` Jiri Kosina
                                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-12 19:45 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-kernel

On Thu, Nov 12, 2015 at 10:59:50AM -0600, Chris J Arges wrote:
> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol in kallsyms for the patched object
> will be used for patching if it is valid.
> 
> In addition, make old_addr an internal structure field not to be specified
> by the user. Finally, remove klp_find_verify_func_addr as it can be
> replaced by klp_find_object_symbol directly.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  include/linux/livepatch.h | 20 ++++++++-------
>  kernel/livepatch/core.c   | 65 ++++++++++++++++++++---------------------------
>  2 files changed, 38 insertions(+), 47 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 31db7a0..3d18dff 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -37,8 +37,9 @@ enum klp_state {
>   * 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_addr:	a hint conveying at what address the old function
> - *		can be found (optional, vmlinux patches only)
> + * @old_sympos: a hint indicating which symbol position the old function
> + *		can be found (optional)
> + * @old_addr:	the address of the function being patched
>   * @kobj:	kobject for sysfs resources
>   * @state:	tracks function-level patch application state
>   * @stack_node:	list node for klp_ops func_stack list
> @@ -47,17 +48,18 @@ struct klp_func {
>  	/* external */
>  	const char *old_name;
>  	void *new_func;
> +
>  	/*
> -	 * The old_addr field is optional and can be used to resolve
> -	 * duplicate symbol names in the vmlinux object.  If this
> -	 * information is not present, the symbol is located by name
> -	 * with kallsyms. If the name is not unique and old_addr is
> -	 * not provided, the patch application fails as there is no
> -	 * way to resolve the ambiguity.
> +	 * The old_sympos field is optional and can be used to resolve
> +	 * duplicate symbol names in livepatch objects. If this field is zero,
> +	 * it is expected the symbol is unique, otherwise patching fails. If
> +	 * this value is greater than zero then that occurrence of the symbol
> +	 * in kallsyms for the given object is used.
>  	 */
> -	unsigned long old_addr;
> +	unsigned long old_sympos;
>  
>  	/* internal */
> +	unsigned long old_addr;
>  	struct kobject kobj;
>  	enum klp_state state;
>  	struct list_head stack_node;
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..479d75e 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -135,13 +135,8 @@ struct klp_find_arg {
>  	const char *objname;
>  	const char *name;
>  	unsigned long addr;
> -	/*
> -	 * If count == 0, the symbol was not found. If count == 1, a unique
> -	 * match was found and addr is set.  If count > 1, there is
> -	 * unresolvable ambiguity among "count" number of symbols with the same
> -	 * name in the same object.
> -	 */
>  	unsigned long count;
> +	unsigned long pos;
>  };
>  
>  static int klp_find_callback(void *data, const char *name,
> @@ -159,36 +154,46 @@ static int klp_find_callback(void *data, const char *name,
>  		return 0;
>  
>  	/*
> -	 * args->addr might be overwritten if another match is found
> -	 * but klp_find_object_symbol() handles this and only returns the
> -	 * addr if count == 1.
> +	 * Increment and assign the address. Return 1 when the desired symbol
> +	 * position is found or the search for a unique symbol fails.
>  	 */
>  	args->addr = addr;
>  	args->count++;
> +	if (((args->pos > 0) && (args->count == args->pos)) ||
> +	    ((args->pos == 0) && (args->count > 1)))
> +		return 1;
>  
>  	return 0;
>  }
>  
>  static int klp_find_object_symbol(const char *objname, const char *name,
> -				  unsigned long *addr)
> +				  unsigned long *addr, unsigned long sympos)

One nit about this interface.  I think it would be clearer if the sympos
argument came before the addr argument:

static int klp_find_object_symbol(const char *objname, const char *name,
				  unsigned long sympos, unsigned long addr)

Because:

1. it puts all input arguments before the output argument; and

2. it puts the sympos in its logical place immediately after the
   function name.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-12 16:59                     ` [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-12 19:50                       ` Josh Poimboeuf
  2015-11-13 16:42                       ` Petr Mladek
  1 sibling, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-12 19:50 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Seth Jennings, Jiri Kosina, Vojtech Pavlik,
	linux-kernel

On Thu, Nov 12, 2015 at 10:59:52AM -0600, Chris J Arges wrote:
> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default sympos will be 0, and patching will only succeed if
> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol in kallsyms for the patched object will be used
> for patching if it is valid.
> 
> Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
> as they are no longer used.
> 
> From the klp_reloc structure remove val, as it can be refactored as a
> local variable in klp_write_object_relocations.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
>  include/linux/livepatch.h |  5 ++-
>  kernel/livepatch/core.c   | 81 +++++++++++++----------------------------------
>  2 files changed, 24 insertions(+), 62 deletions(-)
> 
> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 9808dd4..9149de4 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -68,8 +68,7 @@ struct klp_func {
>  /**
>   * struct klp_reloc - relocation structure for live patching
>   * @loc:	address where the relocation will be written
> - * @val:	address of the referenced symbol (optional,
> - *		vmlinux	patches only)
> + * @sympos:	position in kallsyms to disambiguate symbols (optional)
>   * @type:	ELF relocation type
>   * @name:	name of the referenced symbol (for lookup/verification)
>   * @addend:	offset from the referenced symbol
> @@ -78,7 +77,7 @@ struct klp_func {
>   */
>  struct klp_reloc {
>  	unsigned long loc;
> -	unsigned long val;
> +	unsigned long sympos;
>  	unsigned long type;
>  	const char *name;
>  	int addend;
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 4cd079c..071895f 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -202,45 +202,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
>  	return -EINVAL;
>  }
>  
> -struct klp_verify_args {
> -	const char *name;
> -	const unsigned long addr;
> -};
> -
> -static int klp_verify_callback(void *data, const char *name,
> -			       struct module *mod, unsigned long addr)
> -{
> -	struct klp_verify_args *args = data;
> -
> -	if (!mod &&
> -	    !strcmp(args->name, name) &&
> -	    args->addr == addr)
> -		return 1;
> -
> -	return 0;
> -}
> -
> -static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
> -{
> -	struct klp_verify_args args = {
> -		.name = name,
> -		.addr = addr,
> -	};
> -	int ret;
> -
> -	mutex_lock(&module_mutex);
> -	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
> -	mutex_unlock(&module_mutex);
> -
> -	if (!ret) {
> -		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
> -			name, addr);
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
>  /*
>   * External symbols are exported symbols that are defined outside both
>   * the patched object and the patch.
> @@ -266,6 +227,7 @@ static int klp_write_object_relocations(struct module *pmod,
>  					struct klp_object *obj)
>  {
>  	int ret;
> +	unsigned long val;
>  	struct klp_reloc *reloc;
>  
>  	if (WARN_ON(!klp_is_object_loaded(obj)))
> @@ -275,29 +237,30 @@ static int klp_write_object_relocations(struct module *pmod,
>  		return -EINVAL;
>  
>  	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     &reloc->val, 0);
> -			if (ret)
> -				return ret;
> -		}
> +		/* discover the address of the referenced symbol */
> +		if (reloc->external) {
> +			/*
> +			 * external symbols aren't specified by the user
> +			 * therefore sympos should not be used
> +			 */

"external symbols' *objects* aren't specified by the user..."

> +			if (reloc->sympos) {
> +				pr_err("symbol '%s' is external and has sympos %lu\n",
> +				       reloc->name, reloc->sympos);
> +				return -EINVAL;
> +			}
> +			ret = klp_find_external_symbol(pmod, reloc->name, &val);
> +		} else
> +			ret = klp_find_object_symbol(obj->mod->name,
> +						     reloc->name,
> +						     &val,
> +						     reloc->sympos);
> +		if (ret)
> +			return ret;
>  		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
> -					     reloc->val + reloc->addend);
> +					     val + reloc->addend);
>  		if (ret) {
>  			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
> -			       reloc->name, reloc->val, ret);
> +			       reloc->name, val, ret);
>  			return ret;
>  		}
>  	}
> -- 
> 1.9.1
> 

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-12 19:45                       ` Josh Poimboeuf
@ 2015-11-13  9:56                       ` Jiri Kosina
  2015-11-13 10:14                       ` Miroslav Benes
  2015-11-13 16:27                       ` Petr Mladek
  3 siblings, 0 replies; 104+ messages in thread
From: Jiri Kosina @ 2015-11-13  9:56 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings,
	Vojtech Pavlik, linux-kernel

On Thu, 12 Nov 2015, Chris J Arges wrote:

> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol in kallsyms for the patched object
> will be used for patching if it is valid.
> 
> In addition, make old_addr an internal structure field not to be specified
> by the user. Finally, remove klp_find_verify_func_addr as it can be
> replaced by klp_find_object_symbol directly.

The changelog has to cover the "why is this better than previous aproach". 
It's neither in the cover letter (that by default doesn't make it into 
changelog anyway) nor in either of the commit logs.

Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-12 19:45                       ` Josh Poimboeuf
  2015-11-13  9:56                       ` Jiri Kosina
@ 2015-11-13 10:14                       ` Miroslav Benes
  2015-11-13 16:27                       ` Petr Mladek
  3 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-13 10:14 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Thu, 12 Nov 2015, Chris J Arges wrote:

> diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
> index 31db7a0..3d18dff 100644
> --- a/include/linux/livepatch.h
> +++ b/include/linux/livepatch.h
> @@ -37,8 +37,9 @@ enum klp_state {
>   * 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_addr:	a hint conveying at what address the old function
> - *		can be found (optional, vmlinux patches only)
> + * @old_sympos: a hint indicating which symbol position the old function
> + *		can be found (optional)
> + * @old_addr:	the address of the function being patched
>   * @kobj:	kobject for sysfs resources
>   * @state:	tracks function-level patch application state
>   * @stack_node:	list node for klp_ops func_stack list
> @@ -47,17 +48,18 @@ struct klp_func {
>  	/* external */
>  	const char *old_name;
>  	void *new_func;
> +

A nit, but this new empty line is not necessary. Let's keep all the 
external stuff in one pack.

>  	/*
> -	 * The old_addr field is optional and can be used to resolve
> -	 * duplicate symbol names in the vmlinux object.  If this
> -	 * information is not present, the symbol is located by name
> -	 * with kallsyms. If the name is not unique and old_addr is
> -	 * not provided, the patch application fails as there is no
> -	 * way to resolve the ambiguity.
> +	 * The old_sympos field is optional and can be used to resolve
> +	 * duplicate symbol names in livepatch objects. If this field is zero,
> +	 * it is expected the symbol is unique, otherwise patching fails. If
> +	 * this value is greater than zero then that occurrence of the symbol
> +	 * in kallsyms for the given object is used.
>  	 */


> @@ -749,8 +733,13 @@ static int klp_init_object_loaded(struct klp_patch *patch,
>  			return ret;
>  	}
>  
> +	/*
> +	 * Verify the symbol, find old_addr, and write it to the structure.
> +	 */

It is not verification anymore. I think a comment here is not necessary. 
It is quite clear what klp_find_object_symbol does.

>  	klp_for_each_func(obj, func) {
> -		ret = klp_find_verify_func_addr(obj, func);
> +		ret = klp_find_object_symbol(obj->name, func->old_name,
> +					     &func->old_addr,
> +					     func->old_sympos);
>  		if (ret)
>  			return ret;
>  	}

Thanks,
Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols
  2015-11-12 16:59                     ` [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols Chris J Arges
@ 2015-11-13 10:24                       ` Miroslav Benes
  2015-11-13 13:55                         ` Petr Mladek
  0 siblings, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-13 10:24 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Petr Mladek, Josh Poimboeuf, Seth Jennings,
	Jiri Kosina, Vojtech Pavlik, linux-kernel

On Thu, 12 Nov 2015, Chris J Arges wrote:

> From: Petr Mladek <pmladek@suse.com>
> 
> The livepatch module might be linked from several .o files.
> All symbols that need to be shared between these .o files
> should be exported. This is a normal programming practice.
> I do not see any reason to access static symbols between
> these .o files.
> 
> This patch removes the search for the static symbols within
> the livepatch module. It makes it easier to understand
> the meaning of the external flag and klp_find_external_symbol()
> function.
> 
> Signed-off-by: Petr Mladek <pmladek@suse.com>
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>

I'd remove this patch from the patch set, because

1. Josh needs to confirm that it is possible for kpatch to live without 
external or that we can modify it. This could postpone this patch set as a 
whole.

2. I think the issue is quite independent of the problem this patch set 
solves.

3. I can even imagine that we could get rid of 'external' in klp_func and 
its special handling completely if kpatch allows.

So let's solve it separately. Does anyone have a different opinion?

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-12 19:19                         ` Josh Poimboeuf
@ 2015-11-13 13:54                           ` Petr Mladek
  2015-11-13 16:59                             ` Josh Poimboeuf
  0 siblings, 1 reply; 104+ messages in thread
From: Petr Mladek @ 2015-11-13 13:54 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Thu 2015-11-12 13:19:17, Josh Poimboeuf wrote:
> On Thu, Nov 12, 2015 at 03:31:58PM +0100, Petr Mladek wrote:
> > On Wed 2015-11-11 11:57:31, Josh Poimboeuf wrote:
> > > On Wed, Nov 11, 2015 at 10:29:00AM -0600, Chris J Arges wrote:
> > > > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > > > index 26f9778..4eb8691 100644
> > > > --- a/kernel/livepatch/core.c
> > > > +++ b/kernel/livepatch/core.c
> > > > @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
> > > >   * object is either vmlinux or the kmod being patched).
> > > >   */
> > > >  static int klp_find_external_symbol(struct module *pmod, const char *name,
> > > > -				    unsigned long *addr)
> > > > +				    unsigned long *addr, unsigned long sympos)
> > > >  {
> > > >  	const struct kernel_symbol *sym;
> > > >  
> > > 
> There are two cases for external symbols:
> 
> 1. Accessing a global symbol in another .o file in the patch module.
>    For an example of a patch which does this, see:
> 
>      https://github.com/dynup/kpatch/blob/master/test/integration/f22/module-call-external.patch
> 
>    In that example, notice that kpatch_string() function is global (not
>    static), and is not exported.  It *is* actually a real world
>    scenario.

Mirek helped me to understand it. The symbol is exported if you
compile the above patch from sources. kpatch produces the patch by
pecking out the newly created symbols without looking if they
are newly exported. I hope that we got it right.

>    But I do think we're currently handling it wrong.  kpatch-build isn't
>    smart enough to determine the difference between the use of an
>    exported symbol and a global one that's in another .o in the module.
>    We can probably fix that by looking at Module.symvers.  So I think we
>    can get rid of this case.

That would be lovely.


> 2. Accessing an exported symbol which lives in a module.
> 
>    With Chris's patches, we now don't have any ambiguity for specifying
>    module symbols, so I think we can get rid of this case too.
> 
> So I *think* we can get rid of 'external' completely.  But I could be
> overlooking something.  I'd rather implement the change in kpatch-build
> first to make 100% sure we can actually get rid of it.
> 
> Also, I'd ask that we hold off on this patch for now until we get a
> chance to add support for it in kpatch-build.

Fair enough.


> Then at that point we can just remove all the 'external' stuff.

I see. Each symbol is part of an object. Even the exported symbols
need  to be listed for the related  object. We do not need external at
all if the patch is compiled from sources or if we check for newly exported
symbols in the binaries.

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols
  2015-11-13 10:24                       ` Miroslav Benes
@ 2015-11-13 13:55                         ` Petr Mladek
  0 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-13 13:55 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, jeyu, Josh Poimboeuf,
	Seth Jennings, Jiri Kosina, Vojtech Pavlik, linux-kernel

On Fri 2015-11-13 11:24:33, Miroslav Benes wrote:
> On Thu, 12 Nov 2015, Chris J Arges wrote:
> 
> > From: Petr Mladek <pmladek@suse.com>
> > 
> > The livepatch module might be linked from several .o files.
> > All symbols that need to be shared between these .o files
> > should be exported. This is a normal programming practice.
> > I do not see any reason to access static symbols between
> > these .o files.
> > 
> > This patch removes the search for the static symbols within
> > the livepatch module. It makes it easier to understand
> > the meaning of the external flag and klp_find_external_symbol()
> > function.
> > 
> > Signed-off-by: Petr Mladek <pmladek@suse.com>
> > Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> 
> I'd remove this patch from the patch set, because
> 
> 1. Josh needs to confirm that it is possible for kpatch to live without 
> external or that we can modify it. This could postpone this patch set as a 
> whole.
> 
> 2. I think the issue is quite independent of the problem this patch set 
> solves.
> 
> 3. I can even imagine that we could get rid of 'external' in klp_func and 
> its special handling completely if kpatch allows.
> 
> So let's solve it separately. Does anyone have a different opinion?

I agree. Let's solve this separately and leave it out for now.

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 1/3 v6] livepatch: add old_sympos as disambiguator field to klp_func
       [not found]                     ` <1447431804-18786-1-git-send-email-chris.j.arges@canonical.com>
@ 2015-11-13 16:23                       ` Chris J Arges
  2015-11-13 16:23                       ` [PATCH 2/3 v6] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
                                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-13 16:23 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

In cases of duplicate symbols, old_sympos will be used to disambiguate
instead of old_addr. By default old_sympos will be 0, and patching will
only succeed if the symbol is unique. Specifying a positive value will
ensure that occurrence of the symbol in kallsyms for the patched object
will be used for patching if it is valid.

In addition, make old_addr an internal structure field not to be specified
by the user. Finally, remove klp_find_verify_func_addr as it can be
replaced by klp_find_object_symbol directly.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h | 19 ++++++++-------
 kernel/livepatch/core.c   | 62 ++++++++++++++++++-----------------------------
 2 files changed, 34 insertions(+), 47 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..b60e8ab 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
- *		can be found (optional, vmlinux patches only)
+ * @old_sympos: a hint indicating which symbol position the old function
+ *		can be found (optional)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -48,16 +49,16 @@ struct klp_func {
 	const char *old_name;
 	void *new_func;
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve
+	 * duplicate symbol names in livepatch objects. If this field is zero,
+	 * it is expected the symbol is unique, otherwise patching fails. If
+	 * this value is greater than zero then that occurrence of the symbol
+	 * in kallsyms for the given object is used.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..ebeaa48 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -135,13 +135,8 @@ struct klp_find_arg {
 	const char *objname;
 	const char *name;
 	unsigned long addr;
-	/*
-	 * If count == 0, the symbol was not found. If count == 1, a unique
-	 * match was found and addr is set.  If count > 1, there is
-	 * unresolvable ambiguity among "count" number of symbols with the same
-	 * name in the same object.
-	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -159,36 +154,46 @@ static int klp_find_callback(void *data, const char *name,
 		return 0;
 
 	/*
-	 * args->addr might be overwritten if another match is found
-	 * but klp_find_object_symbol() handles this and only returns the
-	 * addr if count == 1.
+	 * Increment and assign the address. Return 1 when the desired symbol
+	 * position is found or the search for a unique symbol fails.
 	 */
 	args->addr = addr;
 	args->count++;
+	if (((args->pos > 0) && (args->count == args->pos)) ||
+	    ((args->pos == 0) && (args->count > 1)))
+		return 1;
 
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long sympos, unsigned long *addr)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
+	 * otherwise ensure the symbol position count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
+	else if (args.count > 1 && sympos == 0) {
 		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 		       args.count, name, objname);
-	else {
+	} else if (sympos != args.count && sympos > 0) {
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
+	} else {
 		*addr = args.addr;
 		return 0;
 	}
@@ -236,27 +241,6 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 	return 0;
 }
 
-static int klp_find_verify_func_addr(struct klp_object *obj,
-				     struct klp_func *func)
-{
-	int ret;
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
-
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
-
-	return ret;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -277,7 +261,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	preempt_enable();
 
 	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	return klp_find_object_symbol(pmod->name, name, 0, addr);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +291,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     0, &reloc->val);
 			if (ret)
 				return ret;
 		}
@@ -750,7 +734,9 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 	}
 
 	klp_for_each_func(obj, func) {
-		ret = klp_find_verify_func_addr(obj, func);
+		ret = klp_find_object_symbol(obj->name, func->old_name,
+					     func->old_sympos,
+					     &func->old_addr);
 		if (ret)
 			return ret;
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 2/3 v6] livepatch: add sympos as disambiguator field to klp_reloc
       [not found]                     ` <1447431804-18786-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-13 16:23                       ` [PATCH 1/3 v6] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-13 16:23                       ` Chris J Arges
  2015-11-13 16:23                       ` [PATCH 3/3 v6] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
       [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
  3 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-13 16:23 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

In cases of duplicate symbols, sympos will be used to disambiguate instead
of val. By default sympos will be 0, and patching will only succeed if
the symbol is unique. Specifying a positive value will ensure that
occurrence of the symbol in kallsyms for the patched object will be used
for patching if it is valid.

Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
as they are no longer used.

>From the klp_reloc structure remove val, as it can be refactored as a
local variable in klp_write_object_relocations.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  5 ++-
 kernel/livepatch/core.c   | 81 +++++++++++++----------------------------------
 2 files changed, 24 insertions(+), 62 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index b60e8ab..a882865 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -67,8 +67,7 @@ struct klp_func {
 /**
  * struct klp_reloc - relocation structure for live patching
  * @loc:	address where the relocation will be written
- * @val:	address of the referenced symbol (optional,
- *		vmlinux	patches only)
+ * @sympos:	position in kallsyms to disambiguate symbols (optional)
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
@@ -76,7 +75,7 @@ struct klp_func {
  */
 struct klp_reloc {
 	unsigned long loc;
-	unsigned long val;
+	unsigned long sympos;
 	unsigned long type;
 	const char *name;
 	int addend;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index ebeaa48..5cfe7b5 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -202,45 +202,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
 	return -EINVAL;
 }
 
-struct klp_verify_args {
-	const char *name;
-	const unsigned long addr;
-};
-
-static int klp_verify_callback(void *data, const char *name,
-			       struct module *mod, unsigned long addr)
-{
-	struct klp_verify_args *args = data;
-
-	if (!mod &&
-	    !strcmp(args->name, name) &&
-	    args->addr == addr)
-		return 1;
-
-	return 0;
-}
-
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
-{
-	struct klp_verify_args args = {
-		.name = name,
-		.addr = addr,
-	};
-	int ret;
-
-	mutex_lock(&module_mutex);
-	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
-	mutex_unlock(&module_mutex);
-
-	if (!ret) {
-		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
-			name, addr);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -268,6 +229,7 @@ static int klp_write_object_relocations(struct module *pmod,
 					struct klp_object *obj)
 {
 	int ret;
+	unsigned long val;
 	struct klp_reloc *reloc;
 
 	if (WARN_ON(!klp_is_object_loaded(obj)))
@@ -277,29 +239,30 @@ static int klp_write_object_relocations(struct module *pmod,
 		return -EINVAL;
 
 	for (reloc = obj->relocs; reloc->name; reloc++) {
-		if (!klp_is_module(obj)) {
-			ret = klp_verify_vmlinux_symbol(reloc->name,
-							reloc->val);
-			if (ret)
-				return ret;
-		} else {
-			/* module, reloc->val needs to be discovered */
-			if (reloc->external)
-				ret = klp_find_external_symbol(pmod,
-							       reloc->name,
-							       &reloc->val);
-			else
-				ret = klp_find_object_symbol(obj->mod->name,
-							     reloc->name,
-							     0, &reloc->val);
-			if (ret)
-				return ret;
-		}
+		/* discover the address of the referenced symbol */
+		if (reloc->external) {
+			/*
+			 * external symbols aren't specified by the user
+			 * therefore sympos should not be used
+			 */
+			if (reloc->sympos) {
+				pr_err("symbol '%s' is external and has sympos %lu\n",
+				       reloc->name, reloc->sympos);
+				return -EINVAL;
+			}
+			ret = klp_find_external_symbol(pmod, reloc->name, &val);
+		} else
+			ret = klp_find_object_symbol(obj->mod->name,
+						     reloc->name,
+						     reloc->sympos,
+						     &val);
+		if (ret)
+			return ret;
 		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
-					     reloc->val + reloc->addend);
+					     val + reloc->addend);
 		if (ret) {
 			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
-			       reloc->name, reloc->val, ret);
+			       reloc->name, val, ret);
 			return ret;
 		}
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 3/3 v6] livepatch: function,sympos scheme in livepatch sysfs directory
       [not found]                     ` <1447431804-18786-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-13 16:23                       ` [PATCH 1/3 v6] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-13 16:23                       ` [PATCH 2/3 v6] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-13 16:23                       ` Chris J Arges
       [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
  3 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-13 16:23 UTC (permalink / raw)
  To: live-patching
  Cc: jeyu, Chris J Arges, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-api, linux-kernel

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function,sympos>

The sympos number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
 kernel/livepatch/core.c                          | 10 ++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..da87f43 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,sympos>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		sympos number corresponding to the nth occurrence of the symbol
+		name in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 5cfe7b5..53ba0ae 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -679,8 +679,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
+	/* The format for the sysfs directory is <function,sympos> where sympos
+	 * is the nth occurrence of this symbol in kallsyms for the patched
+	 * object. If the user selects 0 for old_sympos, then 1 will be used
+	 * since a unique symbol will be the first occurrence.
+	 */
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 1);
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
                                         ` (2 preceding siblings ...)
  2015-11-13 10:14                       ` Miroslav Benes
@ 2015-11-13 16:27                       ` Petr Mladek
  3 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-13 16:27 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Thu 2015-11-12 10:59:50, Chris J Arges wrote:
> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol in kallsyms for the patched object
> will be used for patching if it is valid.
> 
> In addition, make old_addr an internal structure field not to be specified
> by the user. Finally, remove klp_find_verify_func_addr as it can be
> replaced by klp_find_object_symbol directly.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> ---
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 6e53441..479d75e 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -159,36 +154,46 @@ static int klp_find_callback(void *data, const char *name,
>  		return 0;
>  
>  	/*
> -	 * args->addr might be overwritten if another match is found
> -	 * but klp_find_object_symbol() handles this and only returns the
> -	 * addr if count == 1.
> +	 * Increment and assign the address. Return 1 when the desired symbol
> +	 * position is found or the search for a unique symbol fails.
>  	 */
>  	args->addr = addr;
>  	args->count++;

I would avoid the obvious things and move the comment here:

	/*
	 * Finish the search when the symbol is found on the desired
	 * position or the position is not defined for non-unique
	 * symbol.
	 */

> +	if (((args->pos > 0) && (args->count == args->pos)) ||
> +	    ((args->pos == 0) && (args->count > 1)))
> +		return 1;

I wonder if this is better readable:

	if ((args->pos && (args->count == args->pos)) ||
	    (!args->pos && (args->count > 1)))
		return 1;

>  	return 0;
>  }
>  
[...]
> @@ -277,7 +261,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
>  	preempt_enable();
>  
>  	/* otherwise check if it's in another .o within the patch module */
> -	return klp_find_object_symbol(pmod->name, name, addr);
> +	return klp_find_object_symbol(pmod->name, name, addr, 0);

Please, add a comment here that external symbols always have to be unique.

>  }
>  
>  static int klp_write_object_relocations(struct module *pmod,
> @@ -307,7 +291,7 @@ static int klp_write_object_relocations(struct module *pmod,
>  			else
>  				ret = klp_find_object_symbol(obj->mod->name,
>  							     reloc->name,
> -							     &reloc->val);
> +							     &reloc->val, 0);

Please, mention in the commit message that the support for sympos will
be added into relocations in a separate patch. Or add a FIXME comment
here. It will make easier the review and git history archaeology.

Thank you,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-12 16:59                     ` [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
  2015-11-12 19:50                       ` Josh Poimboeuf
@ 2015-11-13 16:42                       ` Petr Mladek
  1 sibling, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-13 16:42 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jeyu, Josh Poimboeuf, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Thu 2015-11-12 10:59:52, Chris J Arges wrote:
> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default sympos will be 0, and patching will only succeed if
> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol in kallsyms for the patched object will be used
> for patching if it is valid.
> 
> Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
> as they are no longer used.
> 
> >From the klp_reloc structure remove val, as it can be refactored as a
> local variable in klp_write_object_relocations.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 4cd079c..071895f 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -275,29 +237,30 @@ static int klp_write_object_relocations(struct module *pmod,
>  		return -EINVAL;
>  
>  	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     &reloc->val, 0);
> -			if (ret)
> -				return ret;
> -		}
> +		/* discover the address of the referenced symbol */
> +		if (reloc->external) {
> +			/*
> +			 * external symbols aren't specified by the user
> +			 * therefore sympos should not be used
> +			 */
> +			if (reloc->sympos) {
> +				pr_err("symbol '%s' is external and has sympos %lu\n",
> +				       reloc->name, reloc->sympos);
> +				return -EINVAL;
> +			}

To be precise, reloc->sympos == 1 is a valid value. Note that it will show
"symbol,1" in sysfs. I suggest the following to keep it simple:

			if (reloc->sympos && (reloc->sympos != 1)) {
				pr_err("relocated external symbols must be unique but '%s' has sympos %lu\n",
				       reloc->name, reloc->sympos);
				return -EINVAL;
			}

Then we could even get rid of the comment.

Huh, I am looking forward to get rid of the external symbols ;-)

Thank you,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-13 13:54                           ` Petr Mladek
@ 2015-11-13 16:59                             ` Josh Poimboeuf
  2015-11-16 12:11                               ` Petr Mladek
  0 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-13 16:59 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Fri, Nov 13, 2015 at 02:54:42PM +0100, Petr Mladek wrote:
> On Thu 2015-11-12 13:19:17, Josh Poimboeuf wrote:
> > On Thu, Nov 12, 2015 at 03:31:58PM +0100, Petr Mladek wrote:
> > > On Wed 2015-11-11 11:57:31, Josh Poimboeuf wrote:
> > > > On Wed, Nov 11, 2015 at 10:29:00AM -0600, Chris J Arges wrote:
> > > > > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > > > > index 26f9778..4eb8691 100644
> > > > > --- a/kernel/livepatch/core.c
> > > > > +++ b/kernel/livepatch/core.c
> > > > > @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
> > > > >   * object is either vmlinux or the kmod being patched).
> > > > >   */
> > > > >  static int klp_find_external_symbol(struct module *pmod, const char *name,
> > > > > -				    unsigned long *addr)
> > > > > +				    unsigned long *addr, unsigned long sympos)
> > > > >  {
> > > > >  	const struct kernel_symbol *sym;
> > > > >  
> > > > 
> > There are two cases for external symbols:
> > 
> > 1. Accessing a global symbol in another .o file in the patch module.
> >    For an example of a patch which does this, see:
> > 
> >      https://github.com/dynup/kpatch/blob/master/test/integration/f22/module-call-external.patch
> > 
> >    In that example, notice that kpatch_string() function is global (not
> >    static), and is not exported.  It *is* actually a real world
> >    scenario.
> 
> Mirek helped me to understand it. The symbol is exported if you
> compile the above patch from sources. kpatch produces the patch by
> pecking out the newly created symbols without looking if they
> are newly exported. I hope that we got it right.

Hm, I don't really follow what you're saying.  Are we using different
definitions of 'exported'?

By exported, I mean the use of the EXPORT_SYMBOL macro which makes the
symbol available for use by other modules.  The above patch doesn't use
the EXPORT_SYMBOL macro, so the kpatch_string symbol isn't exported, and
can't be used by other kernel modules.

However, the symbol *is* global and can be used by other .o files within
the patch module.

> >    But I do think we're currently handling it wrong.  kpatch-build isn't
> >    smart enough to determine the difference between the use of an
> >    exported symbol and a global one that's in another .o in the module.
> >    We can probably fix that by looking at Module.symvers.  So I think we
> >    can get rid of this case.
> 
> That would be lovely.
> 
> 
> > 2. Accessing an exported symbol which lives in a module.
> > 
> >    With Chris's patches, we now don't have any ambiguity for specifying
> >    module symbols, so I think we can get rid of this case too.
> > 
> > So I *think* we can get rid of 'external' completely.  But I could be
> > overlooking something.  I'd rather implement the change in kpatch-build
> > first to make 100% sure we can actually get rid of it.
> > 
> > Also, I'd ask that we hold off on this patch for now until we get a
> > chance to add support for it in kpatch-build.
> 
> Fair enough.
> 
> 
> > Then at that point we can just remove all the 'external' stuff.
> 
> I see. Each symbol is part of an object. Even the exported symbols
> need  to be listed for the related  object. We do not need external at
> all if the patch is compiled from sources or if we check for newly exported
> symbols in the binaries.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc
  2015-11-13 16:59                             ` Josh Poimboeuf
@ 2015-11-16 12:11                               ` Petr Mladek
  0 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-16 12:11 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Chris J Arges, live-patching, jeyu, Seth Jennings, Jiri Kosina,
	Vojtech Pavlik, linux-kernel

On Fri 2015-11-13 10:59:34, Josh Poimboeuf wrote:
> On Fri, Nov 13, 2015 at 02:54:42PM +0100, Petr Mladek wrote:
> > On Thu 2015-11-12 13:19:17, Josh Poimboeuf wrote:
> > > On Thu, Nov 12, 2015 at 03:31:58PM +0100, Petr Mladek wrote:
> > > > On Wed 2015-11-11 11:57:31, Josh Poimboeuf wrote:
> > > > > On Wed, Nov 11, 2015 at 10:29:00AM -0600, Chris J Arges wrote:
> > > > > > diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> > > > > > index 26f9778..4eb8691 100644
> > > > > > --- a/kernel/livepatch/core.c
> > > > > > +++ b/kernel/livepatch/core.c
> > > > > > @@ -261,7 +222,7 @@ static int klp_find_verify_func_addr(struct klp_object *obj,
> > > > > >   * object is either vmlinux or the kmod being patched).
> > > > > >   */
> > > > > >  static int klp_find_external_symbol(struct module *pmod, const char *name,
> > > > > > -				    unsigned long *addr)
> > > > > > +				    unsigned long *addr, unsigned long sympos)
> > > > > >  {
> > > > > >  	const struct kernel_symbol *sym;
> > > > > >  
> > > > > 
> > > There are two cases for external symbols:
> > > 
> > > 1. Accessing a global symbol in another .o file in the patch module.
> > >    For an example of a patch which does this, see:
> > > 
> > >      https://github.com/dynup/kpatch/blob/master/test/integration/f22/module-call-external.patch
> > > 
> > >    In that example, notice that kpatch_string() function is global (not
> > >    static), and is not exported.  It *is* actually a real world
> > >    scenario.
> > 
> > Mirek helped me to understand it. The symbol is exported if you
> > compile the above patch from sources. kpatch produces the patch by
> > pecking out the newly created symbols without looking if they
> > are newly exported. I hope that we got it right.
> 
> Hm, I don't really follow what you're saying.  Are we using different
> definitions of 'exported'?

Yeah, I messed the meaning of the various terms. Also I did not have a
good picture about the difference in handling global symbols in normal
userspace binaries and kernel.


> By exported, I mean the use of the EXPORT_SYMBOL macro which makes the
> symbol available for use by other modules.  The above patch doesn't use
> the EXPORT_SYMBOL macro, so the kpatch_string symbol isn't exported, and
> can't be used by other kernel modules.
>
> However, the symbol *is* global and can be used by other .o files within
> the patch module.

Thanks you and Mirek for explanation. I hope that I will send less
confusing mails from now on.

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func
       [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
@ 2015-11-16 17:03                         ` Chris J Arges
  2015-11-16 21:59                           ` Jiri Kosina
  2015-11-16 17:03                         ` [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
                                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-16 17:03 UTC (permalink / raw)
  To: live-patching, jpoimboe, sjenning, jikos, vojtech
  Cc: pmladek, jeyu, Chris J Arges, linux-kernel

In cases of duplicate symbols, old_sympos will be used to disambiguate
instead of old_addr. By default old_sympos will be 0, and patching will
only succeed if the symbol is unique. Specifying a positive value will
ensure that occurrence of the symbol in kallsyms for the patched object
will be used for patching if it is valid.

In addition, make old_addr an internal structure field not to be specified
by the user. Finally, remove klp_find_verify_func_addr as it can be
replaced by klp_find_object_symbol directly.

Support for symbol position disambiguation for relocations is added in the
next patch in this series.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h | 19 +++++++------
 kernel/livepatch/core.c   | 72 ++++++++++++++++++++---------------------------
 2 files changed, 41 insertions(+), 50 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..b60e8ab 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
- *		can be found (optional, vmlinux patches only)
+ * @old_sympos: a hint indicating which symbol position the old function
+ *		can be found (optional)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -48,16 +49,16 @@ struct klp_func {
 	const char *old_name;
 	void *new_func;
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve
+	 * duplicate symbol names in livepatch objects. If this field is zero,
+	 * it is expected the symbol is unique, otherwise patching fails. If
+	 * this value is greater than zero then that occurrence of the symbol
+	 * in kallsyms for the given object is used.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..5a53383 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -135,13 +135,8 @@ struct klp_find_arg {
 	const char *objname;
 	const char *name;
 	unsigned long addr;
-	/*
-	 * If count == 0, the symbol was not found. If count == 1, a unique
-	 * match was found and addr is set.  If count > 1, there is
-	 * unresolvable ambiguity among "count" number of symbols with the same
-	 * name in the same object.
-	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -158,37 +153,48 @@ static int klp_find_callback(void *data, const char *name,
 	if (args->objname && strcmp(args->objname, mod->name))
 		return 0;
 
-	/*
-	 * args->addr might be overwritten if another match is found
-	 * but klp_find_object_symbol() handles this and only returns the
-	 * addr if count == 1.
-	 */
 	args->addr = addr;
 	args->count++;
 
+	/*
+	 * Finish the search when the symbol is found for the desired position
+	 * or the position is not defined for a non-unique symbol.
+	 */
+	if ((args->pos && (args->count == args->pos)) ||
+	    (!args->pos && (args->count > 1)))
+		return 1;
+
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long sympos, unsigned long *addr)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
+	 * otherwise ensure the symbol position count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
+	else if (args.count > 1 && sympos == 0) {
 		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 		       args.count, name, objname);
-	else {
+	} else if (sympos != args.count && sympos > 0) {
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
+	} else {
 		*addr = args.addr;
 		return 0;
 	}
@@ -236,27 +242,6 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 	return 0;
 }
 
-static int klp_find_verify_func_addr(struct klp_object *obj,
-				     struct klp_func *func)
-{
-	int ret;
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
-
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
-
-	return ret;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -276,8 +261,11 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	}
 	preempt_enable();
 
-	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	/*
+	 * Check if it's in another .o within the patch module. This also
+	 * checks that the external symbol is unique.
+	 */
+	return klp_find_object_symbol(pmod->name, name, 0, addr);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +295,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     0, &reloc->val);
 			if (ret)
 				return ret;
 		}
@@ -750,7 +738,9 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 	}
 
 	klp_for_each_func(obj, func) {
-		ret = klp_find_verify_func_addr(obj, func);
+		ret = klp_find_object_symbol(obj->name, func->old_name,
+					     func->old_sympos,
+					     &func->old_addr);
 		if (ret)
 			return ret;
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
       [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-16 17:03                         ` [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-16 17:03                         ` Chris J Arges
  2015-11-18  9:56                           ` Miroslav Benes
  2015-11-18 16:37                           ` Petr Mladek
  2015-11-16 17:03                         ` [PATCH 3/3 v7] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
  2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
  3 siblings, 2 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-16 17:03 UTC (permalink / raw)
  To: live-patching, jpoimboe, sjenning, jikos, vojtech
  Cc: pmladek, jeyu, Chris J Arges, linux-kernel

In cases of duplicate symbols, sympos will be used to disambiguate instead
of val. By default sympos will be 0, and patching will only succeed if
the symbol is unique. Specifying a positive value will ensure that
occurrence of the symbol in kallsyms for the patched object will be used
for patching if it is valid.

Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
as they are no longer used.

>From the klp_reloc structure remove val, as it can be refactored as a
local variable in klp_write_object_relocations.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  5 ++--
 kernel/livepatch/core.c   | 75 +++++++++++------------------------------------
 2 files changed, 19 insertions(+), 61 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index b60e8ab..a882865 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -67,8 +67,7 @@ struct klp_func {
 /**
  * struct klp_reloc - relocation structure for live patching
  * @loc:	address where the relocation will be written
- * @val:	address of the referenced symbol (optional,
- *		vmlinux	patches only)
+ * @sympos:	position in kallsyms to disambiguate symbols (optional)
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
@@ -76,7 +75,7 @@ struct klp_func {
  */
 struct klp_reloc {
 	unsigned long loc;
-	unsigned long val;
+	unsigned long sympos;
 	unsigned long type;
 	const char *name;
 	int addend;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 5a53383..9d98c7b 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -203,45 +203,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
 	return -EINVAL;
 }
 
-struct klp_verify_args {
-	const char *name;
-	const unsigned long addr;
-};
-
-static int klp_verify_callback(void *data, const char *name,
-			       struct module *mod, unsigned long addr)
-{
-	struct klp_verify_args *args = data;
-
-	if (!mod &&
-	    !strcmp(args->name, name) &&
-	    args->addr == addr)
-		return 1;
-
-	return 0;
-}
-
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
-{
-	struct klp_verify_args args = {
-		.name = name,
-		.addr = addr,
-	};
-	int ret;
-
-	mutex_lock(&module_mutex);
-	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
-	mutex_unlock(&module_mutex);
-
-	if (!ret) {
-		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
-			name, addr);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
 					struct klp_object *obj)
 {
 	int ret;
+	unsigned long val;
 	struct klp_reloc *reloc;
 
 	if (WARN_ON(!klp_is_object_loaded(obj)))
@@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
 		return -EINVAL;
 
 	for (reloc = obj->relocs; reloc->name; reloc++) {
-		if (!klp_is_module(obj)) {
-			ret = klp_verify_vmlinux_symbol(reloc->name,
-							reloc->val);
-			if (ret)
-				return ret;
-		} else {
-			/* module, reloc->val needs to be discovered */
-			if (reloc->external)
-				ret = klp_find_external_symbol(pmod,
-							       reloc->name,
-							       &reloc->val);
-			else
-				ret = klp_find_object_symbol(obj->mod->name,
-							     reloc->name,
-							     0, &reloc->val);
-			if (ret)
-				return ret;
+		if (reloc->sympos && (reloc->sympos != 1)) {
+			pr_err("symbol '%s' is external and has sympos %lu\n",
+			       reloc->name, reloc->sympos);
+			return -EINVAL;
 		}
+		/* discover the address of the referenced symbol */
+		if (reloc->external) {
+			ret = klp_find_external_symbol(pmod, reloc->name, &val);
+		} else
+			ret = klp_find_object_symbol(obj->mod->name,
+						     reloc->name,
+						     reloc->sympos,
+						     &val);
+		if (ret)
+			return ret;
 		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
-					     reloc->val + reloc->addend);
+					     val + reloc->addend);
 		if (ret) {
 			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
-			       reloc->name, reloc->val, ret);
+			       reloc->name, val, ret);
 			return ret;
 		}
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 3/3 v7] livepatch: function,sympos scheme in livepatch sysfs directory
       [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
  2015-11-16 17:03                         ` [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-16 17:03                         ` [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-16 17:03                         ` Chris J Arges
  2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
  3 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-16 17:03 UTC (permalink / raw)
  To: live-patching, jpoimboe, sjenning, jikos, vojtech
  Cc: pmladek, jeyu, Chris J Arges, linux-api, linux-kernel

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function,sympos>

The sympos number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
 kernel/livepatch/core.c                          | 10 ++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..da87f43 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,sympos>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		sympos number corresponding to the nth occurrence of the symbol
+		name in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 9d98c7b..2a1fd1f 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -679,8 +679,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
+	/* The format for the sysfs directory is <function,sympos> where sympos
+	 * is the nth occurrence of this symbol in kallsyms for the patched
+	 * object. If the user selects 0 for old_sympos, then 1 will be used
+	 * since a unique symbol will be the first occurrence.
+	 */
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 1);
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-16 17:03                         ` [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-16 21:59                           ` Jiri Kosina
  2015-11-17 14:29                             ` Chris J Arges
  0 siblings, 1 reply; 104+ messages in thread
From: Jiri Kosina @ 2015-11-16 21:59 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jpoimboe, sjenning, Vojtech Pavlik, pmladek, jeyu,
	linux-kernel

On Mon, 16 Nov 2015, Chris J Arges wrote:

> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol in kallsyms for the patched object
> will be used for patching if it is valid.
> 
> In addition, make old_addr an internal structure field not to be specified
> by the user. Finally, remove klp_find_verify_func_addr as it can be
> replaced by klp_find_object_symbol directly.
> 
> Support for symbol position disambiguation for relocations is added in the
> next patch in this series.

Chris,

I am sorry to repeat myself, but the changelog is quite verbose with 
respect to "what is being done", but it doesn't contain any information 
whatsoever with respect to "why is this an improvement over current 
state", IOW why we are changing the status quo at all.

This absolutely has to be present in the changelog.

Thanks,

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-16 21:59                           ` Jiri Kosina
@ 2015-11-17 14:29                             ` Chris J Arges
  2015-11-19 10:02                               ` Jiri Kosina
  0 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-17 14:29 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: live-patching, jpoimboe, sjenning, Vojtech Pavlik, pmladek, jeyu,
	linux-kernel



On 11/16/2015 03:59 PM, Jiri Kosina wrote:
> On Mon, 16 Nov 2015, Chris J Arges wrote:
> 
>> In cases of duplicate symbols, old_sympos will be used to disambiguate
>> instead of old_addr. By default old_sympos will be 0, and patching will
>> only succeed if the symbol is unique. Specifying a positive value will
>> ensure that occurrence of the symbol in kallsyms for the patched object
>> will be used for patching if it is valid.
>>
>> In addition, make old_addr an internal structure field not to be specified
>> by the user. Finally, remove klp_find_verify_func_addr as it can be
>> replaced by klp_find_object_symbol directly.
>>
>> Support for symbol position disambiguation for relocations is added in the
>> next patch in this series.
> 
> Chris,
> 
> I am sorry to repeat myself, but the changelog is quite verbose with 
> respect to "what is being done", but it doesn't contain any information 
> whatsoever with respect to "why is this an improvement over current 
> state", IOW why we are changing the status quo at all.
> 
> This absolutely has to be present in the changelog.
> 
> Thanks,
> 

Jiri,
Ok, I had put this in the cover letter which I thought was ok as well.
I'll copy those parts into this commit message as well. Here is the text
below. Let me know if this is sufficient.

"
Currently, patching objects with duplicate symbol names fail because the
creation of the sysfs function directory collides with the previous
attempt. Appending old_addr to the function name is problematic as it
reveals the address of the function being patched to a normal user.
Using the symbol's occurrence in kallsyms to postfix the function name
in the sysfs directory solves the issue of having consistent unique
names and ensuring that the address is not exposed to a normal user.

In addition, using the symbol position as the user's method to
disambiguate symbols instead of addr allows for disambiguating symbols
in modules as well for both function addresses and for relocs. This also
simplifies much of the code. Special handling for kASLR is no longer
needed and can be removed. The klp_find_verify_func_addr function can be
replaced by klp_find_object_symbol, and klp_verify_vmlinux_symbol and
its callback can be removed completely.
"

--chris

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-16 17:03                         ` [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-18  9:56                           ` Miroslav Benes
  2015-11-18 14:01                             ` Josh Poimboeuf
  2015-11-18 16:37                           ` Petr Mladek
  1 sibling, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-18  9:56 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jpoimboe, sjenning, jikos, vojtech, pmladek, jeyu,
	linux-kernel

On Mon, 16 Nov 2015, Chris J Arges wrote:

> @@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
>  		return -EINVAL;
>  
>  	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     0, &reloc->val);
> -			if (ret)
> -				return ret;
> +		if (reloc->sympos && (reloc->sympos != 1)) {
> +			pr_err("symbol '%s' is external and has sympos %lu\n",
> +			       reloc->name, reloc->sympos);
> +			return -EINVAL;
>  		}

Oh, this check should not be here, right? I think it needs to be under 'if 
(reloc->external) {'.

And

if (reloc->sympos && (reloc->sympos != 1)) {

can be written as

if (reloc->sympos > 1) {

Anyway, I am not sure if this is the right thing to do. I know Petr 
suggested it, but maybe it would be sufficient just to error out when 
reloc->sympos is specified for external symbols. Despite there is a valid 
value (== 1). Like it had been done before. Josh came up with the issue. 
So what is your opinion, Josh? It is a nitpick, but nevertheless.

Miroslav

> +		/* discover the address of the referenced symbol */
> +		if (reloc->external) {
> +			ret = klp_find_external_symbol(pmod, reloc->name, &val);
> +		} else
> +			ret = klp_find_object_symbol(obj->mod->name,
> +						     reloc->name,
> +						     reloc->sympos,
> +						     &val);
> +		if (ret)
> +			return ret;
>  		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
> -					     reloc->val + reloc->addend);
> +					     val + reloc->addend);
>  		if (ret) {
>  			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
> -			       reloc->name, reloc->val, ret);
> +			       reloc->name, val, ret);
>  			return ret;
>  		}
>  	}
> 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-18  9:56                           ` Miroslav Benes
@ 2015-11-18 14:01                             ` Josh Poimboeuf
  2015-11-18 16:47                               ` Petr Mladek
  0 siblings, 1 reply; 104+ messages in thread
From: Josh Poimboeuf @ 2015-11-18 14:01 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: Chris J Arges, live-patching, sjenning, jikos, vojtech, pmladek,
	jeyu, linux-kernel

On Wed, Nov 18, 2015 at 10:56:00AM +0100, Miroslav Benes wrote:
> On Mon, 16 Nov 2015, Chris J Arges wrote:
> 
> > @@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
> >  		return -EINVAL;
> >  
> >  	for (reloc = obj->relocs; reloc->name; reloc++) {
> > -		if (!klp_is_module(obj)) {
> > -			ret = klp_verify_vmlinux_symbol(reloc->name,
> > -							reloc->val);
> > -			if (ret)
> > -				return ret;
> > -		} else {
> > -			/* module, reloc->val needs to be discovered */
> > -			if (reloc->external)
> > -				ret = klp_find_external_symbol(pmod,
> > -							       reloc->name,
> > -							       &reloc->val);
> > -			else
> > -				ret = klp_find_object_symbol(obj->mod->name,
> > -							     reloc->name,
> > -							     0, &reloc->val);
> > -			if (ret)
> > -				return ret;
> > +		if (reloc->sympos && (reloc->sympos != 1)) {
> > +			pr_err("symbol '%s' is external and has sympos %lu\n",
> > +			       reloc->name, reloc->sympos);
> > +			return -EINVAL;
> >  		}
> 
> Oh, this check should not be here, right? I think it needs to be under 'if 
> (reloc->external) {'.
> 
> And
> 
> if (reloc->sympos && (reloc->sympos != 1)) {
> 
> can be written as
> 
> if (reloc->sympos > 1) {
> 
> Anyway, I am not sure if this is the right thing to do. I know Petr 
> suggested it, but maybe it would be sufficient just to error out when 
> reloc->sympos is specified for external symbols. Despite there is a valid 
> value (== 1). Like it had been done before. Josh came up with the issue. 
> So what is your opinion, Josh? It is a nitpick, but nevertheless.

I tend to agree.  IMO, any non-zero value of sympos doesn't make sense
for external symbols.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-16 17:03                         ` [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
  2015-11-18  9:56                           ` Miroslav Benes
@ 2015-11-18 16:37                           ` Petr Mladek
  2015-11-18 16:39                             ` Chris J Arges
  1 sibling, 1 reply; 104+ messages in thread
From: Petr Mladek @ 2015-11-18 16:37 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jpoimboe, sjenning, jikos, vojtech, jeyu, linux-kernel

On Mon 2015-11-16 11:03:06, Chris J Arges wrote:
> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default sympos will be 0, and patching will only succeed if
> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol in kallsyms for the patched object will be used
> for patching if it is valid.
> 
> Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
> as they are no longer used.
> 
> >From the klp_reloc structure remove val, as it can be refactored as a
  ^
Please, remove this extra '>'. I guess that you cut&pasted the
comment from a mail reply ;-)

Best Regards,
Petr



^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-18 16:37                           ` Petr Mladek
@ 2015-11-18 16:39                             ` Chris J Arges
  2015-11-18 16:55                               ` Petr Mladek
  0 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-18 16:39 UTC (permalink / raw)
  To: Petr Mladek
  Cc: live-patching, jpoimboe, sjenning, jikos, vojtech, jeyu, linux-kernel

On 11/18/2015 10:37 AM, Petr Mladek wrote:
> On Mon 2015-11-16 11:03:06, Chris J Arges wrote:
>> In cases of duplicate symbols, sympos will be used to disambiguate instead
>> of val. By default sympos will be 0, and patching will only succeed if
>> the symbol is unique. Specifying a positive value will ensure that
>> occurrence of the symbol in kallsyms for the patched object will be used
>> for patching if it is valid.
>>
>> Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
>> as they are no longer used.
>>
>> >From the klp_reloc structure remove val, as it can be refactored as a
>   ^
> Please, remove this extra '>'. I guess that you cut&pasted the
> comment from a mail reply ;-)
> 
> Best Regards,
> Petr
> 

I think that '>' was added in a subsequent reply. My patch doesn't have
that, and I'm guessing checkpatch would have warned me about that as well.
: )

--chris


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-18 14:01                             ` Josh Poimboeuf
@ 2015-11-18 16:47                               ` Petr Mladek
  0 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-11-18 16:47 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Miroslav Benes, Chris J Arges, live-patching, sjenning, jikos,
	vojtech, jeyu, linux-kernel

On Wed 2015-11-18 08:01:37, Josh Poimboeuf wrote:
> On Wed, Nov 18, 2015 at 10:56:00AM +0100, Miroslav Benes wrote:
> > On Mon, 16 Nov 2015, Chris J Arges wrote:
> > 
> > > @@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
> > >  		return -EINVAL;
> > >  
> > >  	for (reloc = obj->relocs; reloc->name; reloc++) {
> > > -		if (!klp_is_module(obj)) {
> > > -			ret = klp_verify_vmlinux_symbol(reloc->name,
> > > -							reloc->val);
> > > -			if (ret)
> > > -				return ret;
> > > -		} else {
> > > -			/* module, reloc->val needs to be discovered */
> > > -			if (reloc->external)
> > > -				ret = klp_find_external_symbol(pmod,
> > > -							       reloc->name,
> > > -							       &reloc->val);
> > > -			else
> > > -				ret = klp_find_object_symbol(obj->mod->name,
> > > -							     reloc->name,
> > > -							     0, &reloc->val);
> > > -			if (ret)
> > > -				return ret;
> > > +		if (reloc->sympos && (reloc->sympos != 1)) {
> > > +			pr_err("symbol '%s' is external and has sympos %lu\n",
> > > +			       reloc->name, reloc->sympos);
> > > +			return -EINVAL;
> > >  		}
> > 
> > Oh, this check should not be here, right? I think it needs to be under 'if 
> > (reloc->external) {'.
> > 
> > And
> > 
> > if (reloc->sympos && (reloc->sympos != 1)) {
> > 
> > can be written as
> > 
> > if (reloc->sympos > 1) {
> > 
> > Anyway, I am not sure if this is the right thing to do. I know Petr 
> > suggested it, but maybe it would be sufficient just to error out when 
> > reloc->sympos is specified for external symbols. Despite there is a valid 
> > value (== 1). Like it had been done before. Josh came up with the issue. 
> > So what is your opinion, Josh? It is a nitpick, but nevertheless.
> 
> I tend to agree.  IMO, any non-zero value of sympos doesn't make sense
> for external symbols.

OK, I do not have a strong opinion here. I am fain with refusing any
non-zero value.

Just please improve the error message. If I find in dmesg
"symbol 'bla' is external and has sympos 1" I would worry what
the problem is.

Please, somehow express that sympos is not supported for external
relocated symbols. You are not limited by the 80 characters here!

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-18 16:39                             ` Chris J Arges
@ 2015-11-18 16:55                               ` Petr Mladek
  2015-11-18 20:34                                 ` Jiri Kosina
  0 siblings, 1 reply; 104+ messages in thread
From: Petr Mladek @ 2015-11-18 16:55 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jpoimboe, sjenning, jikos, vojtech, jeyu, linux-kernel

On Wed 2015-11-18 10:39:24, Chris J Arges wrote:
> On 11/18/2015 10:37 AM, Petr Mladek wrote:
> > On Mon 2015-11-16 11:03:06, Chris J Arges wrote:
> >> In cases of duplicate symbols, sympos will be used to disambiguate instead
> >> of val. By default sympos will be 0, and patching will only succeed if
> >> the symbol is unique. Specifying a positive value will ensure that
> >> occurrence of the symbol in kallsyms for the patched object will be used
> >> for patching if it is valid.
> >>
> >> Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
> >> as they are no longer used.
> >>
> >> >From the klp_reloc structure remove val, as it can be refactored as a
> >   ^
> > Please, remove this extra '>'. I guess that you cut&pasted the
> > comment from a mail reply ;-)
> > 
> > Best Regards,
> > Petr
> > 
> 
> I think that '>' was added in a subsequent reply. My patch doesn't have
> that, and I'm guessing checkpatch would have warned me about that as well.
> : )

Heh, it seems that some mail delivery tool or mail client tries to be
clever.  I see the '>' in you original mail. But it is fine in the
archive, see
http://article.gmane.org/gmane.linux.kernel/2086364
http://marc.info/?l=linux-kernel&m=144769343212421

I am sorry for the noise.

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-18 16:55                               ` Petr Mladek
@ 2015-11-18 20:34                                 ` Jiri Kosina
  0 siblings, 0 replies; 104+ messages in thread
From: Jiri Kosina @ 2015-11-18 20:34 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Chris J Arges, live-patching, jpoimboe, sjenning, vojtech, jeyu,
	linux-kernel

On Wed, 18 Nov 2015, Petr Mladek wrote:

> > I think that '>' was added in a subsequent reply. My patch doesn't have
> > that, and I'm guessing checkpatch would have warned me about that as well.
> > : )
> 
> Heh, it seems that some mail delivery tool or mail client tries to be
> clever.  I see the '>' in you original mail. But it is fine in the
> archive, see
> http://article.gmane.org/gmane.linux.kernel/2086364
> http://marc.info/?l=linux-kernel&m=144769343212421

It has to be stored this way if you are using mbox format as a storage, as 
lines startng with "From" that directly follow an empty line (which is 
exactly what happened here) have special meaning in mbox format (it is 
used as a message separator).

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-17 14:29                             ` Chris J Arges
@ 2015-11-19 10:02                               ` Jiri Kosina
  0 siblings, 0 replies; 104+ messages in thread
From: Jiri Kosina @ 2015-11-19 10:02 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, jpoimboe, sjenning, Vojtech Pavlik, pmladek, jeyu,
	linux-kernel

On Tue, 17 Nov 2015, Chris J Arges wrote:

> Jiri,
> Ok, I had put this in the cover letter which I thought was ok as well.
> I'll copy those parts into this commit message as well. Here is the text
> below. Let me know if this is sufficient.

Yup, it'd be nice to have this in changelog of one of the patches in the 
series.

Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name
       [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
                                           ` (2 preceding siblings ...)
  2015-11-16 17:03                         ` [PATCH 3/3 v7] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
@ 2015-11-20 17:25                         ` Chris J Arges
  2015-11-20 17:25                           ` [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
                                             ` (3 more replies)
  3 siblings, 4 replies; 104+ messages in thread
From: Chris J Arges @ 2015-11-20 17:25 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes
  Cc: jeyu, Chris J Arges

Currently, patching objects with duplicate symbol names fail because the
creation of the sysfs function directory collides with the previous
attempt. Appending old_addr to the function name is problematic as it
reveals the address of the function being patch to a normal user. Using
the symbol's occurrence in kallsyms to postfix the function name in the
sysfs directory solves the issue of having consistent unique names and
ensuring that the address is not exposed to a normal user.

In addition, using the symbol position as the user's method to disambiguate
symbols instead of addr allows for disambiguating symbols in modules as
well for both function addresses and for relocs. This also simplifies much
of the code. Special handling for kASLR is no longer needed and can be
removed. The klp_find_verify_func_addr function can be replaced by
klp_find_object_symbol, and klp_verify_vmlinux_symbol and its callback can
be removed completely.

The following set of patches use symbol positioning instead of old
addresses to disambiguate symbols that have the same name in a given
object. This is necessary in order to be able to patch symbols with the
same name within the same object. This requires modifications to the
klp_func and klp_reloc structures to add an additional element. In addition
the scheme used for the func directory in sysfs is modified to append the
symbols occurrence in kallsyms.

v8:
 - explain motivation and necessity in initial patch
 - don't support sympos for external relocations

v7:
 - make count/pos checking in klp_find_callback more readable
 - fix klp_write_object_relocations sympos/external checking

v6:
 - move sympos arg before addr in klp_find_object_symbol
 - make comments more accurate, remove unnecessary whitespace
 - improve cover letter

v5:
 - remove val from klp_reloc struct
 - klp_write_object_relocations doesn't use sympos with external relocs
 - add Petr Mladek's patch to simplify relocated external symbol code
 - add optimization in klp_find_callback in unique case
 - remove klp_find_verify_func_addr
 - amend/remove commit messages/comments to be more precise

Chris J Arges (3):
  livepatch: add old_sympos as disambiguator field to klp_func
  livepatch: add sympos as disambiguator field to klp_reloc
  livepatch: function,sympos scheme in livepatch sysfs directory

 Documentation/ABI/testing/sysfs-kernel-livepatch |   6 +-
 include/linux/livepatch.h                        |  24 ++--
 kernel/livepatch/core.c                          | 157 ++++++++---------------
 3 files changed, 73 insertions(+), 114 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
@ 2015-11-20 17:25                           ` Chris J Arges
  2015-11-23  9:47                             ` Miroslav Benes
  2015-11-20 17:25                           ` [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
                                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-20 17:25 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes
  Cc: jeyu, Chris J Arges, Seth Jennings, Vojtech Pavlik

Currently, patching objects with duplicate symbol names fail because the
creation of the sysfs function directory collides with the previous
attempt. Appending old_addr to the function name is problematic as it
reveals the address of the function being patch to a normal user. Using
the symbol's occurrence in kallsyms to postfix the function name in the
sysfs directory solves the issue of having consistent unique names and
ensuring that the address is not exposed to a normal user.

In addition, using the symbol position as the user's method to disambiguate
symbols instead of addr allows for disambiguating symbols in modules as
well for both function addresses and for relocs. This also simplifies much
of the code. Special handling for kASLR is no longer needed and can be
removed. The klp_find_verify_func_addr function can be replaced by
klp_find_object_symbol, and klp_verify_vmlinux_symbol and its callback can
be removed completely.

In cases of duplicate symbols, old_sympos will be used to disambiguate
instead of old_addr. By default old_sympos will be 0, and patching will
only succeed if the symbol is unique. Specifying a positive value will
ensure that occurrence of the symbol in kallsyms for the patched object
will be used for patching if it is valid.

In addition, make old_addr an internal structure field not to be specified
by the user. Finally, remove klp_find_verify_func_addr as it can be
replaced by klp_find_object_symbol directly.

Support for symbol position disambiguation for relocations is added in the
next patch in this series.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h | 19 +++++++------
 kernel/livepatch/core.c   | 72 ++++++++++++++++++++---------------------------
 2 files changed, 41 insertions(+), 50 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..b60e8ab 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
- *		can be found (optional, vmlinux patches only)
+ * @old_sympos: a hint indicating which symbol position the old function
+ *		can be found (optional)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -48,16 +49,16 @@ struct klp_func {
 	const char *old_name;
 	void *new_func;
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve
+	 * duplicate symbol names in livepatch objects. If this field is zero,
+	 * it is expected the symbol is unique, otherwise patching fails. If
+	 * this value is greater than zero then that occurrence of the symbol
+	 * in kallsyms for the given object is used.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 6e53441..5a53383 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -135,13 +135,8 @@ struct klp_find_arg {
 	const char *objname;
 	const char *name;
 	unsigned long addr;
-	/*
-	 * If count == 0, the symbol was not found. If count == 1, a unique
-	 * match was found and addr is set.  If count > 1, there is
-	 * unresolvable ambiguity among "count" number of symbols with the same
-	 * name in the same object.
-	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -158,37 +153,48 @@ static int klp_find_callback(void *data, const char *name,
 	if (args->objname && strcmp(args->objname, mod->name))
 		return 0;
 
-	/*
-	 * args->addr might be overwritten if another match is found
-	 * but klp_find_object_symbol() handles this and only returns the
-	 * addr if count == 1.
-	 */
 	args->addr = addr;
 	args->count++;
 
+	/*
+	 * Finish the search when the symbol is found for the desired position
+	 * or the position is not defined for a non-unique symbol.
+	 */
+	if ((args->pos && (args->count == args->pos)) ||
+	    (!args->pos && (args->count > 1)))
+		return 1;
+
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long sympos, unsigned long *addr)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
+	 * otherwise ensure the symbol position count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
+	else if (args.count > 1 && sympos == 0) {
 		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 		       args.count, name, objname);
-	else {
+	} else if (sympos != args.count && sympos > 0) {
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
+	} else {
 		*addr = args.addr;
 		return 0;
 	}
@@ -236,27 +242,6 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 	return 0;
 }
 
-static int klp_find_verify_func_addr(struct klp_object *obj,
-				     struct klp_func *func)
-{
-	int ret;
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
-
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
-
-	return ret;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -276,8 +261,11 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	}
 	preempt_enable();
 
-	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	/*
+	 * Check if it's in another .o within the patch module. This also
+	 * checks that the external symbol is unique.
+	 */
+	return klp_find_object_symbol(pmod->name, name, 0, addr);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -307,7 +295,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     0, &reloc->val);
 			if (ret)
 				return ret;
 		}
@@ -750,7 +738,9 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 	}
 
 	klp_for_each_func(obj, func) {
-		ret = klp_find_verify_func_addr(obj, func);
+		ret = klp_find_object_symbol(obj->name, func->old_name,
+					     func->old_sympos,
+					     &func->old_addr);
 		if (ret)
 			return ret;
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
  2015-11-20 17:25                           ` [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-20 17:25                           ` Chris J Arges
  2015-11-23  9:52                             ` Miroslav Benes
  2015-11-20 17:25                           ` [PATCH 3/3 v8] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
  3 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-20 17:25 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes
  Cc: jeyu, Chris J Arges, Seth Jennings, Vojtech Pavlik

In cases of duplicate symbols, sympos will be used to disambiguate instead
of val. By default sympos will be 0, and patching will only succeed if
the symbol is unique. Specifying a positive value will ensure that
occurrence of the symbol in kallsyms for the patched object will be used
for patching if it is valid. For external relocations sympos is not
supported.

Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
as they are no longer used.

>From the klp_reloc structure remove val, as it can be refactored as a
local variable in klp_write_object_relocations.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  5 ++-
 kernel/livepatch/core.c   | 77 +++++++++++------------------------------------
 2 files changed, 20 insertions(+), 62 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index b60e8ab..a882865 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -67,8 +67,7 @@ struct klp_func {
 /**
  * struct klp_reloc - relocation structure for live patching
  * @loc:	address where the relocation will be written
- * @val:	address of the referenced symbol (optional,
- *		vmlinux	patches only)
+ * @sympos:	position in kallsyms to disambiguate symbols (optional)
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
@@ -76,7 +75,7 @@ struct klp_func {
  */
 struct klp_reloc {
 	unsigned long loc;
-	unsigned long val;
+	unsigned long sympos;
 	unsigned long type;
 	const char *name;
 	int addend;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 5a53383..c9f924e 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -203,45 +203,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
 	return -EINVAL;
 }
 
-struct klp_verify_args {
-	const char *name;
-	const unsigned long addr;
-};
-
-static int klp_verify_callback(void *data, const char *name,
-			       struct module *mod, unsigned long addr)
-{
-	struct klp_verify_args *args = data;
-
-	if (!mod &&
-	    !strcmp(args->name, name) &&
-	    args->addr == addr)
-		return 1;
-
-	return 0;
-}
-
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
-{
-	struct klp_verify_args args = {
-		.name = name,
-		.addr = addr,
-	};
-	int ret;
-
-	mutex_lock(&module_mutex);
-	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
-	mutex_unlock(&module_mutex);
-
-	if (!ret) {
-		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
-			name, addr);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
 					struct klp_object *obj)
 {
 	int ret;
+	unsigned long val;
 	struct klp_reloc *reloc;
 
 	if (WARN_ON(!klp_is_object_loaded(obj)))
@@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
 		return -EINVAL;
 
 	for (reloc = obj->relocs; reloc->name; reloc++) {
-		if (!klp_is_module(obj)) {
-			ret = klp_verify_vmlinux_symbol(reloc->name,
-							reloc->val);
-			if (ret)
-				return ret;
-		} else {
-			/* module, reloc->val needs to be discovered */
-			if (reloc->external)
-				ret = klp_find_external_symbol(pmod,
-							       reloc->name,
-							       &reloc->val);
-			else
-				ret = klp_find_object_symbol(obj->mod->name,
-							     reloc->name,
-							     0, &reloc->val);
-			if (ret)
-				return ret;
-		}
+		/* discover the address of the referenced symbol */
+		if (reloc->external) {
+			if (reloc->sympos > 0) {
+				pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
+				       reloc->name);
+				return -EINVAL;
+			}
+			ret = klp_find_external_symbol(pmod, reloc->name, &val);
+		} else
+			ret = klp_find_object_symbol(obj->mod->name,
+						     reloc->name,
+						     reloc->sympos,
+						     &val);
+		if (ret)
+			return ret;
 		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
-					     reloc->val + reloc->addend);
+					     val + reloc->addend);
 		if (ret) {
 			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
-			       reloc->name, reloc->val, ret);
+			       reloc->name, val, ret);
 			return ret;
 		}
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 3/3 v8] livepatch: function,sympos scheme in livepatch sysfs directory
  2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
  2015-11-20 17:25                           ` [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-11-20 17:25                           ` [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-20 17:25                           ` Chris J Arges
  2015-11-23  9:47                             ` Miroslav Benes
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
  3 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-20 17:25 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes
  Cc: jeyu, Chris J Arges, Seth Jennings, Vojtech Pavlik, linux-api

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function,sympos>

The sympos number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
 kernel/livepatch/core.c                          | 10 ++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..da87f43 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,sympos>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		sympos number corresponding to the nth occurrence of the symbol
+		name in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index c9f924e..0e86c45 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -679,8 +679,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
+	/* The format for the sysfs directory is <function,sympos> where sympos
+	 * is the nth occurrence of this symbol in kallsyms for the patched
+	 * object. If the user selects 0 for old_sympos, then 1 will be used
+	 * since a unique symbol will be the first occurrence.
+	 */
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 1);
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func
  2015-11-20 17:25                           ` [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-11-23  9:47                             ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-23  9:47 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, linux-kernel, jpoimboe, jikos, pmladek, jeyu,
	Seth Jennings, Vojtech Pavlik

On Fri, 20 Nov 2015, Chris J Arges wrote:

> Currently, patching objects with duplicate symbol names fail because the
> creation of the sysfs function directory collides with the previous
> attempt. Appending old_addr to the function name is problematic as it
> reveals the address of the function being patch to a normal user. Using
> the symbol's occurrence in kallsyms to postfix the function name in the
> sysfs directory solves the issue of having consistent unique names and
> ensuring that the address is not exposed to a normal user.
> 
> In addition, using the symbol position as the user's method to disambiguate
> symbols instead of addr allows for disambiguating symbols in modules as
> well for both function addresses and for relocs. This also simplifies much
> of the code. Special handling for kASLR is no longer needed and can be
> removed. The klp_find_verify_func_addr function can be replaced by
> klp_find_object_symbol, and klp_verify_vmlinux_symbol and its callback can
> be removed completely.
> 
> In cases of duplicate symbols, old_sympos will be used to disambiguate
> instead of old_addr. By default old_sympos will be 0, and patching will
> only succeed if the symbol is unique. Specifying a positive value will
> ensure that occurrence of the symbol in kallsyms for the patched object
> will be used for patching if it is valid.
> 
> In addition, make old_addr an internal structure field not to be specified
> by the user. Finally, remove klp_find_verify_func_addr as it can be
> replaced by klp_find_object_symbol directly.
> 
> Support for symbol position disambiguation for relocations is added in the
> next patch in this series.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>

Reviewed-by: Miroslav Benes <mbenes@suse.cz>

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 3/3 v8] livepatch: function,sympos scheme in livepatch sysfs directory
  2015-11-20 17:25                           ` [PATCH 3/3 v8] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
@ 2015-11-23  9:47                             ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-11-23  9:47 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, linux-kernel, jpoimboe, jikos, pmladek, jeyu,
	Seth Jennings, Vojtech Pavlik, linux-api

On Fri, 20 Nov 2015, Chris J Arges wrote:

> The following directory structure will allow for cases when the same
> function name exists in a single object.
> 	/sys/kernel/livepatch/<patch>/<object>/<function,sympos>
> 
> The sympos number corresponds to the nth occurrence of the symbol name in
> kallsyms for the patched object.
> 
> An example of patching multiple symbols can be found here:
> 	https://github.com/dynup/kpatch/issues/493
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>

Reviewed-by: Miroslav Benes <mbenes@suse.cz>

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-20 17:25                           ` [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-11-23  9:52                             ` Miroslav Benes
  2015-11-30 20:46                               ` Chris J Arges
  0 siblings, 1 reply; 104+ messages in thread
From: Miroslav Benes @ 2015-11-23  9:52 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, linux-kernel, jpoimboe, jikos, pmladek, jeyu,
	Seth Jennings, Vojtech Pavlik

On Fri, 20 Nov 2015, Chris J Arges wrote:

[...]

> @@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
>  					struct klp_object *obj)
>  {
>  	int ret;
> +	unsigned long val;
>  	struct klp_reloc *reloc;
>  
>  	if (WARN_ON(!klp_is_object_loaded(obj)))
> @@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
>  		return -EINVAL;
>  
>  	for (reloc = obj->relocs; reloc->name; reloc++) {
> -		if (!klp_is_module(obj)) {
> -			ret = klp_verify_vmlinux_symbol(reloc->name,
> -							reloc->val);
> -			if (ret)
> -				return ret;
> -		} else {
> -			/* module, reloc->val needs to be discovered */
> -			if (reloc->external)
> -				ret = klp_find_external_symbol(pmod,
> -							       reloc->name,
> -							       &reloc->val);
> -			else
> -				ret = klp_find_object_symbol(obj->mod->name,
> -							     reloc->name,
> -							     0, &reloc->val);
> -			if (ret)
> -				return ret;
> -		}
> +		/* discover the address of the referenced symbol */
> +		if (reloc->external) {
> +			if (reloc->sympos > 0) {
> +				pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
> +				       reloc->name);
> +				return -EINVAL;
> +			}
> +			ret = klp_find_external_symbol(pmod, reloc->name, &val);
> +		} else
> +			ret = klp_find_object_symbol(obj->mod->name,
> +						     reloc->name,
> +						     reloc->sympos,
> +						     &val);

I think this will cause an unwanted effect if a relocation is for vmlinux 
symbol. obj->mod is NULL in that case. So obj->name should be there. Can 
you test it with kpatch, Chris, please? If that is possible.

Thanks,
Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-23  9:52                             ` Miroslav Benes
@ 2015-11-30 20:46                               ` Chris J Arges
  2015-12-01  1:17                                 ` Josh Poimboeuf
  0 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-11-30 20:46 UTC (permalink / raw)
  To: Miroslav Benes
  Cc: live-patching, linux-kernel, jpoimboe, jikos, pmladek, jeyu,
	Seth Jennings, Vojtech Pavlik

On Mon, Nov 23, 2015 at 10:52:23AM +0100, Miroslav Benes wrote:
> On Fri, 20 Nov 2015, Chris J Arges wrote:
> 
> [...]
> 
> > @@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
> >  					struct klp_object *obj)
> >  {
> >  	int ret;
> > +	unsigned long val;
> >  	struct klp_reloc *reloc;
> >  
> >  	if (WARN_ON(!klp_is_object_loaded(obj)))
> > @@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
> >  		return -EINVAL;
> >  
> >  	for (reloc = obj->relocs; reloc->name; reloc++) {
> > -		if (!klp_is_module(obj)) {
> > -			ret = klp_verify_vmlinux_symbol(reloc->name,
> > -							reloc->val);
> > -			if (ret)
> > -				return ret;
> > -		} else {
> > -			/* module, reloc->val needs to be discovered */
> > -			if (reloc->external)
> > -				ret = klp_find_external_symbol(pmod,
> > -							       reloc->name,
> > -							       &reloc->val);
> > -			else
> > -				ret = klp_find_object_symbol(obj->mod->name,
> > -							     reloc->name,
> > -							     0, &reloc->val);
> > -			if (ret)
> > -				return ret;
> > -		}
> > +		/* discover the address of the referenced symbol */
> > +		if (reloc->external) {
> > +			if (reloc->sympos > 0) {
> > +				pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
> > +				       reloc->name);
> > +				return -EINVAL;
> > +			}
> > +			ret = klp_find_external_symbol(pmod, reloc->name, &val);
> > +		} else
> > +			ret = klp_find_object_symbol(obj->mod->name,
> > +						     reloc->name,
> > +						     reloc->sympos,
> > +						     &val);
> 
> I think this will cause an unwanted effect if a relocation is for vmlinux 
> symbol. obj->mod is NULL in that case. So obj->name should be there. Can 
> you test it with kpatch, Chris, please? If that is possible.
> 
> Thanks,
> Miroslav
>

Yes I need to fix this, an option would be to use:
	ret = klp_find_object_symbol(obj->name ? obj->name : obj->mod->name,
				     reloc->name, 0, &reloc->val);

Testing with kpatch will require some modifications as the structures are
different.

--chris

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc
  2015-11-30 20:46                               ` Chris J Arges
@ 2015-12-01  1:17                                 ` Josh Poimboeuf
  0 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-12-01  1:17 UTC (permalink / raw)
  To: Chris J Arges
  Cc: Miroslav Benes, live-patching, linux-kernel, jikos, pmladek,
	jeyu, Seth Jennings, Vojtech Pavlik

On Mon, Nov 30, 2015 at 02:46:18PM -0600, Chris J Arges wrote:
> On Mon, Nov 23, 2015 at 10:52:23AM +0100, Miroslav Benes wrote:
> > On Fri, 20 Nov 2015, Chris J Arges wrote:
> > 
> > [...]
> > 
> > > @@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
> > >  					struct klp_object *obj)
> > >  {
> > >  	int ret;
> > > +	unsigned long val;
> > >  	struct klp_reloc *reloc;
> > >  
> > >  	if (WARN_ON(!klp_is_object_loaded(obj)))
> > > @@ -281,29 +243,26 @@ static int klp_write_object_relocations(struct module *pmod,
> > >  		return -EINVAL;
> > >  
> > >  	for (reloc = obj->relocs; reloc->name; reloc++) {
> > > -		if (!klp_is_module(obj)) {
> > > -			ret = klp_verify_vmlinux_symbol(reloc->name,
> > > -							reloc->val);
> > > -			if (ret)
> > > -				return ret;
> > > -		} else {
> > > -			/* module, reloc->val needs to be discovered */
> > > -			if (reloc->external)
> > > -				ret = klp_find_external_symbol(pmod,
> > > -							       reloc->name,
> > > -							       &reloc->val);
> > > -			else
> > > -				ret = klp_find_object_symbol(obj->mod->name,
> > > -							     reloc->name,
> > > -							     0, &reloc->val);
> > > -			if (ret)
> > > -				return ret;
> > > -		}
> > > +		/* discover the address of the referenced symbol */
> > > +		if (reloc->external) {
> > > +			if (reloc->sympos > 0) {
> > > +				pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
> > > +				       reloc->name);
> > > +				return -EINVAL;
> > > +			}
> > > +			ret = klp_find_external_symbol(pmod, reloc->name, &val);
> > > +		} else
> > > +			ret = klp_find_object_symbol(obj->mod->name,
> > > +						     reloc->name,
> > > +						     reloc->sympos,
> > > +						     &val);
> > 
> > I think this will cause an unwanted effect if a relocation is for vmlinux 
> > symbol. obj->mod is NULL in that case. So obj->name should be there. Can 
> > you test it with kpatch, Chris, please? If that is possible.
> > 
> > Thanks,
> > Miroslav
> >
> 
> Yes I need to fix this, an option would be to use:
> 	ret = klp_find_object_symbol(obj->name ? obj->name : obj->mod->name,
> 				     reloc->name, 0, &reloc->val);

Instead of

  'obj->name ? obj->name : obj->mod->name'
  
I think it can just be 'obj->name'.

If it's patching a module, obj->name will be the module name, otherwise
it will be NULL (for patching vmlinux).  klp_find_object_symbol() is
equipped to handle it either way.

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name
  2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
                                             ` (2 preceding siblings ...)
  2015-11-20 17:25                           ` [PATCH 3/3 v8] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
@ 2015-12-02  2:40                           ` Chris J Arges
  2015-12-02  2:40                             ` [PATCH 1/3 v9] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
                                               ` (5 more replies)
  3 siblings, 6 replies; 104+ messages in thread
From: Chris J Arges @ 2015-12-02  2:40 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes, jeyu
  Cc: Chris J Arges

Currently, patching objects with duplicate symbol names fail because the
creation of the sysfs function directory collides with the previous
attempt. Appending old_addr to the function name is problematic as it
reveals the address of the function being patch to a normal user. Using
the symbol's occurrence in kallsyms to postfix the function name in the
sysfs directory solves the issue of having consistent unique names and
ensuring that the address is not exposed to a normal user.

In addition, using the symbol position as the user's method to disambiguate
symbols instead of addr allows for disambiguating symbols in modules as
well for both function addresses and for relocs. This also simplifies much
of the code. Special handling for kASLR is no longer needed and can be
removed. The klp_find_verify_func_addr function can be replaced by
klp_find_object_symbol, and klp_verify_vmlinux_symbol and its callback can
be removed completely.

The following set of patches use symbol positioning instead of old
addresses to disambiguate symbols that have the same name in a given
object. This is necessary in order to be able to patch symbols with the
same name within the same object. This requires modifications to the
klp_func and klp_reloc structures to add an additional element. In addition
the scheme used for the func directory in sysfs is modified to append the
symbols occurrence in kallsyms.

In addition, I've tested this patchset against a modified kpatch. I
modified the kpatch livepatch scaffolding to set lreloc->sympos = 0, and
lfunc->old_sympos to the nth occurrence of the symbol for that object in
kallsyms. I was able to patch the same test patch as described here:
  https://github.com/dynup/kpatch/issues/493
I've also tested this with sample livepatch code to test if the various
old_sympos values work for unique and duplicate functions.

v9:
 - use mod->name instead of mod->obj->name for klp_find_object_symbol in
   klp_write_object_relocations
 - rebase on current master
 - tested with kpatch

v8:
 - explain motivation and necessity in initial patch
 - don't support sympos for external relocations

v7:
 - make count/pos checking in klp_find_callback more readable
 - fix klp_write_object_relocations sympos/external checking

v6:
 - move sympos arg before addr in klp_find_object_symbol
 - make comments more accurate, remove unnecessary whitespace
 - improve cover letter

v5:
 - remove val from klp_reloc struct
 - klp_write_object_relocations doesn't use sympos with external relocs
 - add Petr Mladek's patch to simplify relocated external symbol code
 - add optimization in klp_find_callback in unique case
 - remove klp_find_verify_func_addr
 - amend/remove commit messages/comments to be more precise


Chris J Arges (3):
  livepatch: add old_sympos as disambiguator field to klp_func
  livepatch: add sympos as disambiguator field to klp_reloc
  livepatch: function,sympos scheme in livepatch sysfs directory

 Documentation/ABI/testing/sysfs-kernel-livepatch |   6 +-
 include/linux/livepatch.h                        |  24 ++--
 kernel/livepatch/core.c                          | 164 ++++++++---------------
 3 files changed, 74 insertions(+), 120 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 1/3 v9] livepatch: add old_sympos as disambiguator field to klp_func
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
@ 2015-12-02  2:40                             ` Chris J Arges
  2015-12-02  2:40                             ` [PATCH 2/3 v9] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
                                               ` (4 subsequent siblings)
  5 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-12-02  2:40 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes, jeyu
  Cc: Chris J Arges, Seth Jennings, Vojtech Pavlik

Currently, patching objects with duplicate symbol names fail because the
creation of the sysfs function directory collides with the previous
attempt. Appending old_addr to the function name is problematic as it
reveals the address of the function being patch to a normal user. Using
the symbol's occurrence in kallsyms to postfix the function name in the
sysfs directory solves the issue of having consistent unique names and
ensuring that the address is not exposed to a normal user.

In addition, using the symbol position as the user's method to disambiguate
symbols instead of addr allows for disambiguating symbols in modules as
well for both function addresses and for relocs. This also simplifies much
of the code. Special handling for kASLR is no longer needed and can be
removed. The klp_find_verify_func_addr function can be replaced by
klp_find_object_symbol, and klp_verify_vmlinux_symbol and its callback can
be removed completely.

In cases of duplicate symbols, old_sympos will be used to disambiguate
instead of old_addr. By default old_sympos will be 0, and patching will
only succeed if the symbol is unique. Specifying a positive value will
ensure that occurrence of the symbol in kallsyms for the patched object
will be used for patching if it is valid.

In addition, make old_addr an internal structure field not to be specified
by the user. Finally, remove klp_find_verify_func_addr as it can be
replaced by klp_find_object_symbol directly.

Support for symbol position disambiguation for relocations is added in the
next patch in this series.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h | 19 +++++++------
 kernel/livepatch/core.c   | 72 ++++++++++++++++++++---------------------------
 2 files changed, 41 insertions(+), 50 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index 31db7a0..b60e8ab 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -37,8 +37,9 @@ enum klp_state {
  * 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_addr:	a hint conveying at what address the old function
- *		can be found (optional, vmlinux patches only)
+ * @old_sympos: a hint indicating which symbol position the old function
+ *		can be found (optional)
+ * @old_addr:	the address of the function being patched
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
@@ -48,16 +49,16 @@ struct klp_func {
 	const char *old_name;
 	void *new_func;
 	/*
-	 * The old_addr field is optional and can be used to resolve
-	 * duplicate symbol names in the vmlinux object.  If this
-	 * information is not present, the symbol is located by name
-	 * with kallsyms. If the name is not unique and old_addr is
-	 * not provided, the patch application fails as there is no
-	 * way to resolve the ambiguity.
+	 * The old_sympos field is optional and can be used to resolve
+	 * duplicate symbol names in livepatch objects. If this field is zero,
+	 * it is expected the symbol is unique, otherwise patching fails. If
+	 * this value is greater than zero then that occurrence of the symbol
+	 * in kallsyms for the given object is used.
 	 */
-	unsigned long old_addr;
+	unsigned long old_sympos;
 
 	/* internal */
+	unsigned long old_addr;
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index db545cb..e416f96 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -135,13 +135,8 @@ struct klp_find_arg {
 	const char *objname;
 	const char *name;
 	unsigned long addr;
-	/*
-	 * If count == 0, the symbol was not found. If count == 1, a unique
-	 * match was found and addr is set.  If count > 1, there is
-	 * unresolvable ambiguity among "count" number of symbols with the same
-	 * name in the same object.
-	 */
 	unsigned long count;
+	unsigned long pos;
 };
 
 static int klp_find_callback(void *data, const char *name,
@@ -158,37 +153,48 @@ static int klp_find_callback(void *data, const char *name,
 	if (args->objname && strcmp(args->objname, mod->name))
 		return 0;
 
-	/*
-	 * args->addr might be overwritten if another match is found
-	 * but klp_find_object_symbol() handles this and only returns the
-	 * addr if count == 1.
-	 */
 	args->addr = addr;
 	args->count++;
 
+	/*
+	 * Finish the search when the symbol is found for the desired position
+	 * or the position is not defined for a non-unique symbol.
+	 */
+	if ((args->pos && (args->count == args->pos)) ||
+	    (!args->pos && (args->count > 1)))
+		return 1;
+
 	return 0;
 }
 
 static int klp_find_object_symbol(const char *objname, const char *name,
-				  unsigned long *addr)
+				  unsigned long sympos, unsigned long *addr)
 {
 	struct klp_find_arg args = {
 		.objname = objname,
 		.name = name,
 		.addr = 0,
-		.count = 0
+		.count = 0,
+		.pos = sympos,
 	};
 
 	mutex_lock(&module_mutex);
 	kallsyms_on_each_symbol(klp_find_callback, &args);
 	mutex_unlock(&module_mutex);
 
-	if (args.count == 0)
+	/*
+	 * Ensure an address was found. If sympos is 0, ensure symbol is unique;
+	 * otherwise ensure the symbol position count matches sympos.
+	 */
+	if (args.addr == 0)
 		pr_err("symbol '%s' not found in symbol table\n", name);
-	else if (args.count > 1)
+	else if (args.count > 1 && sympos == 0) {
 		pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 		       args.count, name, objname);
-	else {
+	} else if (sympos != args.count && sympos > 0) {
+		pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
+		       sympos, name, objname ? objname : "vmlinux");
+	} else {
 		*addr = args.addr;
 		return 0;
 	}
@@ -236,27 +242,6 @@ static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
 	return 0;
 }
 
-static int klp_find_verify_func_addr(struct klp_object *obj,
-				     struct klp_func *func)
-{
-	int ret;
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-	/* If KASLR has been enabled, adjust old_addr accordingly */
-	if (kaslr_enabled() && func->old_addr)
-		func->old_addr += kaslr_offset();
-#endif
-
-	if (!func->old_addr || klp_is_module(obj))
-		ret = klp_find_object_symbol(obj->name, func->old_name,
-					     &func->old_addr);
-	else
-		ret = klp_verify_vmlinux_symbol(func->old_name,
-						func->old_addr);
-
-	return ret;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -276,8 +261,11 @@ static int klp_find_external_symbol(struct module *pmod, const char *name,
 	}
 	preempt_enable();
 
-	/* otherwise check if it's in another .o within the patch module */
-	return klp_find_object_symbol(pmod->name, name, addr);
+	/*
+	 * Check if it's in another .o within the patch module. This also
+	 * checks that the external symbol is unique.
+	 */
+	return klp_find_object_symbol(pmod->name, name, 0, addr);
 }
 
 static int klp_write_object_relocations(struct module *pmod,
@@ -313,7 +301,7 @@ static int klp_write_object_relocations(struct module *pmod,
 			else
 				ret = klp_find_object_symbol(obj->mod->name,
 							     reloc->name,
-							     &reloc->val);
+							     0, &reloc->val);
 			if (ret)
 				return ret;
 		}
@@ -756,7 +744,9 @@ static int klp_init_object_loaded(struct klp_patch *patch,
 	}
 
 	klp_for_each_func(obj, func) {
-		ret = klp_find_verify_func_addr(obj, func);
+		ret = klp_find_object_symbol(obj->name, func->old_name,
+					     func->old_sympos,
+					     &func->old_addr);
 		if (ret)
 			return ret;
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 2/3 v9] livepatch: add sympos as disambiguator field to klp_reloc
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
  2015-12-02  2:40                             ` [PATCH 1/3 v9] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
@ 2015-12-02  2:40                             ` Chris J Arges
  2015-12-14 12:45                               ` Miroslav Benes
  2015-12-02  2:40                             ` [PATCH 3/3 v9] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
                                               ` (3 subsequent siblings)
  5 siblings, 1 reply; 104+ messages in thread
From: Chris J Arges @ 2015-12-02  2:40 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes, jeyu
  Cc: Chris J Arges, Seth Jennings, Vojtech Pavlik

In cases of duplicate symbols, sympos will be used to disambiguate instead
of val. By default sympos will be 0, and patching will only succeed if
the symbol is unique. Specifying a positive value will ensure that
occurrence of the symbol in kallsyms for the patched object will be used
for patching if it is valid. For external relocations sympos is not
supported.

Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
as they are no longer used.

>From the klp_reloc structure remove val, as it can be refactored as a
local variable in klp_write_object_relocations.

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 include/linux/livepatch.h |  5 ++-
 kernel/livepatch/core.c   | 84 +++++++++++------------------------------------
 2 files changed, 21 insertions(+), 68 deletions(-)

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index b60e8ab..a882865 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -67,8 +67,7 @@ struct klp_func {
 /**
  * struct klp_reloc - relocation structure for live patching
  * @loc:	address where the relocation will be written
- * @val:	address of the referenced symbol (optional,
- *		vmlinux	patches only)
+ * @sympos:	position in kallsyms to disambiguate symbols (optional)
  * @type:	ELF relocation type
  * @name:	name of the referenced symbol (for lookup/verification)
  * @addend:	offset from the referenced symbol
@@ -76,7 +75,7 @@ struct klp_func {
  */
 struct klp_reloc {
 	unsigned long loc;
-	unsigned long val;
+	unsigned long sympos;
 	unsigned long type;
 	const char *name;
 	int addend;
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index e416f96..e842534 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -203,45 +203,6 @@ static int klp_find_object_symbol(const char *objname, const char *name,
 	return -EINVAL;
 }
 
-struct klp_verify_args {
-	const char *name;
-	const unsigned long addr;
-};
-
-static int klp_verify_callback(void *data, const char *name,
-			       struct module *mod, unsigned long addr)
-{
-	struct klp_verify_args *args = data;
-
-	if (!mod &&
-	    !strcmp(args->name, name) &&
-	    args->addr == addr)
-		return 1;
-
-	return 0;
-}
-
-static int klp_verify_vmlinux_symbol(const char *name, unsigned long addr)
-{
-	struct klp_verify_args args = {
-		.name = name,
-		.addr = addr,
-	};
-	int ret;
-
-	mutex_lock(&module_mutex);
-	ret = kallsyms_on_each_symbol(klp_verify_callback, &args);
-	mutex_unlock(&module_mutex);
-
-	if (!ret) {
-		pr_err("symbol '%s' not found at specified address 0x%016lx, kernel mismatch?\n",
-			name, addr);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 /*
  * external symbols are located outside the parent object (where the parent
  * object is either vmlinux or the kmod being patched).
@@ -272,6 +233,7 @@ static int klp_write_object_relocations(struct module *pmod,
 					struct klp_object *obj)
 {
 	int ret;
+	unsigned long val;
 	struct klp_reloc *reloc;
 
 	if (WARN_ON(!klp_is_object_loaded(obj)))
@@ -281,35 +243,27 @@ static int klp_write_object_relocations(struct module *pmod,
 		return -EINVAL;
 
 	for (reloc = obj->relocs; reloc->name; reloc++) {
-		if (!klp_is_module(obj)) {
-
-#if defined(CONFIG_RANDOMIZE_BASE)
-			/* If KASLR has been enabled, adjust old value accordingly */
-			if (kaslr_enabled())
-				reloc->val += kaslr_offset();
-#endif
-			ret = klp_verify_vmlinux_symbol(reloc->name,
-							reloc->val);
-			if (ret)
-				return ret;
-		} else {
-			/* module, reloc->val needs to be discovered */
-			if (reloc->external)
-				ret = klp_find_external_symbol(pmod,
-							       reloc->name,
-							       &reloc->val);
-			else
-				ret = klp_find_object_symbol(obj->mod->name,
-							     reloc->name,
-							     0, &reloc->val);
-			if (ret)
-				return ret;
-		}
+		/* discover the address of the referenced symbol */
+		if (reloc->external) {
+			if (reloc->sympos > 0) {
+				pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
+				       reloc->name);
+				return -EINVAL;
+			}
+			ret = klp_find_external_symbol(pmod, reloc->name, &val);
+		} else
+			ret = klp_find_object_symbol(obj->name,
+						     reloc->name,
+						     reloc->sympos,
+						     &val);
+		if (ret)
+			return ret;
+
 		ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
-					     reloc->val + reloc->addend);
+					     val + reloc->addend);
 		if (ret) {
 			pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
-			       reloc->name, reloc->val, ret);
+			       reloc->name, val, ret);
 			return ret;
 		}
 	}
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 3/3 v9] livepatch: function,sympos scheme in livepatch sysfs directory
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
  2015-12-02  2:40                             ` [PATCH 1/3 v9] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
  2015-12-02  2:40                             ` [PATCH 2/3 v9] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-12-02  2:40                             ` Chris J Arges
  2015-12-02 15:28                             ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Petr Mladek
                                               ` (2 subsequent siblings)
  5 siblings, 0 replies; 104+ messages in thread
From: Chris J Arges @ 2015-12-02  2:40 UTC (permalink / raw)
  To: live-patching, linux-kernel, jpoimboe, jikos, pmladek, mbenes, jeyu
  Cc: Chris J Arges, Seth Jennings, Vojtech Pavlik, linux-api

The following directory structure will allow for cases when the same
function name exists in a single object.
	/sys/kernel/livepatch/<patch>/<object>/<function,sympos>

The sympos number corresponds to the nth occurrence of the symbol name in
kallsyms for the patched object.

An example of patching multiple symbols can be found here:
	https://github.com/dynup/kpatch/issues/493

Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>
---
 Documentation/ABI/testing/sysfs-kernel-livepatch |  6 +++++-
 kernel/livepatch/core.c                          | 10 ++++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-livepatch b/Documentation/ABI/testing/sysfs-kernel-livepatch
index 5bf42a8..da87f43 100644
--- a/Documentation/ABI/testing/sysfs-kernel-livepatch
+++ b/Documentation/ABI/testing/sysfs-kernel-livepatch
@@ -33,7 +33,7 @@ Description:
 		The object directory contains subdirectories for each function
 		that is patched within the object.
 
-What:		/sys/kernel/livepatch/<patch>/<object>/<function>
+What:		/sys/kernel/livepatch/<patch>/<object>/<function,sympos>
 Date:		Nov 2014
 KernelVersion:	3.19.0
 Contact:	live-patching@vger.kernel.org
@@ -41,4 +41,8 @@ Description:
 		The function directory contains attributes regarding the
 		properties and state of the patched function.
 
+		The directory name contains the patched function name and a
+		sympos number corresponding to the nth occurrence of the symbol
+		name in kallsyms for the patched object.
+
 		There are currently no such attributes.
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index e842534..94893e8 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -535,7 +535,7 @@ EXPORT_SYMBOL_GPL(klp_enable_patch);
  * /sys/kernel/livepatch/<patch>
  * /sys/kernel/livepatch/<patch>/enabled
  * /sys/kernel/livepatch/<patch>/<object>
- * /sys/kernel/livepatch/<patch>/<object>/<func>
+ * /sys/kernel/livepatch/<patch>/<object>/<function,sympos>
  */
 
 static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr,
@@ -680,8 +680,14 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
 
+	/* The format for the sysfs directory is <function,sympos> where sympos
+	 * is the nth occurrence of this symbol in kallsyms for the patched
+	 * object. If the user selects 0 for old_sympos, then 1 will be used
+	 * since a unique symbol will be the first occurrence.
+	 */
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
-				    &obj->kobj, "%s", func->old_name);
+				    &obj->kobj, "%s,%lu", func->old_name,
+				    func->old_sympos ? func->old_sympos : 1);
 }
 
 /* parts of the initialization that is done only when the object is loaded */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
                                               ` (2 preceding siblings ...)
  2015-12-02  2:40                             ` [PATCH 3/3 v9] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
@ 2015-12-02 15:28                             ` Petr Mladek
  2015-12-03 17:59                             ` Josh Poimboeuf
  2015-12-03 22:04                             ` Jiri Kosina
  5 siblings, 0 replies; 104+ messages in thread
From: Petr Mladek @ 2015-12-02 15:28 UTC (permalink / raw)
  To: Chris J Arges; +Cc: live-patching, linux-kernel, jpoimboe, jikos, mbenes, jeyu

On Tue 2015-12-01 20:40:53, Chris J Arges wrote:
> v9:
>  - use mod->name instead of mod->obj->name for klp_find_object_symbol in
>    klp_write_object_relocations
>  - rebase on current master
>  - tested with kpatch

The last version looks fine to me. Feel free to add the following
into all three patches:

Reviewed-by: Petr Mladek <pmladek@suse.com>


Thanks,
Petr

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
                                               ` (3 preceding siblings ...)
  2015-12-02 15:28                             ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Petr Mladek
@ 2015-12-03 17:59                             ` Josh Poimboeuf
  2015-12-03 22:04                             ` Jiri Kosina
  5 siblings, 0 replies; 104+ messages in thread
From: Josh Poimboeuf @ 2015-12-03 17:59 UTC (permalink / raw)
  To: Chris J Arges; +Cc: live-patching, linux-kernel, jikos, pmladek, mbenes, jeyu

On Tue, Dec 01, 2015 at 08:40:53PM -0600, Chris J Arges wrote:
> Currently, patching objects with duplicate symbol names fail because the
> creation of the sysfs function directory collides with the previous
> attempt. Appending old_addr to the function name is problematic as it
> reveals the address of the function being patch to a normal user. Using
> the symbol's occurrence in kallsyms to postfix the function name in the
> sysfs directory solves the issue of having consistent unique names and
> ensuring that the address is not exposed to a normal user.
> 
> In addition, using the symbol position as the user's method to disambiguate
> symbols instead of addr allows for disambiguating symbols in modules as
> well for both function addresses and for relocs. This also simplifies much
> of the code. Special handling for kASLR is no longer needed and can be
> removed. The klp_find_verify_func_addr function can be replaced by
> klp_find_object_symbol, and klp_verify_vmlinux_symbol and its callback can
> be removed completely.
> 
> The following set of patches use symbol positioning instead of old
> addresses to disambiguate symbols that have the same name in a given
> object. This is necessary in order to be able to patch symbols with the
> same name within the same object. This requires modifications to the
> klp_func and klp_reloc structures to add an additional element. In addition
> the scheme used for the func directory in sysfs is modified to append the
> symbols occurrence in kallsyms.
> 
> In addition, I've tested this patchset against a modified kpatch. I
> modified the kpatch livepatch scaffolding to set lreloc->sympos = 0, and
> lfunc->old_sympos to the nth occurrence of the symbol for that object in
> kallsyms. I was able to patch the same test patch as described here:
>   https://github.com/dynup/kpatch/issues/493
> I've also tested this with sample livepatch code to test if the various
> old_sympos values work for unique and duplicate functions.
> 
> v9:
>  - use mod->name instead of mod->obj->name for klp_find_object_symbol in
>    klp_write_object_relocations
>  - rebase on current master
>  - tested with kpatch

For the series:

Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>

-- 
Josh

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name
  2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
                                               ` (4 preceding siblings ...)
  2015-12-03 17:59                             ` Josh Poimboeuf
@ 2015-12-03 22:04                             ` Jiri Kosina
  5 siblings, 0 replies; 104+ messages in thread
From: Jiri Kosina @ 2015-12-03 22:04 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, linux-kernel, jpoimboe, pmladek, mbenes, jeyu

Chris,

thanks a lot for promptly reacting to all the feedback.

I've now applied this to livepatching.git#for-4.5/core.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 2/3 v9] livepatch: add sympos as disambiguator field to klp_reloc
  2015-12-02  2:40                             ` [PATCH 2/3 v9] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
@ 2015-12-14 12:45                               ` Miroslav Benes
  0 siblings, 0 replies; 104+ messages in thread
From: Miroslav Benes @ 2015-12-14 12:45 UTC (permalink / raw)
  To: Chris J Arges
  Cc: live-patching, linux-kernel, jpoimboe, jikos, pmladek, jeyu,
	Seth Jennings, Vojtech Pavlik

On Tue, 1 Dec 2015, Chris J Arges wrote:

> In cases of duplicate symbols, sympos will be used to disambiguate instead
> of val. By default sympos will be 0, and patching will only succeed if
> the symbol is unique. Specifying a positive value will ensure that
> occurrence of the symbol in kallsyms for the patched object will be used
> for patching if it is valid. For external relocations sympos is not
> supported.
> 
> Remove klp_verify_callback, klp_verify_args and klp_verify_vmlinux_symbol
> as they are no longer used.
> 
> >From the klp_reloc structure remove val, as it can be refactored as a
> local variable in klp_write_object_relocations.
> 
> Signed-off-by: Chris J Arges <chris.j.arges@canonical.com>

FWIW

Reviewed-by: Miroslav Benes <mbenes@suse.cz>

Miroslav

^ permalink raw reply	[flat|nested] 104+ messages in thread

end of thread, other threads:[~2015-12-14 12:45 UTC | newest]

Thread overview: 104+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-02 17:58 [PATCH] livepatch: old_name.number scheme in livepatch sysfs directory Chris J Arges
2015-11-02 17:58 ` Chris J Arges
2015-11-02 19:15 ` Jessica Yu
2015-11-02 19:52 ` [PATCH] " Josh Poimboeuf
2015-11-02 19:52   ` Josh Poimboeuf
2015-11-02 20:16   ` Chris J Arges
2015-11-02 20:32     ` Josh Poimboeuf
2015-11-02 22:59       ` [PATCH v2] " Chris J Arges
2015-11-02 22:59         ` Chris J Arges
2015-11-03  9:50         ` Miroslav Benes
2015-11-03 15:03           ` Josh Poimboeuf
2015-11-03 10:52         ` Miroslav Benes
2015-11-03 10:52           ` Miroslav Benes
2015-11-03 12:44           ` Petr Mladek
2015-11-03 12:44             ` Petr Mladek
2015-11-03 15:03             ` Josh Poimboeuf
2015-11-03 15:03               ` Josh Poimboeuf
2015-11-03 19:57             ` Jiri Kosina
2015-11-03 19:57               ` Jiri Kosina
2015-11-03 20:06               ` Josh Poimboeuf
2015-11-03 20:06                 ` Josh Poimboeuf
     [not found]                 ` <1447259366-7055-1-git-send-email-chris.j.arges@canonical.com>
2015-11-11 16:28                   ` [PATCH 1/3 v4] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
2015-11-11 17:43                     ` Josh Poimboeuf
2015-11-12 10:22                     ` Miroslav Benes
2015-11-11 16:29                   ` [PATCH 2/3 v4] livepatch: add old_sympos as disambiguator field to klp_reloc Chris J Arges
2015-11-11 16:39                     ` Chris J Arges
2015-11-11 17:57                     ` Josh Poimboeuf
2015-11-12 14:31                       ` Petr Mladek
2015-11-12 19:19                         ` Josh Poimboeuf
2015-11-13 13:54                           ` Petr Mladek
2015-11-13 16:59                             ` Josh Poimboeuf
2015-11-16 12:11                               ` Petr Mladek
2015-11-12 10:23                     ` Miroslav Benes
2015-11-11 16:29                   ` [PATCH 3/3 v4] livepatch: old_name,number scheme in livepatch sysfs directory Chris J Arges
2015-11-11 18:01                     ` Josh Poimboeuf
2015-11-11 18:01                       ` Josh Poimboeuf
     [not found]                   ` <1447347595-30728-1-git-send-email-chris.j.arges@canonical.com>
2015-11-12 16:59                     ` [PATCH 1/4 v5] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
2015-11-12 19:45                       ` Josh Poimboeuf
2015-11-13  9:56                       ` Jiri Kosina
2015-11-13 10:14                       ` Miroslav Benes
2015-11-13 16:27                       ` Petr Mladek
2015-11-12 16:59                     ` [PATCH 2/4 v5] livepatch: Simplify code for relocated external symbols Chris J Arges
2015-11-13 10:24                       ` Miroslav Benes
2015-11-13 13:55                         ` Petr Mladek
2015-11-12 16:59                     ` [PATCH 3/4 v5] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
2015-11-12 19:50                       ` Josh Poimboeuf
2015-11-13 16:42                       ` Petr Mladek
2015-11-12 16:59                     ` [PATCH 4/4 v5] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
     [not found]                     ` <1447431804-18786-1-git-send-email-chris.j.arges@canonical.com>
2015-11-13 16:23                       ` [PATCH 1/3 v6] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
2015-11-13 16:23                       ` [PATCH 2/3 v6] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
2015-11-13 16:23                       ` [PATCH 3/3 v6] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
     [not found]                       ` <1447693391-10065-1-git-send-email-chris.j.arges@canonical.com>
2015-11-16 17:03                         ` [PATCH 1/3 v7] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
2015-11-16 21:59                           ` Jiri Kosina
2015-11-17 14:29                             ` Chris J Arges
2015-11-19 10:02                               ` Jiri Kosina
2015-11-16 17:03                         ` [PATCH 2/3 v7] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
2015-11-18  9:56                           ` Miroslav Benes
2015-11-18 14:01                             ` Josh Poimboeuf
2015-11-18 16:47                               ` Petr Mladek
2015-11-18 16:37                           ` Petr Mladek
2015-11-18 16:39                             ` Chris J Arges
2015-11-18 16:55                               ` Petr Mladek
2015-11-18 20:34                                 ` Jiri Kosina
2015-11-16 17:03                         ` [PATCH 3/3 v7] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
2015-11-20 17:25                         ` [PATCH 0/3 v8] livepatch: disambiguate symbols with the same name Chris J Arges
2015-11-20 17:25                           ` [PATCH 1/3 v8] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
2015-11-23  9:47                             ` Miroslav Benes
2015-11-20 17:25                           ` [PATCH 2/3 v8] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
2015-11-23  9:52                             ` Miroslav Benes
2015-11-30 20:46                               ` Chris J Arges
2015-12-01  1:17                                 ` Josh Poimboeuf
2015-11-20 17:25                           ` [PATCH 3/3 v8] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
2015-11-23  9:47                             ` Miroslav Benes
2015-12-02  2:40                           ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Chris J Arges
2015-12-02  2:40                             ` [PATCH 1/3 v9] livepatch: add old_sympos as disambiguator field to klp_func Chris J Arges
2015-12-02  2:40                             ` [PATCH 2/3 v9] livepatch: add sympos as disambiguator field to klp_reloc Chris J Arges
2015-12-14 12:45                               ` Miroslav Benes
2015-12-02  2:40                             ` [PATCH 3/3 v9] livepatch: function,sympos scheme in livepatch sysfs directory Chris J Arges
2015-12-02 15:28                             ` [PATCH 0/3 v9] livepatch: disambiguate symbols with the same name Petr Mladek
2015-12-03 17:59                             ` Josh Poimboeuf
2015-12-03 22:04                             ` Jiri Kosina
2015-11-03 14:58           ` [PATCH v2] livepatch: old_name.number scheme in livepatch sysfs directory Josh Poimboeuf
2015-11-03 16:09             ` Miroslav Benes
2015-11-03 16:50               ` Josh Poimboeuf
2015-11-03 20:42                 ` Chris J Arges
2015-11-03 20:42                   ` Chris J Arges
2015-11-04  9:52                 ` Miroslav Benes
2015-11-04  9:52                   ` Miroslav Benes
2015-11-04 16:03                   ` Josh Poimboeuf
2015-11-04 16:17                     ` Chris J Arges
2015-11-04 16:17                       ` Chris J Arges
2015-11-05 15:18                     ` Miroslav Benes
2015-11-05 15:56                       ` Josh Poimboeuf
2015-11-05 16:07                         ` Chris J Arges
2015-11-09 16:16                         ` [PATCH v3] livepatch: old_name,number " Chris J Arges
2015-11-09 16:16                           ` Chris J Arges
2015-11-09 20:56                           ` Josh Poimboeuf
2015-11-09 23:01                             ` Chris J Arges
2015-11-09 23:01                               ` Chris J Arges
2015-11-10  4:54                               ` Josh Poimboeuf
2015-11-10  8:49                                 ` Miroslav Benes
2015-11-10 13:40                                   ` Josh Poimboeuf
2015-11-10 13:40                                     ` Josh Poimboeuf
2015-11-10  9:02                           ` Miroslav Benes

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.