All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiri Slaby <jslaby@suse.cz>
To: live-patching@vger.kernel.org
Cc: jpoimboe@redhat.com, sjenning@redhat.com, jkosina@suse.cz,
	vojtech@suse.cz, mingo@redhat.com, linux-kernel@vger.kernel.org,
	Jiri Slaby <jslaby@suse.cz>
Subject: [RFC kgr on klp 5/9] livepatch: teach klp about consistency models
Date: Mon,  4 May 2015 13:40:21 +0200	[thread overview]
Message-ID: <1430739625-4658-5-git-send-email-jslaby@suse.cz> (raw)
In-Reply-To: <1430739625-4658-1-git-send-email-jslaby@suse.cz>

We want more concise consistency models than simple is. This is a
preparation for other, more complex ones. It moves the simple handling
out of ftrace handler and is called as newly introduced struct
klp_cmodel->stub. This way, every model can implement its own handler.

On the top of that, I assume the structure will be extended over time.
For example, kGraft-like patching will need pre-patch and post-patch
hooks and more.

We store the models in a list and all have its ID, specified in every
patch. The ID is then looked up in the list and appropriate cmodel
used.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 include/linux/livepatch.h            | 35 ++++++++++++++++++++++++++++++++
 kernel/livepatch/Makefile            |  2 +-
 kernel/livepatch/cmodel-simple.c     | 39 ++++++++++++++++++++++++++++++++++++
 kernel/livepatch/core.c              | 37 ++++++++++++++++++++++++++++++----
 samples/livepatch/livepatch-sample.c |  1 +
 5 files changed, 109 insertions(+), 5 deletions(-)
 create mode 100644 kernel/livepatch/cmodel-simple.c

diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h
index fabb067a3f1d..009f308ff756 100644
--- a/include/linux/livepatch.h
+++ b/include/linux/livepatch.h
@@ -23,11 +23,36 @@
 
 #include <linux/module.h>
 #include <linux/ftrace.h>
+#include <linux/ptrace.h>
 
 #if IS_ENABLED(CONFIG_LIVEPATCH)
 
 #include <asm/livepatch.h>
 
+struct klp_func;
+
+/**
+ * enum klp_cmodel_id - possible consistency models
+ */
+enum klp_cmodel_id {
+	KLP_CM_INVALID = 0,
+	KLP_CM_SIMPLE, /* LEAVE_FUNCTION and SWITCH_FUNCTION */
+};
+
+/**
+ * struct klp_cmodel - implementation of a consistency model
+ * @id: id of this model (from enum klp_cmodel_id)
+ * @list: member of klp_cmodel_list
+ * @stub: what to use as an ftrace handler (annotate with notrace!)
+ */
+struct klp_cmodel {
+	const enum klp_cmodel_id id;
+	struct list_head list;
+
+	void (*stub)(struct list_head *func_stack, struct klp_func *func,
+			struct pt_regs *regs);
+};
+
 enum klp_state {
 	KLP_DISABLED,
 	KLP_ENABLED
@@ -42,6 +67,7 @@ enum klp_state {
  * @kobj:	kobject for sysfs resources
  * @state:	tracks function-level patch application state
  * @stack_node:	list node for klp_ops func_stack list
+ * @stub:	cache of klp_patch.cmodel.stub
  */
 struct klp_func {
 	/* external */
@@ -61,6 +87,8 @@ struct klp_func {
 	struct kobject kobj;
 	enum klp_state state;
 	struct list_head stack_node;
+	void (*stub)(struct list_head *func_stack, struct klp_func *func,
+			struct pt_regs *regs);
 };
 
 /**
@@ -108,19 +136,23 @@ struct klp_object {
  * struct klp_patch - patch structure for live patching
  * @mod:	reference to the live patch module
  * @objs:	object entries for kernel objects to be patched
+ * @cmodel_id:	consistency model used to apply this patch
  * @list:	list node for global list of registered patches
  * @kobj:	kobject for sysfs resources
  * @state:	tracks patch-level application state
+ * @cmodel:	cmodel_id's implementation
  */
 struct klp_patch {
 	/* external */
 	struct module *mod;
 	struct klp_object *objs;
+	const enum klp_cmodel_id cmodel_id;
 
 	/* internal */
 	struct list_head list;
 	struct kobject kobj;
 	enum klp_state state;
+	struct klp_cmodel *cmodel;
 };
 
 #define klp_for_each_object(patch, obj) \
@@ -144,6 +176,9 @@ int klp_unregister_patch(struct klp_patch *);
 int klp_enable_patch(struct klp_patch *);
 int klp_disable_patch(struct klp_patch *);
 
+void klp_init_cmodel_simple(void);
+void klp_register_cmodel(struct klp_cmodel *);
+
 #endif /* CONFIG_LIVEPATCH */
 
 #endif /* _LINUX_LIVEPATCH_H_ */
diff --git a/kernel/livepatch/Makefile b/kernel/livepatch/Makefile
index e8780c0901d9..926533777247 100644
--- a/kernel/livepatch/Makefile
+++ b/kernel/livepatch/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_LIVEPATCH) += livepatch.o
 
-livepatch-objs := core.o
+livepatch-objs := core.o cmodel-simple.o
diff --git a/kernel/livepatch/cmodel-simple.c b/kernel/livepatch/cmodel-simple.c
new file mode 100644
index 000000000000..d4e430ff40c0
--- /dev/null
+++ b/kernel/livepatch/cmodel-simple.c
@@ -0,0 +1,39 @@
+/*
+ * cmodel-simple.c - KLP Simple Consistency Model
+ *
+ * Copyright (C) 2015 Seth Jennings <sjenning@redhat.com>
+ * Copyright (C) 2015 SUSE
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/list.h>
+#include <linux/livepatch.h>
+
+static void notrace klp_simple_stub(struct list_head *func_stack,
+		struct klp_func *func, struct pt_regs *regs)
+{
+	klp_arch_set_pc(regs, (unsigned long)func->new_func);
+}
+
+static struct klp_cmodel klp_simple_model = {
+	.id = KLP_CM_SIMPLE,
+	.stub = klp_simple_stub,
+};
+
+void klp_init_cmodel_simple(void)
+{
+	klp_register_cmodel(&klp_simple_model);
+}
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 2da42be84452..ab6a36688c93 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -58,6 +58,7 @@ static DEFINE_MUTEX(klp_mutex);
 
 static LIST_HEAD(klp_patches);
 static LIST_HEAD(klp_ops);
+static LIST_HEAD(klp_cmodel_list);
 
 static struct kobject *klp_root_kobj;
 
@@ -319,18 +320,16 @@ static void notrace klp_ftrace_handler(unsigned long ip,
 				       struct ftrace_ops *fops,
 				       struct pt_regs *regs)
 {
-	struct klp_ops *ops;
+	struct klp_ops *ops = container_of(fops, struct klp_ops, fops);
 	struct klp_func *func;
 
-	ops = container_of(fops, struct klp_ops, fops);
-
 	rcu_read_lock();
 	func = list_first_or_null_rcu(&ops->func_stack, struct klp_func,
 				      stack_node);
 	if (WARN_ON_ONCE(!func))
 		goto unlock;
 
-	klp_arch_set_pc(regs, (unsigned long)func->new_func);
+	func->stub(&ops->func_stack, func, regs);
 unlock:
 	rcu_read_unlock();
 }
@@ -720,6 +719,7 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
 {
 	INIT_LIST_HEAD(&func->stack_node);
 	func->state = KLP_DISABLED;
+	func->stub = klp_object_to_patch(obj)->cmodel->stub;
 
 	return kobject_init_and_add(&func->kobj, &klp_ktype_func,
 				    &obj->kobj, "%s", func->old_name);
@@ -790,13 +790,28 @@ free:
 static int klp_init_patch(struct klp_patch *patch)
 {
 	struct klp_object *obj;
+	struct klp_cmodel *cm, *cmodel = NULL;
 	int ret;
 
 	if (!patch->objs)
 		return -EINVAL;
 
+	list_for_each_entry(cm, &klp_cmodel_list, list) {
+		if (patch->cmodel_id == cm->id) {
+			cmodel = cm;
+			break;
+		}
+	}
+
+	if (!cmodel) {
+		pr_err("%s: patch '%ps' requires unknown consistency model %d\n",
+				__func__, patch, patch->cmodel_id);
+		return -EINVAL;
+	}
+
 	mutex_lock(&klp_mutex);
 
+	patch->cmodel = cmodel;
 	patch->state = KLP_DISABLED;
 
 	ret = kobject_init_and_add(&patch->kobj, &klp_ktype_patch,
@@ -893,6 +908,18 @@ int klp_register_patch(struct klp_patch *patch)
 }
 EXPORT_SYMBOL_GPL(klp_register_patch);
 
+/**
+ * klp_register_cmodel - register a consistency model
+ * @model: model to register
+ *
+ * This functions has to be synchronously called before klp_root_kobj is
+ * created in klp_init since we use no locking.
+ */
+void klp_register_cmodel(struct klp_cmodel *model)
+{
+	list_add_tail(&model->list, &klp_cmodel_list);
+}
+
 static void klp_module_notify_coming(struct klp_patch *patch,
 				     struct klp_object *obj)
 {
@@ -993,6 +1020,8 @@ static int klp_init(void)
 		return -EINVAL;
 	}
 
+	klp_init_cmodel_simple();
+
 	ret = register_module_notifier(&klp_module_nb);
 	if (ret)
 		return ret;
diff --git a/samples/livepatch/livepatch-sample.c b/samples/livepatch/livepatch-sample.c
index fb8c8614e728..48621de040db 100644
--- a/samples/livepatch/livepatch-sample.c
+++ b/samples/livepatch/livepatch-sample.c
@@ -63,6 +63,7 @@ static struct klp_object objs[] = {
 static struct klp_patch patch = {
 	.mod = THIS_MODULE,
 	.objs = objs,
+	.cmodel_id = KLP_CM_SIMPLE,
 };
 
 static int livepatch_init(void)
-- 
2.3.5


  parent reply	other threads:[~2015-05-04 11:41 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-04 11:40 [RFC kgr on klp 1/9] livepatch: make kobject in klp_object statically allocated Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 2/9] livepatch: introduce patch/func-walking helpers Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 3/9] livepatch: add klp_*_to_patch helpers Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 4/9] livepatch: add kgr infrastructure Jiri Slaby
2015-05-04 12:23   ` Martin Schwidefsky
2015-05-05 13:27     ` Jiri Slaby
2015-05-05 14:34       ` Martin Schwidefsky
2015-05-04 11:40 ` Jiri Slaby [this message]
2015-05-04 11:40 ` [RFC kgr on klp 6/9] livepatch: do not allow failure while really patching Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 7/9] livepatch: propagate the patch status to functions Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 8/9] livepatch: add kgraft-like patching Jiri Slaby
2015-05-04 11:40 ` [RFC kgr on klp 9/9] livepatch: send a fake signal to all tasks Jiri Slaby
2015-05-04 14:34   ` Oleg Nesterov
2015-05-06 12:58     ` Miroslav Benes
2015-05-04 12:20 ` [RFC kgr on klp 0/9] kGraft on the top of KLP Jiri Slaby
2015-05-04 15:44   ` Josh Poimboeuf
2015-05-04 22:48     ` Jiri Kosina
2015-05-05  3:43       ` Josh Poimboeuf
2015-05-05  6:14         ` Jiri Kosina
2015-05-05 16:24           ` Josh Poimboeuf
2015-05-12  9:45             ` Jiri Kosina
2015-05-12 15:20               ` Josh Poimboeuf

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=1430739625-4658-5-git-send-email-jslaby@suse.cz \
    --to=jslaby@suse.cz \
    --cc=jkosina@suse.cz \
    --cc=jpoimboe@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=sjenning@redhat.com \
    --cc=vojtech@suse.cz \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is 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.