]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livep...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Apr 2015 17:15:34 +0000 (10:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Apr 2015 17:15:34 +0000 (10:15 -0700)
Pull livepatching updates from Jiri Kosina:
 "These are mostly smaller things that got accumulated during the
  development cycle.  The unified solution is still being worked on and
  is not mature enough for 4.1 yet.

   - s390 livepatching support, from Jiri Slaby (has Ack from s390
     maintainers)

   - error handling simplification, from Josh Poimboeuf

   - two minor code cleanups from Josh Poimboeuf and Miroslav Benes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching:
  livepatch: add support on s390
  livepatch: remove unnecessary call to klp_find_object_module()
  livepatch: simplify disable error path
  livepatch: remove extern specifier from header files

arch/s390/Kconfig
arch/s390/include/asm/livepatch.h [new file with mode: 0644]
arch/x86/include/asm/livepatch.h
include/linux/livepatch.h
kernel/livepatch/core.c

index 373cd5badf1cf8eea7ff7c65610b0a4ee2bfd5b1..b2d7ec1669b48f2da33b912582b232322e6a6213 100644 (file)
@@ -133,6 +133,7 @@ config S390
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_KVM if 64BIT
+       select HAVE_LIVEPATCH
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_MEMBLOCK_PHYS_MAP
@@ -159,6 +160,8 @@ source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
 
+source "kernel/livepatch/Kconfig"
+
 menu "Processor type and features"
 
 config HAVE_MARCH_Z900_FEATURES
diff --git a/arch/s390/include/asm/livepatch.h b/arch/s390/include/asm/livepatch.h
new file mode 100644 (file)
index 0000000..7aa7991
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * livepatch.h - s390-specific Kernel Live Patching Core
+ *
+ *  Copyright (c) 2013-2015 SUSE
+ *   Authors: Jiri Kosina
+ *           Vojtech Pavlik
+ *           Jiri Slaby
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef ASM_LIVEPATCH_H
+#define ASM_LIVEPATCH_H
+
+#include <linux/module.h>
+
+#ifdef CONFIG_LIVEPATCH
+static inline int klp_check_compiler_support(void)
+{
+       return 0;
+}
+
+static inline int klp_write_module_reloc(struct module *mod, unsigned long
+               type, unsigned long loc, unsigned long value)
+{
+       /* not supported yet */
+       return -ENOSYS;
+}
+
+static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
+{
+       regs->psw.addr = ip;
+}
+#else
+#error Live patching support is disabled; check CONFIG_LIVEPATCH
+#endif
+
+#endif
index a455a53d789a12c908097ee6b266086c56479e47..2d29197bd2fbfb7da88b1b3f9c9c932a78e177a5 100644 (file)
@@ -32,8 +32,8 @@ static inline int klp_check_compiler_support(void)
 #endif
        return 0;
 }
-extern int klp_write_module_reloc(struct module *mod, unsigned long type,
-                                 unsigned long loc, unsigned long value);
+int klp_write_module_reloc(struct module *mod, unsigned long type,
+                          unsigned long loc, unsigned long value);
 
 static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
index 95023fd8b00dd8343896524b31a31a7f1e9451a4..ee6dbb39a809811ca6aa563ea125fc9bb0af4756 100644 (file)
@@ -123,10 +123,10 @@ struct klp_patch {
        enum klp_state state;
 };
 
-extern int klp_register_patch(struct klp_patch *);
-extern int klp_unregister_patch(struct klp_patch *);
-extern int klp_enable_patch(struct klp_patch *);
-extern int klp_disable_patch(struct klp_patch *);
+int klp_register_patch(struct klp_patch *);
+int klp_unregister_patch(struct klp_patch *);
+int klp_enable_patch(struct klp_patch *);
+int klp_disable_patch(struct klp_patch *);
 
 #endif /* CONFIG_LIVEPATCH */
 
index 3f9f1d6b4c2e5726217556a40454c46dbe368b89..284e2691e38073d52b00d46010e654e6ff7de9bf 100644 (file)
@@ -335,32 +335,20 @@ unlock:
        rcu_read_unlock();
 }
 
-static int klp_disable_func(struct klp_func *func)
+static void klp_disable_func(struct klp_func *func)
 {
        struct klp_ops *ops;
-       int ret;
-
-       if (WARN_ON(func->state != KLP_ENABLED))
-               return -EINVAL;
 
-       if (WARN_ON(!func->old_addr))
-               return -EINVAL;
+       WARN_ON(func->state != KLP_ENABLED);
+       WARN_ON(!func->old_addr);
 
        ops = klp_find_ops(func->old_addr);
        if (WARN_ON(!ops))
-               return -EINVAL;
+               return;
 
        if (list_is_singular(&ops->func_stack)) {
-               ret = unregister_ftrace_function(&ops->fops);
-               if (ret) {
-                       pr_err("failed to unregister ftrace handler for function '%s' (%d)\n",
-                              func->old_name, ret);
-                       return ret;
-               }
-
-               ret = ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0);
-               if (ret)
-                       pr_warn("function unregister succeeded but failed to clear the filter\n");
+               WARN_ON(unregister_ftrace_function(&ops->fops));
+               WARN_ON(ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0));
 
                list_del_rcu(&func->stack_node);
                list_del(&ops->node);
@@ -370,8 +358,6 @@ static int klp_disable_func(struct klp_func *func)
        }
 
        func->state = KLP_DISABLED;
-
-       return 0;
 }
 
 static int klp_enable_func(struct klp_func *func)
@@ -432,23 +418,15 @@ err:
        return ret;
 }
 
-static int klp_disable_object(struct klp_object *obj)
+static void klp_disable_object(struct klp_object *obj)
 {
        struct klp_func *func;
-       int ret;
 
-       for (func = obj->funcs; func->old_name; func++) {
-               if (func->state != KLP_ENABLED)
-                       continue;
-
-               ret = klp_disable_func(func);
-               if (ret)
-                       return ret;
-       }
+       for (func = obj->funcs; func->old_name; func++)
+               if (func->state == KLP_ENABLED)
+                       klp_disable_func(func);
 
        obj->state = KLP_DISABLED;
-
-       return 0;
 }
 
 static int klp_enable_object(struct klp_object *obj)
@@ -464,22 +442,19 @@ static int klp_enable_object(struct klp_object *obj)
 
        for (func = obj->funcs; func->old_name; func++) {
                ret = klp_enable_func(func);
-               if (ret)
-                       goto unregister;
+               if (ret) {
+                       klp_disable_object(obj);
+                       return ret;
+               }
        }
        obj->state = KLP_ENABLED;
 
        return 0;
-
-unregister:
-       WARN_ON(klp_disable_object(obj));
-       return ret;
 }
 
 static int __klp_disable_patch(struct klp_patch *patch)
 {
        struct klp_object *obj;
-       int ret;
 
        /* enforce stacking: only the last enabled patch can be disabled */
        if (!list_is_last(&patch->list, &klp_patches) &&
@@ -489,12 +464,8 @@ static int __klp_disable_patch(struct klp_patch *patch)
        pr_notice("disabling patch '%s'\n", patch->mod->name);
 
        for (obj = patch->objs; obj->funcs; obj++) {
-               if (obj->state != KLP_ENABLED)
-                       continue;
-
-               ret = klp_disable_object(obj);
-               if (ret)
-                       return ret;
+               if (obj->state == KLP_ENABLED)
+                       klp_disable_object(obj);
        }
 
        patch->state = KLP_DISABLED;
@@ -553,8 +524,6 @@ static int __klp_enable_patch(struct klp_patch *patch)
        pr_notice("enabling patch '%s'\n", patch->mod->name);
 
        for (obj = patch->objs; obj->funcs; obj++) {
-               klp_find_object_module(obj);
-
                if (!klp_is_object_loaded(obj))
                        continue;
 
@@ -945,7 +914,6 @@ static void klp_module_notify_going(struct klp_patch *patch,
 {
        struct module *pmod = patch->mod;
        struct module *mod = obj->mod;
-       int ret;
 
        if (patch->state == KLP_DISABLED)
                goto disabled;
@@ -953,10 +921,7 @@ static void klp_module_notify_going(struct klp_patch *patch,
        pr_notice("reverting patch '%s' on unloading module '%s'\n",
                  pmod->name, mod->name);
 
-       ret = klp_disable_object(obj);
-       if (ret)
-               pr_warn("failed to revert patch '%s' on module '%s' (%d)\n",
-                       pmod->name, mod->name, ret);
+       klp_disable_object(obj);
 
 disabled:
        klp_free_object_loaded(obj);