From patchwork Wed Aug 14 11:24:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wieczorkiewicz, Pawel" X-Patchwork-Id: 11093781 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4251F1399 for ; Wed, 14 Aug 2019 11:26:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F26E287BF for ; Wed, 14 Aug 2019 11:26:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2386E287CD; Wed, 14 Aug 2019 11:26:49 +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=-4.2 required=2.0 tests=BAYES_00,DKIM_ADSP_ALL, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id BC007287BF for ; Wed, 14 Aug 2019 11:26:48 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hxrP1-0003eW-U9; Wed, 14 Aug 2019 11:25:15 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hxrP1-0003eR-5M for xen-devel@lists.xen.org; Wed, 14 Aug 2019 11:25:15 +0000 X-Inumbo-ID: 2f546924-be86-11e9-bade-d33f781166c8 Received: from smtp-fw-9102.amazon.com (unknown [207.171.184.29]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 2f546924-be86-11e9-bade-d33f781166c8; Wed, 14 Aug 2019 11:25:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1565781914; x=1597317914; h=from:to:cc:subject:date:message-id:mime-version; bh=JyCMbREvJAaeqdyjHkAPuLBuIbMlB9aGBUX6eBY6mIw=; b=elgcPj2Y+siu5w8ss4VYQTjS7Ii9f1jUY3yLow01JvYy8dRAvnRG1us6 jJCgGF2lhFk+1fIOOPE7Lxw2A/0gJ/RbwYKHnQRcNqjLon1QB4vpJeTH5 lAEBVnA+xwcl7qFkCXDSfHoFZRBqqntqx5TiWEFjAWiBYv4hP2uR9A9jF Y=; X-IronPort-AV: E=Sophos;i="5.64,385,1559520000"; d="scan'208";a="693767235" Received: from sea3-co-svc-lb6-vlan3.sea.amazon.com (HELO email-inbound-relay-2a-d0be17ee.us-west-2.amazon.com) ([10.47.22.38]) by smtp-border-fw-out-9102.sea19.amazon.com with ESMTP; 14 Aug 2019 11:25:08 +0000 Received: from EX13MTAUEA001.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan3.pdx.amazon.com [10.170.41.166]) by email-inbound-relay-2a-d0be17ee.us-west-2.amazon.com (Postfix) with ESMTPS id A4C88A20CC; Wed, 14 Aug 2019 11:25:07 +0000 (UTC) Received: from EX13D03EUA003.ant.amazon.com (10.43.165.89) by EX13MTAUEA001.ant.amazon.com (10.43.61.243) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 14 Aug 2019 11:25:07 +0000 Received: from EX13MTAUEE001.ant.amazon.com (10.43.62.200) by EX13D03EUA003.ant.amazon.com (10.43.165.89) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 14 Aug 2019 11:25:06 +0000 Received: from dev-dsk-wipawel-1a-0c4e6d58.eu-west-1.amazon.com (10.4.134.33) by mail-relay.amazon.com (10.43.62.226) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Wed, 14 Aug 2019 11:25:04 +0000 From: Pawel Wieczorkiewicz To: Date: Wed, 14 Aug 2019 11:24:57 +0000 Message-ID: <20190814112457.8468-1-wipawel@amazon.de> X-Mailer: git-send-email 2.16.5 MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH livepatch-expect 1/2] create-diff-object: Add support for expectations X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: mpohlack@amazon.de, ross.lagerwall@citrix.com, wipawel@amazon.de, konrad.wilk@oracle.com Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Extend livepatch_patch_func to support a new field: expect. This new field describes the expected data, its length and whether expectation is enabled. The expectation's data is of opaque padding size. Bump the payload version for hotpatches built with expectations. The expectations are supported starting from version 3 of the payload. By default the expectation field is zero-out and the expectation is disabled unless explicitly specified in the patch. Signed-off-by: Pawel Wieczorkiewicz --- common.h | 11 ++++++++++- create-diff-object.c | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/common.h b/common.h index d8cde35..7c6fb73 100644 --- a/common.h +++ b/common.h @@ -115,6 +115,14 @@ struct kpatch_elf { }; #define PATCH_INSN_SIZE 5 +#define MAX_REPLACEMENT_SIZE 31 +struct livepatch_expectation { + uint8_t enabled : 1; + uint8_t len : 5; + uint8_t pad : 2; + uint8_t data[MAX_REPLACEMENT_SIZE]; +}; +typedef struct livepatch_expectation livepatch_expectation_t; struct livepatch_patch_func { char *name; @@ -123,9 +131,10 @@ struct livepatch_patch_func { uint32_t new_size; uint32_t old_size; uint8_t version; - unsigned char pad[31]; + unsigned char pad[MAX_REPLACEMENT_SIZE]; uint8_t applied; uint8_t _pad[7]; + livepatch_expectation_t expect; }; struct special_section { diff --git a/create-diff-object.c b/create-diff-object.c index 534516b..c7431cc 100644 --- a/create-diff-object.c +++ b/create-diff-object.c @@ -2009,10 +2009,11 @@ static void livepatch_create_patches_sections(struct kpatch_elf *kelf, funcs[index].old_size = result.size; funcs[index].new_addr = 0; funcs[index].new_size = sym->sym.st_size; - funcs[index].version = 2; + funcs[index].version = 3; memset(funcs[index].pad, 0, sizeof funcs[index].pad); funcs[index].applied = 0; memset(funcs[index]._pad, 0, sizeof funcs[index]._pad); + memset(&funcs[index].expect, 0, sizeof funcs[index].expect); /* * Add a relocation that will populate From patchwork Wed Aug 14 11:25:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wieczorkiewicz, Pawel" X-Patchwork-Id: 11093783 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E794D1399 for ; Wed, 14 Aug 2019 11:27:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D016A287BF for ; Wed, 14 Aug 2019 11:27:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BF579287A1; Wed, 14 Aug 2019 11:27:31 +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=-4.2 required=2.0 tests=BAYES_00,DKIM_ADSP_ALL, DKIM_INVALID,DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 290D4287A1 for ; Wed, 14 Aug 2019 11:27:30 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hxrPd-0003h4-7c; Wed, 14 Aug 2019 11:25:53 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hxrPb-0003gt-GV for xen-devel@lists.xen.org; Wed, 14 Aug 2019 11:25:51 +0000 X-Inumbo-ID: 43ff0aaa-be86-11e9-8d23-3fbc657c5699 Received: from smtp-fw-6001.amazon.com (unknown [52.95.48.154]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 43ff0aaa-be86-11e9-8d23-3fbc657c5699; Wed, 14 Aug 2019 11:25:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1565781948; x=1597317948; h=from:to:cc:subject:date:message-id:mime-version; bh=LVcL4/E73wtHCjbLs6oBzpAveUfgn18XtLmsmNDnwCY=; b=vPLizIl6Eji28GmPDf4XmGHX/8nq6QpuCMjKn/LQ5Dytem+Ca3gH7Ilu 6xCrdbNSprfC9fO32vcKJZyIHjhOBRUKoz6Z5Mp6gl9jsIe773pRxxf6+ mwzJK7xlMhhXiVwvOJm+h6aOR1p4HehieFhDFrj/n9eKlYIc/w1Fru7L/ 8=; X-IronPort-AV: E=Sophos;i="5.64,385,1559520000"; d="scan'208";a="409574262" Received: from iad6-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-2a-90c42d1d.us-west-2.amazon.com) ([10.124.125.6]) by smtp-border-fw-out-6001.iad6.amazon.com with ESMTP; 14 Aug 2019 11:25:47 +0000 Received: from EX13MTAUEA001.ant.amazon.com (pdx4-ws-svc-p6-lb7-vlan3.pdx.amazon.com [10.170.41.166]) by email-inbound-relay-2a-90c42d1d.us-west-2.amazon.com (Postfix) with ESMTPS id EAF55A257C; Wed, 14 Aug 2019 11:25:46 +0000 (UTC) Received: from EX13D05EUC002.ant.amazon.com (10.43.164.231) by EX13MTAUEA001.ant.amazon.com (10.43.61.82) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 14 Aug 2019 11:25:46 +0000 Received: from EX13MTAUEE001.ant.amazon.com (10.43.62.200) by EX13D05EUC002.ant.amazon.com (10.43.164.231) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 14 Aug 2019 11:25:45 +0000 Received: from dev-dsk-wipawel-1a-0c4e6d58.eu-west-1.amazon.com (10.4.134.33) by mail-relay.amazon.com (10.43.62.226) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Wed, 14 Aug 2019 11:25:44 +0000 From: Pawel Wieczorkiewicz To: Date: Wed, 14 Aug 2019 11:25:41 +0000 Message-ID: <20190814112541.8651-1-wipawel@amazon.de> X-Mailer: git-send-email 2.16.5 MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH livepatch-expect 2/2] livepatch: Add support for inline asm hotpatching expectations X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: mpohlack@amazon.de, ross.lagerwall@citrix.com, wipawel@amazon.de, konrad.wilk@oracle.com Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP This is the initial implementation of the expectations enhancement to improve inline asm hotpatching. Expectations are designed as optional feature, since the main use of them is planned for inline asm hotpatching. The flag enabled allows to control the expectation state. Each expectation has data and len fields that describe the data that is expected to be found at a given patching (old_addr) location. The len must not exceed the data array size. The data array size follows the size of the opaque array, since the opaque array holds the original data and therefore must match what is specified in the expectation (if enabled). The payload structure is modified as each expectation structure is part of the livepatch_func structure and hence extends the payload. The payload version is bumped to 3 with this change to highlight the ABI modification and enforce proper support. Each expectation is checked prior to the apply action (i.e. as late as possible to check against the most current state of the code). For the replace action a new payload's expectations are checked AFTER all applied payloads are successfully reverted, but BEFORE new payload is applied. That breaks the replace action's atomicity and in case of an expectation check failure would leave a system with all payloads reverted. That is obviously insecure. Use it with caution and act upon replace errors! Signed-off-by: Pawel Wieczorkiewicz Reviewed-by: Andra-Irina Paraschiv Reviewed-by: Martin Pohlack Reviewed-by: Norbert Manthey --- xen/common/livepatch.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ xen/include/public/sysctl.h | 17 +++++++++-- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index 090a48977b..8aef2fd12e 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -560,6 +560,58 @@ static int check_patching_sections(const struct livepatch_elf *elf) return 0; } +static inline int livepatch_verify_expectation_fn(const struct livepatch_func *func) +{ + const livepatch_expectation_t *exp = &func->expect; + + /* Ignore disabled expectations. */ + if ( !exp->enabled ) + return 0; + + /* There is nothing to expect */ + if ( !func->old_addr ) + return -EFAULT; + + if ( exp->len > sizeof(exp->data)) + return -EOVERFLOW; + + /* Incorrect expectation */ + if ( func->old_size < exp->len ) + return -ERANGE; + + if ( memcmp(func->old_addr, exp->data, exp->len) ) + { + printk(XENLOG_ERR LIVEPATCH "%s: expectation failed: expected:%*phN, actual:%*phN\n", + func->name, exp->len, exp->data, exp->len, func->old_addr); + return -EINVAL; + } + + return 0; +} + +static inline int livepatch_check_expectations(const struct payload *payload) +{ + int i, rc; + + printk(XENLOG_INFO LIVEPATCH "%s: Verifying enabled expectations for all functions\n", + payload->name); + + for ( i = 0; i < payload->nfuncs; i++ ) + { + const struct livepatch_func *func = &(payload->funcs[i]); + + rc = livepatch_verify_expectation_fn(func); + if ( rc ) + { + printk(XENLOG_ERR LIVEPATCH "%s: expectations of %s failed (rc=%d), aborting!\n", + payload->name, func->name ?: "unknown", rc); + return rc; + } + } + + return 0; +} + /* * Lookup specified section and when exists assign its address to a specified hook. * Perform section pointer and size validation: single hook sections must contain a @@ -1347,6 +1399,20 @@ static void livepatch_do_action(void) if ( rc == 0 ) { + /* + * Make sure all expectation requirements are met. + * Beware all the payloads are reverted at this point. + * If expectations are not met the system is left in a + * completely UNPATCHED state! + */ + rc = livepatch_check_expectations(data); + if ( rc ) + { + printk(XENLOG_ERR LIVEPATCH "%s: SYSTEM MIGHT BE INSECURE: " + "Replace action has been aborted after reverting ALL payloads!\n", data->name); + break; + } + if ( is_hook_enabled(data->hooks.apply.action) ) { printk(XENLOG_INFO LIVEPATCH "%s: Calling apply action hook function\n", data->name); @@ -1800,6 +1866,11 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action) break; } + /* Make sure all expectation requirements are met. */ + rc = livepatch_check_expectations(data); + if ( rc ) + break; + if ( is_hook_enabled(data->hooks.apply.pre) ) { printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-apply hook function\n", data->name); diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 98cdcc64bb..335e193712 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -818,7 +818,7 @@ struct xen_sysctl_cpu_featureset { * If zero exit with success. */ -#define LIVEPATCH_PAYLOAD_VERSION 2 +#define LIVEPATCH_PAYLOAD_VERSION 3 /* * .livepatch.funcs structure layout defined in the `Payload format` * section in the Live Patch design document. @@ -826,6 +826,18 @@ struct xen_sysctl_cpu_featureset { * We guard this with __XEN__ as toolstacks SHOULD not use it. */ #ifdef __XEN__ +#define LIVEPATCH_OPAQUE_SIZE 31 + +struct livepatch_expectation { + uint8_t enabled : 1; + uint8_t len : 5; /* Length of data up to LIVEPATCH_OPAQUE_SIZE + (5 bits is enough for now) */ + uint8_t data[LIVEPATCH_OPAQUE_SIZE]; /* Same size as opaque[] buffer of + struct livepatch_func. This is the + max number of bytes to be patched */ +}; +typedef struct livepatch_expectation livepatch_expectation_t; + typedef enum livepatch_func_state { LIVEPATCH_FUNC_NOT_APPLIED = 0, LIVEPATCH_FUNC_APPLIED = 1 @@ -838,11 +850,12 @@ struct livepatch_func { uint32_t new_size; uint32_t old_size; uint8_t version; /* MUST be LIVEPATCH_PAYLOAD_VERSION. */ - uint8_t opaque[31]; + uint8_t opaque[LIVEPATCH_OPAQUE_SIZE]; #if defined CONFIG_X86 uint8_t applied; uint8_t _pad[7]; #endif + livepatch_expectation_t expect; }; typedef struct livepatch_func livepatch_func_t; #endif