From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752766AbcGFCfs (ORCPT ); Tue, 5 Jul 2016 22:35:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36355 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751111AbcGFCfo (ORCPT ); Tue, 5 Jul 2016 22:35:44 -0400 From: Jessica Yu To: Josh Poimboeuf , Miroslav Benes , Petr Mladek , Jiri Kosina , Chris J Arges , Eugene Shatokhin Cc: live-patching@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, Jessica Yu Subject: [PATCH 2/2] livepatch/x86: apply alternatives and paravirt patches after relocations Date: Tue, 5 Jul 2016 22:35:00 -0400 Message-Id: <1467772500-26092-3-git-send-email-jeyu@redhat.com> In-Reply-To: <1467772500-26092-1-git-send-email-jeyu@redhat.com> References: <1467772500-26092-1-git-send-email-jeyu@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 06 Jul 2016 02:35:43 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement arch_klp_init_object_loaded() for x86, which applies alternatives/paravirt patches. This fixes the order in which relocations and alternatives/paravirt patches are applied. Previously, if a patch module had alternatives or paravirt patches, these were applied first by the module loader before livepatch can apply per-object relocations. The (buggy) sequence of events was: (1) Load patch module (2) Apply alternatives and paravirt patches to patch module * Note that these are applied to the new functions in the patch module (3) Apply per-object relocations to patch module when target module loads. * This clobbers what was written in step 2 This lead to crashes and corruption in general, since livepatch would overwrite or step on previously applied alternative/paravirt patches. The correct sequence of events should be: (1) Load patch module (2) Apply per-object relocations to patch module (3) Apply per-object alternatives and paravirt patches to patch module This is fixed by delaying paravirt/alternatives patching until after relocations are applied. Any .altinstructions or .parainstructions sections in a patch module are prefixed with ".klp.arch.${objname}" and applied in arch_klp_init_object_loaded(). Signed-off-by: Jessica Yu --- arch/x86/kernel/Makefile | 1 + arch/x86/kernel/livepatch.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 arch/x86/kernel/livepatch.c diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 0503f5b..4f656fe 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -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 index 0000000..f0845b2 --- /dev/null +++ b/arch/x86/kernel/livepatch.c @@ -0,0 +1,66 @@ +/* + * 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 . + */ + +#include +#include +#include +#include + +/* 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"; + + for (s = info->sechdrs; s < info->sechdrs + info->hdr.e_shnum; s++) { + /* + * Search for .klp.arch sections that apply to this object. + * See BUILD_BUG_ON() in livepatch core code for field width + * explanations. + */ + 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); + } +} -- 2.4.3