[PATCH v4 2/3] livepatch: shuffle core.c function order
From: Jason Baron
Date: Thu Oct 12 2017 - 17:13:24 EST
In preparation for __klp_enable_patch() to call a number of 'static'
functions, in a subsequent patch, move them earlier in core.c. This patch
should be a nop from a functional pov.
Signed-off-by: Jason Baron <jbaron@xxxxxxxxxx>
Cc: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
Cc: Jessica Yu <jeyu@xxxxxxxxxx>
Cc: Jiri Kosina <jikos@xxxxxxxxxx>
Cc: Miroslav Benes <mbenes@xxxxxxx>
Cc: Petr Mladek <pmladek@xxxxxxxx>
---
kernel/livepatch/core.c | 349 ++++++++++++++++++++++++------------------------
1 file changed, 173 insertions(+), 176 deletions(-)
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index b7f77be..f53eed5 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -283,6 +283,179 @@ static int klp_write_object_relocations(struct module *pmod,
return ret;
}
+static void klp_kobj_release_object(struct kobject *kobj)
+{
+}
+
+static struct kobj_type klp_ktype_object = {
+ .release = klp_kobj_release_object,
+ .sysfs_ops = &kobj_sysfs_ops,
+};
+
+static void klp_kobj_release_func(struct kobject *kobj)
+{
+}
+
+static struct kobj_type klp_ktype_func = {
+ .release = klp_kobj_release_func,
+ .sysfs_ops = &kobj_sysfs_ops,
+};
+
+/*
+ * Free all functions' kobjects in the array up to some limit. When limit is
+ * NULL, all kobjects are freed.
+ */
+static void klp_free_funcs_limited(struct klp_object *obj,
+ struct klp_func *limit)
+{
+ struct klp_func *func;
+
+ for (func = obj->funcs; func->old_name && func != limit; func++)
+ kobject_put(&func->kobj);
+}
+
+/* Clean up when a patched object is unloaded */
+static void klp_free_object_loaded(struct klp_object *obj)
+{
+ struct klp_func *func;
+
+ obj->mod = NULL;
+
+ klp_for_each_func(obj, func)
+ func->old_addr = 0;
+}
+
+/*
+ * Free all objects' kobjects in the array up to some limit. When limit is
+ * NULL, all kobjects are freed.
+ */
+static void klp_free_objects_limited(struct klp_patch *patch,
+ struct klp_object *limit)
+{
+ struct klp_object *obj;
+
+ for (obj = patch->objs; obj->funcs && obj != limit; obj++) {
+ klp_free_funcs_limited(obj, NULL);
+ kobject_put(&obj->kobj);
+ }
+}
+
+static void klp_free_patch(struct klp_patch *patch)
+{
+ klp_free_objects_limited(patch, NULL);
+ if (!list_empty(&patch->list))
+ list_del(&patch->list);
+}
+
+static int klp_init_func(struct klp_object *obj, struct klp_func *func)
+{
+ if (!func->old_name || !func->new_func)
+ return -EINVAL;
+
+ INIT_LIST_HEAD(&func->stack_node);
+ func->patched = false;
+ func->transition = false;
+
+ /* 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,%lu", func->old_name,
+ func->old_sympos ? func->old_sympos : 1);
+}
+
+/* Arches may override this to finish any remaining arch-specific tasks */
+void __weak arch_klp_init_object_loaded(struct klp_patch *patch,
+ struct klp_object *obj)
+{
+}
+
+/* parts of the initialization that is done only when the object is loaded */
+static int klp_init_object_loaded(struct klp_patch *patch,
+ struct klp_object *obj)
+{
+ struct klp_func *func;
+ int ret;
+
+ module_disable_ro(patch->mod);
+ ret = klp_write_object_relocations(patch->mod, obj);
+ if (ret) {
+ module_enable_ro(patch->mod, true);
+ return ret;
+ }
+
+ arch_klp_init_object_loaded(patch, obj);
+ module_enable_ro(patch->mod, true);
+
+ klp_for_each_func(obj, func) {
+ ret = klp_find_object_symbol(obj->name, func->old_name,
+ func->old_sympos,
+ &func->old_addr);
+ if (ret)
+ return ret;
+
+ ret = kallsyms_lookup_size_offset(func->old_addr,
+ &func->old_size, NULL);
+ if (!ret) {
+ pr_err("kallsyms size lookup failed for '%s'\n",
+ func->old_name);
+ return -ENOENT;
+ }
+
+ ret = kallsyms_lookup_size_offset((unsigned long)func->new_func,
+ &func->new_size, NULL);
+ if (!ret) {
+ pr_err("kallsyms size lookup failed for '%s' replacement\n",
+ func->old_name);
+ return -ENOENT;
+ }
+ }
+
+ return 0;
+}
+
+static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
+{
+ struct klp_func *func;
+ int ret;
+ const char *name;
+
+ if (!obj->funcs)
+ return -EINVAL;
+
+ obj->patched = false;
+ obj->mod = NULL;
+
+ klp_find_object_module(obj);
+
+ name = klp_is_module(obj) ? obj->name : "vmlinux";
+ ret = kobject_init_and_add(&obj->kobj, &klp_ktype_object,
+ &patch->kobj, "%s", name);
+ if (ret)
+ return ret;
+
+ klp_for_each_func(obj, func) {
+ ret = klp_init_func(obj, func);
+ if (ret)
+ goto free;
+ }
+
+ if (klp_is_object_loaded(obj)) {
+ ret = klp_init_object_loaded(patch, obj);
+ if (ret)
+ goto free;
+ }
+
+ return 0;
+
+free:
+ klp_free_funcs_limited(obj, func);
+ kobject_put(&obj->kobj);
+ return ret;
+}
+
static int __klp_disable_patch(struct klp_patch *patch)
{
if (klp_transition_patch)
@@ -536,182 +709,6 @@ static struct kobj_type klp_ktype_patch = {
.default_attrs = klp_patch_attrs,
};
-static void klp_kobj_release_object(struct kobject *kobj)
-{
-}
-
-static struct kobj_type klp_ktype_object = {
- .release = klp_kobj_release_object,
- .sysfs_ops = &kobj_sysfs_ops,
-};
-
-static void klp_kobj_release_func(struct kobject *kobj)
-{
-}
-
-static struct kobj_type klp_ktype_func = {
- .release = klp_kobj_release_func,
- .sysfs_ops = &kobj_sysfs_ops,
-};
-
-/*
- * Free all functions' kobjects in the array up to some limit. When limit is
- * NULL, all kobjects are freed.
- */
-static void klp_free_funcs_limited(struct klp_object *obj,
- struct klp_func *limit)
-{
- struct klp_func *func;
-
- for (func = obj->funcs; func->old_name && func != limit; func++)
- kobject_put(&func->kobj);
-}
-
-/* Clean up when a patched object is unloaded */
-static void klp_free_object_loaded(struct klp_object *obj)
-{
- struct klp_func *func;
-
- obj->mod = NULL;
-
- klp_for_each_func(obj, func)
- func->old_addr = 0;
-}
-
-/*
- * Free all objects' kobjects in the array up to some limit. When limit is
- * NULL, all kobjects are freed.
- */
-static void klp_free_objects_limited(struct klp_patch *patch,
- struct klp_object *limit)
-{
- struct klp_object *obj;
-
- for (obj = patch->objs; obj->funcs && obj != limit; obj++) {
- klp_free_funcs_limited(obj, NULL);
- kobject_put(&obj->kobj);
- }
-}
-
-static void klp_free_patch(struct klp_patch *patch)
-{
- klp_free_objects_limited(patch, NULL);
- if (!list_empty(&patch->list))
- list_del(&patch->list);
-}
-
-static int klp_init_func(struct klp_object *obj, struct klp_func *func)
-{
- if (!func->old_name || !func->new_func)
- return -EINVAL;
-
- INIT_LIST_HEAD(&func->stack_node);
- func->patched = false;
- func->transition = false;
- list_add(&func->func_entry, &obj->func_list);
-
- /* 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,%lu", func->old_name,
- func->old_sympos ? func->old_sympos : 1);
-}
-
-/* Arches may override this to finish any remaining arch-specific tasks */
-void __weak arch_klp_init_object_loaded(struct klp_patch *patch,
- struct klp_object *obj)
-{
-}
-
-/* parts of the initialization that is done only when the object is loaded */
-static int klp_init_object_loaded(struct klp_patch *patch,
- struct klp_object *obj)
-{
- struct klp_func *func;
- int ret;
-
- module_disable_ro(patch->mod);
- ret = klp_write_object_relocations(patch->mod, obj);
- if (ret) {
- module_enable_ro(patch->mod, true);
- return ret;
- }
-
- arch_klp_init_object_loaded(patch, obj);
- module_enable_ro(patch->mod, true);
-
- klp_for_each_func(obj, func) {
- ret = klp_find_object_symbol(obj->name, func->old_name,
- func->old_sympos,
- &func->old_addr);
- if (ret)
- return ret;
-
- ret = kallsyms_lookup_size_offset(func->old_addr,
- &func->old_size, NULL);
- if (!ret) {
- pr_err("kallsyms size lookup failed for '%s'\n",
- func->old_name);
- return -ENOENT;
- }
-
- ret = kallsyms_lookup_size_offset((unsigned long)func->new_func,
- &func->new_size, NULL);
- if (!ret) {
- pr_err("kallsyms size lookup failed for '%s' replacement\n",
- func->old_name);
- return -ENOENT;
- }
- }
-
- return 0;
-}
-
-static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
-{
- struct klp_func *func;
- int ret;
- const char *name;
-
- if (!obj->funcs)
- return -EINVAL;
-
- obj->patched = false;
- obj->mod = NULL;
-
- klp_find_object_module(obj);
-
- name = klp_is_module(obj) ? obj->name : "vmlinux";
- ret = kobject_init_and_add(&obj->kobj, &klp_ktype_object,
- &patch->kobj, "%s", name);
- if (ret)
- return ret;
-
- list_add(&obj->obj_entry, &patch->obj_list);
- INIT_LIST_HEAD(&obj->func_list);
- klp_for_each_func_static(obj, func) {
- ret = klp_init_func(obj, func);
- if (ret)
- goto free;
- }
-
- if (klp_is_object_loaded(obj)) {
- ret = klp_init_object_loaded(patch, obj);
- if (ret)
- goto free;
- }
-
- return 0;
-
-free:
- klp_free_funcs_limited(obj, func);
- kobject_put(&obj->kobj);
- return ret;
-}
-
static int klp_init_patch(struct klp_patch *patch)
{
struct klp_object *obj;
--
2.6.1