From patchwork Thu Jan 14 21:47:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Rzeszutek Wilk X-Patchwork-Id: 8035831 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 445989F1C0 for ; Thu, 14 Jan 2016 21:50:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EB6002035D for ; Thu, 14 Jan 2016 21:50:41 +0000 (UTC) Received: from lists.xen.org (lists.xenproject.org [50.57.142.19]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 06306202EB for ; Thu, 14 Jan 2016 21:50:38 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aJpjw-0006VU-5o; Thu, 14 Jan 2016 21:47:32 +0000 Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aJpjt-0006Ry-K1 for xen-devel@lists.xenproject.org; Thu, 14 Jan 2016 21:47:29 +0000 Received: from [85.158.143.35] by server-3.bemta-4.messagelabs.com id E1/8E-31122-17718965; Thu, 14 Jan 2016 21:47:29 +0000 X-Env-Sender: konrad@char.us.oracle.com X-Msg-Ref: server-9.tower-21.messagelabs.com!1452808046!10162500!1 X-Originating-IP: [156.151.31.81] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTU2LjE1MS4zMS44MSA9PiAyODgzMzk=\n X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 16853 invoked from network); 14 Jan 2016 21:47:28 -0000 Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by server-9.tower-21.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 14 Jan 2016 21:47:28 -0000 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u0ELlLFf021455 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 14 Jan 2016 21:47:21 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u0ELlKTs010645 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 14 Jan 2016 21:47:21 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u0ELlK9f003175; Thu, 14 Jan 2016 21:47:20 GMT Received: from char.us.oracle.com (/10.137.176.158) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 14 Jan 2016 13:47:19 -0800 Received: by char.us.oracle.com (Postfix, from userid 1000) id AF43C6A4DB2; Thu, 14 Jan 2016 16:47:17 -0500 (EST) From: Konrad Rzeszutek Wilk To: xen-devel@lists.xenproject.org, ross.lagerwall@citrix.com, mpohlack@amazon.com, andrew.cooper3@citrix.com, stefano.stabellini@citrix.com, jbeulich@suse.com, ian.jackson@eu.citrix.com, ian.campbell@citrix.com, wei.liu2@citrix.com, sasha.levin@oracle.com Date: Thu, 14 Jan 2016 16:47:09 -0500 Message-Id: <1452808031-706-12-git-send-email-konrad.wilk@oracle.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1452808031-706-1-git-send-email-konrad.wilk@oracle.com> References: <1452808031-706-1-git-send-email-konrad.wilk@oracle.com> X-Source-IP: userv0022.oracle.com [156.151.31.74] Cc: Konrad Rzeszutek Wilk Subject: [Xen-devel] [PATCH v2 11/13] xsplice: Add support for bug frames. (v2) X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Ross Lagerwall Add support for handling bug frames contained with xsplice modules. If a trap occurs search either the kernel bug table or an applied payload's bug table depending on the instruction pointer. Signed-off-by: Ross Lagerwall Signed-off-by: Konrad Rzeszutek Wilk --- v2:- s/module/payload/ - add build time check in case amount of bug frames expands. - add define for the number of bug-frames. --- xen/arch/x86/traps.c | 30 ++++++++----- xen/common/symbols.c | 7 +++ xen/common/xsplice.c | 109 +++++++++++++++++++++++++++++++++++++++++----- xen/include/asm-arm/bug.h | 2 + xen/include/asm-x86/bug.h | 2 + xen/include/xen/kernel.h | 1 + xen/include/xen/xsplice.h | 15 +++++++ 7 files changed, 145 insertions(+), 21 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index e105b95..6e80607 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -1080,20 +1081,29 @@ void do_invalid_op(struct cpu_user_regs *regs) return; } - if ( !is_active_kernel_text(regs->eip) || + if ( !is_active_text(regs->eip) || __copy_from_user(bug_insn, eip, sizeof(bug_insn)) || memcmp(bug_insn, "\xf\xb", sizeof(bug_insn)) ) goto die; - for ( bug = __start_bug_frames, id = 0; stop_frames[id]; ++bug ) + if ( likely(is_active_kernel_text(regs->eip)) ) { - while ( unlikely(bug == stop_frames[id]) ) - ++id; - if ( bug_loc(bug) == eip ) - break; + for ( bug = __start_bug_frames, id = 0; stop_frames[id]; ++bug ) + { + while ( unlikely(bug == stop_frames[id]) ) + ++id; + if ( bug_loc(bug) == eip ) + break; + } + if ( !stop_frames[id] ) + goto die; + } + else + { + bug = xsplice_find_bug(eip, &id); + if ( !bug ) + goto die; } - if ( !stop_frames[id] ) - goto die; eip += sizeof(bug_insn); if ( id == BUGFRAME_run_fn ) @@ -1107,7 +1117,7 @@ void do_invalid_op(struct cpu_user_regs *regs) /* WARN, BUG or ASSERT: decode the filename pointer and line number. */ filename = bug_ptr(bug); - if ( !is_kernel(filename) ) + if ( !is_kernel(filename) && !is_module(filename) ) goto die; fixup = strlen(filename); if ( fixup > 50 ) @@ -1134,7 +1144,7 @@ void do_invalid_op(struct cpu_user_regs *regs) case BUGFRAME_assert: /* ASSERT: decode the predicate string pointer. */ predicate = bug_msg(bug); - if ( !is_kernel(predicate) ) + if ( !is_kernel(predicate) && !is_module(predicate) ) predicate = ""; printk("Assertion '%s' failed at %s%s:%d\n", diff --git a/xen/common/symbols.c b/xen/common/symbols.c index a59c59d..bf5623f 100644 --- a/xen/common/symbols.c +++ b/xen/common/symbols.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,12 @@ bool_t is_active_kernel_text(unsigned long addr) (system_state < SYS_STATE_active && is_kernel_inittext(addr))); } +bool_t is_active_text(unsigned long addr) +{ + return is_active_kernel_text(addr) || + is_active_module_text(addr); +} + const char *symbols_lookup(unsigned long addr, unsigned long *symbolsize, unsigned long *offset, diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c index 5abeb28..02cb4a8 100644 --- a/xen/common/xsplice.c +++ b/xen/common/xsplice.c @@ -43,7 +43,10 @@ struct payload { struct list_head applied_list; /* Linked to 'applied_list'. */ struct xsplice_patch_func *funcs; /* The array of functions to patch. */ unsigned int nfuncs; /* Nr of functions to patch. */ - + size_t core_size; /* Only .text size. */ + size_t core_text_size; /* Everything else - .data,.rodata, etc. */ + struct bug_frame *start_bug_frames[BUGFRAME_NR]; /* .bug.frame patching. */ + struct bug_frame *stop_bug_frames[BUGFRAME_NR]; char name[XEN_XSPLICE_NAME_SIZE + 1];/* Name of it. */ }; @@ -544,26 +547,27 @@ static void free_payload_data(struct payload *payload) payload->payload_pages = 0; } -static void calc_section(struct xsplice_elf_sec *sec, size_t *core_size) +static void calc_section(struct xsplice_elf_sec *sec, size_t *size) { - size_t align_size = ROUNDUP(*core_size, sec->sec->sh_addralign); + size_t align_size = ROUNDUP(*size, sec->sec->sh_addralign); sec->sec->sh_entsize = align_size; - *core_size = sec->sec->sh_size + align_size; + *size = sec->sec->sh_size + align_size; } static int move_payload(struct payload *payload, struct xsplice_elf *elf) { uint8_t *buf; unsigned int i; - size_t core_size = 0; + size_t size = 0; /* Compute text regions */ for ( i = 0; i < elf->hdr->e_shnum; i++ ) { if ( (elf->sec[i].sec->sh_flags & (SHF_ALLOC|SHF_EXECINSTR)) == (SHF_ALLOC|SHF_EXECINSTR) ) - calc_section(&elf->sec[i], &core_size); + calc_section(&elf->sec[i], &size); } + payload->core_text_size = size; /* Compute rw data */ for ( i = 0; i < elf->hdr->e_shnum; i++ ) @@ -571,7 +575,7 @@ static int move_payload(struct payload *payload, struct xsplice_elf *elf) if ( (elf->sec[i].sec->sh_flags & SHF_ALLOC) && !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) && (elf->sec[i].sec->sh_flags & SHF_WRITE) ) - calc_section(&elf->sec[i], &core_size); + calc_section(&elf->sec[i], &size); } /* Compute ro data */ @@ -580,16 +584,17 @@ static int move_payload(struct payload *payload, struct xsplice_elf *elf) if ( (elf->sec[i].sec->sh_flags & SHF_ALLOC) && !(elf->sec[i].sec->sh_flags & SHF_EXECINSTR) && !(elf->sec[i].sec->sh_flags & SHF_WRITE) ) - calc_section(&elf->sec[i], &core_size); + calc_section(&elf->sec[i], &size); } + payload->core_size = size; - buf = alloc_payload(core_size); + buf = alloc_payload(size); if ( !buf ) { printk(XENLOG_ERR "%s: Could not allocate memory for module\n", elf->name); return -ENOMEM; } - memset(buf, 0, core_size); + memset(buf, 0, size); for ( i = 0; i < elf->hdr->e_shnum; i++ ) { @@ -604,7 +609,7 @@ static int move_payload(struct payload *payload, struct xsplice_elf *elf) } payload->payload_address = buf; - payload->payload_pages = PFN_UP(core_size); + payload->payload_pages = PFN_UP(size); return 0; } @@ -647,6 +652,22 @@ static int find_special_sections(struct payload *payload, if ( f->pad[j] ) return -EINVAL; } + for ( i = 0; i < BUGFRAME_NR; i++ ) + { + char str[14]; + + snprintf(str, sizeof str, ".bug_frames.%d", i); + sec = xsplice_elf_sec_by_name(elf, str); + if ( !sec ) + continue; + + if ( ( !sec->sec->sh_size ) || + ( sec->sec->sh_size % sizeof (struct bug_frame) ) ) + return -EINVAL; + + payload->start_bug_frames[i] = (struct bug_frame *)sec->load_addr; + payload->stop_bug_frames[i] = (struct bug_frame *)(sec->load_addr + sec->sec->sh_size); + } return 0; } @@ -942,6 +963,72 @@ void do_xsplice(void) } } + +/* + * Functions for handling special sections. + */ +struct bug_frame *xsplice_find_bug(const char *eip, int *id) +{ + struct payload *data; + struct bug_frame *bug; + int i; + + /* No locking since this list is only ever changed during apply or revert + * context. */ + list_for_each_entry ( data, &applied_list, applied_list ) + { + for (i = 0; i < 4; i++) { + if (!data->start_bug_frames[i]) + continue; + if ( !((void *)eip >= data->payload_address && + (void *)eip < (data->payload_address + data->core_text_size))) + continue; + + for ( bug = data->start_bug_frames[i]; bug != data->stop_bug_frames[i]; ++bug ) { + if ( bug_loc(bug) == eip ) + { + *id = i; + return bug; + } + } + } + } + + return NULL; +} + +bool_t is_module(const void *ptr) +{ + struct payload *data; + + /* No locking since this list is only ever changed during apply or revert + * context. */ + list_for_each_entry ( data, &applied_list, applied_list ) + { + if ( ptr >= data->payload_address && + ptr < (data->payload_address + data->core_size)) + return 1; + } + + return 0; +} + +bool_t is_active_module_text(unsigned long addr) +{ + struct payload *data; + + /* No locking since this list is only ever changed during apply or revert + * context. */ + list_for_each_entry ( data, &applied_list, applied_list ) + { + if ( (void *)addr >= data->payload_address && + (void *)addr < (data->payload_address + data->core_text_size)) + return 1; + } + + return 0; +} + static int __init xsplice_init(void) { register_keyhandler('x', xsplice_printall, "print xsplicing info", 1); diff --git a/xen/include/asm-arm/bug.h b/xen/include/asm-arm/bug.h index ab9e811..4df6b2a 100644 --- a/xen/include/asm-arm/bug.h +++ b/xen/include/asm-arm/bug.h @@ -31,6 +31,7 @@ struct bug_frame { #define BUGFRAME_warn 0 #define BUGFRAME_bug 1 #define BUGFRAME_assert 2 +#define BUGFRAME_NR 3 /* Many versions of GCC doesn't support the asm %c parameter which would * be preferable to this unpleasantness. We use mergeable string @@ -39,6 +40,7 @@ struct bug_frame { */ #define BUG_FRAME(type, line, file, has_msg, msg) do { \ BUILD_BUG_ON((line) >> 16); \ + BUILD_BUG_ON(type >= BUGFRAME_NR); \ asm ("1:"BUG_INSTR"\n" \ ".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \ "2:\t.asciz " __stringify(file) "\n" \ diff --git a/xen/include/asm-x86/bug.h b/xen/include/asm-x86/bug.h index e868e85..5443191 100644 --- a/xen/include/asm-x86/bug.h +++ b/xen/include/asm-x86/bug.h @@ -9,6 +9,7 @@ #define BUGFRAME_warn 1 #define BUGFRAME_bug 2 #define BUGFRAME_assert 3 +#define BUGFRAME_NR 4 #ifndef __ASSEMBLY__ @@ -51,6 +52,7 @@ struct bug_frame { #define BUG_FRAME(type, line, ptr, second_frame, msg) do { \ BUILD_BUG_ON((line) >> (BUG_LINE_LO_WIDTH + BUG_LINE_HI_WIDTH)); \ + BUILD_BUG_ON((type) >= (BUGFRAME_NR)); \ asm volatile ( _ASM_BUGFRAME_TEXT(second_frame) \ :: _ASM_BUGFRAME_INFO(type, line, ptr, msg) ); \ } while (0) diff --git a/xen/include/xen/kernel.h b/xen/include/xen/kernel.h index 548b64d..df57754 100644 --- a/xen/include/xen/kernel.h +++ b/xen/include/xen/kernel.h @@ -99,6 +99,7 @@ extern enum system_state { } system_state; bool_t is_active_kernel_text(unsigned long addr); +bool_t is_active_text(unsigned long addr); #endif /* _LINUX_KERNEL_H */ diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h index 61a9ec6..41b738a 100644 --- a/xen/include/xen/xsplice.h +++ b/xen/include/xen/xsplice.h @@ -26,8 +26,23 @@ int xsplice_control(struct xen_sysctl_xsplice_op *); #ifdef CONFIG_XSPLICE void do_xsplice(void); +struct bug_frame *xsplice_find_bug(const char *eip, int *id); +bool_t is_module(const void *addr); +bool_t is_active_module_text(unsigned long addr); #else static inline void do_xsplice(void) { }; +static inline struct bug_frame *xsplice_find_bug(const char *eip, int *id) +{ + return NULL; +} +static inline bool_t is_module(const void *addr) +{ + return 0; +} +static inline bool_t is_active_module_text(unsigned long addr) +{ + return 0; +} #endif /* Arch hooks */