From patchwork Wed Sep 20 22:31:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Rzeszutek Wilk X-Patchwork-Id: 9962715 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id EBE34601D5 for ; Wed, 20 Sep 2017 22:34:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DE01929258 for ; Wed, 20 Sep 2017 22:34:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D2F3329271; Wed, 20 Sep 2017 22:34:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-3.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RCVD_IN_SORBS_SPAM,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3CD8629258 for ; Wed, 20 Sep 2017 22:34:50 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dunXV-0007Jm-9Z; Wed, 20 Sep 2017 22:32:17 +0000 Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dunXU-0007Hd-Aw for xen-devel@lists.xenproject.org; Wed, 20 Sep 2017 22:32:16 +0000 Received: from [85.158.139.211] by server-2.bemta-5.messagelabs.com id B1/A5-02092-F6CE2C95; Wed, 20 Sep 2017 22:32:15 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrGIsWRWlGSWpSXmKPExsVyMfTGEd28N4c iDVYdNrL4vmUykwOjx+EPV1gCGKNYM/OS8isSWDMW/f7OWLDFuuLe/sNsDYxX9LoYuTiEBKYz Svy90MUI4rAIfGCReH19CzuIIyEwjVXi77EJzF2MnEBOlkTH2vVQdprEy8cTWboYOYDsSoktf 0VAwkICShJbJj9mhJh6iEni3/ctjCAJYQE9icnfboPZbAL6Ek/XXmOG6HWT+HSNC6ReRKCdUW L2lV+sIDXMAoYSrW+PskH0pkl83PiDBcRmEVCVWHNkOVicV8BG4sPzBawQ98hLTOydBjafEyi +/1MnM8RB1hJPtp5mm8AovICRYRWjRnFqUVlqka6huV5SUWZ6RkluYmaOrqGBqV5uanFxYnpq TmJSsV5yfu4mRmCIMgDBDsaLpz0PMUpyMCmJ8orGH4oU4kvKT6nMSCzOiC8qzUktPsQow8GhJ MFbmwqUEyxKTU+tSMvMAUYLTFqCg0dJhJcZJM1bXJCYW5yZDpE6xWjPMe/7xT9MHBfuXAKSB/ bcApIdN+/+YRJiycvPS5US5xUEaRMAacsozYMbCovuS4yyUsK8jEBnCvEUpBblZpagyr9iFOd gVBLmFQGZwpOZVwK3+xXQWUxAZ2VvOAByVkkiQkqqgfHCekaRHX3sr8Rcmi9Ma+Lu4xLNW2Hw ZMuUQyGOX2KWSwZKKDxbvtR99vtXtc9OGx8uv1cldrz8fctjyYmeCxPnMllId1u6xqseEHZ9k W6oP+F5gcXmu16G6VM0d8YWN6vXfEtNmjbHKtxx05zTXY8f64Yw9Fs+nrFbJfMi49potgCGYz /flyixFGckGmoxFxUnAgACVij86QIAAA== X-Env-Sender: ketuzsezr@gmail.com X-Msg-Ref: server-3.tower-206.messagelabs.com!1505946733!108934686!1 X-Originating-IP: [209.85.216.196] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 3156 invoked from network); 20 Sep 2017 22:32:14 -0000 Received: from mail-qt0-f196.google.com (HELO mail-qt0-f196.google.com) (209.85.216.196) by server-3.tower-206.messagelabs.com with AES128-GCM-SHA256 encrypted SMTP; 20 Sep 2017 22:32:14 -0000 Received: by mail-qt0-f196.google.com with SMTP id q8so2677413qtb.1 for ; Wed, 20 Sep 2017 15:32:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=cG6UwdKYH27YagW/Ee4cBbCDxAIooScGZpJMioWVPt4=; b=GA3iBADDqrbMjSRixXXz/rOrCN28bJbSBNMFFQlY2FO4/MRlfPmNCE/zgVZc4y8m47 kO9AJ4MSllnzpnK6xnWyC7S66xPD+mSbxUCgq2Xv7+jXOuG7S+GtYZzA+CJuoTqrK5C2 t5r445rf97VsxaRQL6MhPXEIrU84b0r/qWZPBblC6R8O28DaaafUKjFIMdL0+Mv2WA2N 9UfaOg5/zAQLVmyb/OUfXSJ4RyZlTEpL4KurmxsuQG5nbJFm7LqTK+ILkiJOb9yI5PVh QN/UpDwioUgr15ARn9NuIT0StkTXy06tRIzFj2cDxwPH/18uNFPHi12PFCiiW+2UUP6K p/aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=cG6UwdKYH27YagW/Ee4cBbCDxAIooScGZpJMioWVPt4=; b=QQsWXRv9NTESQfNSjpSZ7qti0B+JzrUOG8ZRE4SP/txOKlZn8U50Ok8boapw9sRrzS wZew8AGWwreGiDsCpk3Z8Qx7HniUPQ/+cijbJixBhm5aVjyfMcha7qLQJBO4rk7sHA2U MIdgI1ZMwl4pZgZoHg7nqvYDb0Efkw3oxp+JG9FomKYZH7mBpbN8JcDTXVEOf0Gwy/G7 jZfjskd1x8Tka7OlwOGcc+b3TmFWzlkSji/dzbGFAfRcOgvhNSHtMJ/0Orev85croLcC 6+8eTNMoEHsp73gPTaVxd6KBnmIWTgNHQT4zlw1p92dZq3I9knmv4CfkjOK+cgMLMys/ sFGQ== X-Gm-Message-State: AHPjjUi/Ge6L3Raeyr4kxPvPc9fqhfVnA1M05FLCdH34vJzatL547in9 r1hAvXuax/+U6Zkyl75AdBlvvg== X-Google-Smtp-Source: AOwi7QCAWMYddYpNGROPc2wwKgGnZDLQV3610IxS5vxber57pqfud0nH5Yto0WPeZGPCIvwAlhcnfg== X-Received: by 10.200.39.189 with SMTP id w58mr364481qtw.246.1505946733229; Wed, 20 Sep 2017 15:32:13 -0700 (PDT) Received: from localhost.localdomain (209-6-200-48.s4398.c3-0.smr-ubr2.sbo-smr.ma.cable.rcncustomer.com. [209.6.200.48]) by smtp.gmail.com with ESMTPSA id z192sm2012656qka.91.2017.09.20.15.32.12 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 20 Sep 2017 15:32:12 -0700 (PDT) From: Konrad Rzeszutek Wilk X-Google-Original-From: Konrad Rzeszutek Wilk To: xen-devel@lists.xenproject.org, ross.lagerwall@citrix.com, konrad.wilk@oracle.com, julien.grall@arm.com, sstabellini@kernel.org Date: Wed, 20 Sep 2017 18:31:47 -0400 Message-Id: <20170920223148.13137-11-konrad.wilk@oracle.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20170920223148.13137-1-konrad.wilk@oracle.com> References: <20170920223148.13137-1-konrad.wilk@oracle.com> Cc: andrew.cooper3@citrix.com, jbeulich@suse.com Subject: [Xen-devel] [PATCH v4 10/11] livepatch/arm[32, 64]: Modify .livepatch.funcs section to be RW when patching X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This was found when porting livepatch-build-tools to ARM64/32 When livepatch-build-tools are built (and test-case thanks to: livepatch/tests: Make sure all .livepatch.funcs sections are read-only) the .livepatch.funcs are in read-only section. However the hypervisor uses the 'opaque' for its own purpose, that is stashing the original code. But the .livepatch_funcs section is in the RO vmap area so on ARM[32,64] we get a fault (as the secure_payload changes the VA to RO). On x86 the same protection is in place. In 'arch_livepatch_quiesce' we disable WP to allow changes to read-only pages (and in arch_livepatch_revive we re-enable the WP protection). On ARM[32,64] we do not have the luxury of a global register that can be changed after boot. In lieu of that we modify the VA of where the .livepatch.funcs is to RW. After we are done with patching we change it back to RO. To do this we need to stash during livepatching the va of the page in which the .livepatch.func resides, and the number of pages said section uses (or 1 at min). Equipped with that we can patch livepatch functions which have .livepatch_funcs in rodata section. An alternative is to add the 'W' flag during loading of the .livepatch_funcs which would result the section being in writeable region from the gecko. Suggested-by: Julien Grall Signed-off-by: Konrad Rzeszutek Wilk --- Cc: Ross Lagerwall v4: First posting --- xen/arch/arm/livepatch.c | 45 ++++++++++++++++++++++++++++++++++++++--- xen/arch/x86/livepatch.c | 2 +- xen/common/livepatch.c | 9 +++++++-- xen/include/asm-arm/livepatch.h | 13 ++++++++++++ xen/include/xen/livepatch.h | 2 +- 5 files changed, 64 insertions(+), 7 deletions(-) diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c index 76723f1f1a..f23df8597d 100644 --- a/xen/arch/arm/livepatch.c +++ b/xen/arch/arm/livepatch.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,13 +18,15 @@ #define virt_to_mfn(va) _mfn(__virt_to_mfn(va)) void *vmap_of_xen_text; +struct livepatch_va livepatch_stash; -int arch_livepatch_quiesce(void) +int arch_livepatch_quiesce(struct livepatch_func *func, size_t nfuncs) { mfn_t text_mfn; unsigned int text_order; + int rc = 0; - if ( vmap_of_xen_text ) + if ( vmap_of_xen_text || livepatch_stash.va ) return -EINVAL; text_mfn = virt_to_mfn(_start); @@ -43,7 +46,29 @@ int arch_livepatch_quiesce(void) return -ENOMEM; } - return 0; + if ( nfuncs ) + { + unsigned long va = (unsigned long)func; + unsigned int offs = va & (PAGE_SIZE - 1); + unsigned int pages = PFN_UP(offs + nfuncs * sizeof(*func)); + + va &= PAGE_MASK; + + rc = modify_xen_mappings(va, va + (pages * PAGE_SIZE), PTE_NX); + if ( rc ) + { + printk(XENLOG_ERR LIVEPATCH "Failed to modify 0x%lx to RW\n", va); + vunmap(vmap_of_xen_text); + vmap_of_xen_text = NULL; + } + else + { + livepatch_stash.va = va; + livepatch_stash.pages = pages; + } + } + + return rc; } void arch_livepatch_revive(void) @@ -58,6 +83,20 @@ void arch_livepatch_revive(void) vunmap(vmap_of_xen_text); vmap_of_xen_text = NULL; + + if ( livepatch_stash.va ) + { + unsigned long va = livepatch_stash.va; + + int rc = modify_xen_mappings(va, va + (livepatch_stash.pages * PAGE_SIZE), + PTE_NX | PTE_RO); + if ( rc ) + printk(XENLOG_ERR LIVEPATCH "Failed to modify %lx to RO!\n", va); + + livepatch_stash.va = 0; + livepatch_stash.pages = 0; + + } } int arch_livepatch_verify_func(const struct livepatch_func *func) diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c index 48d20fdacd..f5865370d5 100644 --- a/xen/arch/x86/livepatch.c +++ b/xen/arch/x86/livepatch.c @@ -14,7 +14,7 @@ #include #include -int arch_livepatch_quiesce(void) +int arch_livepatch_quiesce(struct livepatch_func *func, size_t nfuncs) { /* Disable WP to allow changes to read-only pages. */ write_cr0(read_cr0() & ~X86_CR0_WP); diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index f736c3a7ea..af8998ec8d 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -56,6 +56,7 @@ struct payload { int32_t rc; /* 0 or -XEN_EXX. */ bool reverted; /* Whether it was reverted. */ bool safe_to_reapply; /* Can apply safely after revert. */ + bool funcs_ro; /* Are livepatch.funcs in .rodata section. */ struct list_head list; /* Linked to 'payload_list'. */ const void *text_addr; /* Virtual address of .text. */ size_t text_size; /* .. and its size. */ @@ -538,6 +539,10 @@ static int prepare_payload(struct payload *payload, payload->funcs = sec->load_addr; payload->nfuncs = sec->sec->sh_size / sizeof(*payload->funcs); + if ( sec->load_addr >= payload->ro_addr && + sec->load_addr < (payload->ro_addr + payload->ro_size) ) + payload->funcs_ro = true; + for ( i = 0; i < payload->nfuncs; i++ ) { int rc; @@ -1070,7 +1075,7 @@ static int apply_payload(struct payload *data) printk(XENLOG_INFO LIVEPATCH "%s: Applying %u functions\n", data->name, data->nfuncs); - rc = arch_livepatch_quiesce(); + rc = arch_livepatch_quiesce(data->funcs, data->funcs_ro ? data->nfuncs : 0); if ( rc ) { printk(XENLOG_ERR LIVEPATCH "%s: unable to quiesce!\n", data->name); @@ -1111,7 +1116,7 @@ static int revert_payload(struct payload *data) printk(XENLOG_INFO LIVEPATCH "%s: Reverting\n", data->name); - rc = arch_livepatch_quiesce(); + rc = arch_livepatch_quiesce(data->funcs, data->funcs_ro ? data->nfuncs : 0); if ( rc ) { printk(XENLOG_ERR LIVEPATCH "%s: unable to quiesce!\n", data->name); diff --git a/xen/include/asm-arm/livepatch.h b/xen/include/asm-arm/livepatch.h index 6bca79deb9..cd13ca786d 100644 --- a/xen/include/asm-arm/livepatch.h +++ b/xen/include/asm-arm/livepatch.h @@ -17,6 +17,19 @@ */ extern void *vmap_of_xen_text; +/* + * The va of the livepatch .livepatch.funcs. Only used if said + * region is in RO VA and we need to modify it to RW during + * livepatching. + */ +struct livepatch_va +{ + unsigned long va; + unsigned int pages; +}; + +extern struct livepatch_va livepatch_stash; + /* These ranges are only for unconditional branches. */ #ifdef CONFIG_ARM_32 /* ARM32: A4.3 IN ARM DDI 0406C.c - we are using only ARM instructions in Xen.*/ diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h index e9bab87f28..4aceaab637 100644 --- a/xen/include/xen/livepatch.h +++ b/xen/include/xen/livepatch.h @@ -104,7 +104,7 @@ static inline int livepatch_verify_distance(const struct livepatch_func *func) * These functions are called around the critical region patching live code, * for an architecture to take make appropratie global state adjustments. */ -int arch_livepatch_quiesce(void); +int arch_livepatch_quiesce(struct livepatch_func *, size_t nfunc); void arch_livepatch_revive(void); void arch_livepatch_apply(struct livepatch_func *func);