Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livep...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Oct 2016 19:02:24 +0000 (12:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Oct 2016 19:02:24 +0000 (12:02 -0700)
Pull livepatching updates from Jiri Kosina:

 - fix for patching modules that contain .altinstructions or
   .parainstructions sections, from Jessica Yu

 - make TAINT_LIVEPATCH a per-module flag (so that it's immediately
   clear which module caused the taint), from Josh Poimboeuf

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livepatching:
  livepatch/module: make TAINT_LIVEPATCH module-specific
  Documentation: livepatch: add section about arch-specific code
  livepatch/x86: apply alternatives and paravirt patches after relocations
  livepatch: use arch_klp_init_object_loaded() to finish arch-specific tasks

Documentation/livepatch/module-elf-format.txt
arch/x86/kernel/Makefile
arch/x86/kernel/livepatch.c [new file with mode: 0644]
include/linux/livepatch.h
kernel/livepatch/core.c
kernel/module.c

index eedbdcf..f21a528 100644 (file)
@@ -25,7 +25,8 @@ Table of Contents
        3.3.2 Required name format
        3.3.3 Example livepatch symbol names
        3.3.4 Example `readelf --symbols` output
-4. Symbol table and Elf section access
+4. Architecture-specific sections
+5. Symbol table and Elf section access
 
 ----------------------------
 0. Background and motivation
@@ -46,7 +47,7 @@ architecture.
 
 Since apply_relocate_add() requires access to a module's section header
 table, symbol table, and relocation section indices, Elf information is
-preserved for livepatch modules (see section 4). Livepatch manages its own
+preserved for livepatch modules (see section 5). Livepatch manages its own
 relocation sections and symbols, which are described in this document. The
 Elf constants used to mark livepatch symbols and relocation sections were
 selected from OS-specific ranges according to the definitions from glibc.
@@ -117,7 +118,7 @@ also possible for a livepatch module to have no livepatch relocation
 sections, as in the case of the sample livepatch module (see
 samples/livepatch).
 
-Since Elf information is preserved for livepatch modules (see Section 4), a
+Since Elf information is preserved for livepatch modules (see Section 5), a
 livepatch relocation section can be applied simply by passing in the
 appropriate section index to apply_relocate_add(), which then uses it to
 access the relocation section and apply the relocations.
@@ -292,8 +293,19 @@ Symbol table '.symtab' contains 127 entries:
 [*] Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
     "OS" means OS-specific.
 
+---------------------------------
+4. Architecture-specific sections
+---------------------------------
+Architectures may override arch_klp_init_object_loaded() to perform
+additional arch-specific tasks when a target module loads, such as applying
+arch-specific sections. On x86 for example, we must apply per-object
+.altinstructions and .parainstructions sections when a target module loads.
+These sections must be prefixed with ".klp.arch.$objname." so that they can
+be easily identified when iterating through a patch module's Elf sections
+(See arch/x86/kernel/livepatch.c for a complete example).
+
 --------------------------------------
-4. Symbol table and Elf section access
+5. Symbol table and Elf section access
 --------------------------------------
 A livepatch module's symbol table is accessible through module->symtab.
 
index 45257cf..4dd5d50 100644 (file)
@@ -83,6 +83,7 @@ obj-$(CONFIG_X86_MPPARSE)     += mpparse.o
 obj-y                          += apic/
 obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
 obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
+obj-$(CONFIG_LIVEPATCH)        += livepatch.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
 obj-$(CONFIG_X86_TSC)          += trace_clock.o
diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c
new file mode 100644 (file)
index 0000000..e9d252d
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * livepatch.c - x86-specific Kernel Live Patching Core
+ *
+ * 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/module.h>
+#include <linux/kallsyms.h>
+#include <linux/livepatch.h>
+#include <asm/text-patching.h>
+
+/* Apply per-object alternatives. Based on x86 module_finalize() */
+void arch_klp_init_object_loaded(struct klp_patch *patch,
+                                struct klp_object *obj)
+{
+       int cnt;
+       struct klp_modinfo *info;
+       Elf_Shdr *s, *alt = NULL, *para = NULL;
+       void *aseg, *pseg;
+       const char *objname;
+       char sec_objname[MODULE_NAME_LEN];
+       char secname[KSYM_NAME_LEN];
+
+       info = patch->mod->klp_info;
+       objname = obj->name ? obj->name : "vmlinux";
+
+       /* See livepatch core code for BUILD_BUG_ON() explanation */
+       BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128);
+
+       for (s = info->sechdrs; s < info->sechdrs + info->hdr.e_shnum; s++) {
+               /* Apply per-object .klp.arch sections */
+               cnt = sscanf(info->secstrings + s->sh_name,
+                            ".klp.arch.%55[^.].%127s",
+                            sec_objname, secname);
+               if (cnt != 2)
+                       continue;
+               if (strcmp(sec_objname, objname))
+                       continue;
+               if (!strcmp(".altinstructions", secname))
+                       alt = s;
+               if (!strcmp(".parainstructions", secname))
+                       para = s;
+       }
+
+       if (alt) {
+               aseg = (void *) alt->sh_addr;
+               apply_alternatives(aseg, aseg + alt->sh_size);
+       }
+
+       if (para) {
+               pseg = (void *) para->sh_addr;
+               apply_paravirt(pseg, pseg + para->sh_size);
+       }
+}
index a93a0b2..9072f04 100644 (file)
@@ -116,6 +116,9 @@ int klp_unregister_patch(struct klp_patch *);
 int klp_enable_patch(struct klp_patch *);
 int klp_disable_patch(struct klp_patch *);
 
+void arch_klp_init_object_loaded(struct klp_patch *patch,
+                                struct klp_object *obj);
+
 /* Called from the module loader during module coming/going states */
 int klp_module_coming(struct module *mod);
 void klp_module_going(struct module *mod);
index 8bbe507..af46438 100644 (file)
@@ -274,7 +274,6 @@ static int klp_write_object_relocations(struct module *pmod,
 
        objname = klp_is_module(obj) ? obj->name : "vmlinux";
 
-       module_disable_ro(pmod);
        /* For each klp relocation section */
        for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) {
                sec = pmod->klp_info->sechdrs + i;
@@ -309,7 +308,6 @@ static int klp_write_object_relocations(struct module *pmod,
                        break;
        }
 
-       module_enable_ro(pmod, true);
        return ret;
 }
 
@@ -547,9 +545,6 @@ static int __klp_enable_patch(struct klp_patch *patch)
            list_prev_entry(patch, list)->state == KLP_DISABLED)
                return -EBUSY;
 
-       pr_notice_once("tainting kernel with TAINT_LIVEPATCH\n");
-       add_taint(TAINT_LIVEPATCH, LOCKDEP_STILL_OK);
-
        pr_notice("enabling patch '%s'\n", patch->mod->name);
 
        klp_for_each_object(patch, obj) {
@@ -763,6 +758,12 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
                                    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)
@@ -770,9 +771,15 @@ static int klp_init_object_loaded(struct klp_patch *patch,
        struct klp_func *func;
        int ret;
 
+       module_disable_ro(patch->mod);
        ret = klp_write_object_relocations(patch->mod, obj);
-       if (ret)
+       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,
index 529efae..f57dd63 100644 (file)
@@ -1149,6 +1149,8 @@ static size_t module_flags_taint(struct module *mod, char *buf)
                buf[l++] = 'C';
        if (mod->taints & (1 << TAINT_UNSIGNED_MODULE))
                buf[l++] = 'E';
+       if (mod->taints & (1 << TAINT_LIVEPATCH))
+               buf[l++] = 'K';
        /*
         * TAINT_FORCED_RMMOD: could be added.
         * TAINT_CPU_OUT_OF_SPEC, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't
@@ -2792,14 +2794,17 @@ static int copy_chunked_from_user(void *dst, const void __user *usrc, unsigned l
 }
 
 #ifdef CONFIG_LIVEPATCH
-static int find_livepatch_modinfo(struct module *mod, struct load_info *info)
+static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
 {
-       mod->klp = get_modinfo(info, "livepatch") ? true : false;
+       if (get_modinfo(info, "livepatch")) {
+               mod->klp = true;
+               add_taint_module(mod, TAINT_LIVEPATCH, LOCKDEP_STILL_OK);
+       }
 
        return 0;
 }
 #else /* !CONFIG_LIVEPATCH */
-static int find_livepatch_modinfo(struct module *mod, struct load_info *info)
+static int check_modinfo_livepatch(struct module *mod, struct load_info *info)
 {
        if (get_modinfo(info, "livepatch")) {
                pr_err("%s: module is marked as livepatch module, but livepatch support is disabled",
@@ -2969,7 +2974,7 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
                        "is unknown, you have been warned.\n", mod->name);
        }
 
-       err = find_livepatch_modinfo(mod, info);
+       err = check_modinfo_livepatch(mod, info);
        if (err)
                return err;