From patchwork Wed Aug 21 08:19:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Wieczorkiewicz, Pawel" X-Patchwork-Id: 11106033 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8E86A1395 for ; Wed, 21 Aug 2019 08:22:32 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5FD872339F for ; Wed, 21 Aug 2019 08:22:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=amazon.de header.i=@amazon.de header.b="ozd+A4Er" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5FD872339F Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=amazon.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i0LrQ-0008Nl-De; Wed, 21 Aug 2019 08:20:52 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1i0LrO-0008MO-OW for xen-devel@lists.xenproject.org; Wed, 21 Aug 2019 08:20:50 +0000 X-Inumbo-ID: 9576329e-c3ec-11e9-b95f-bc764e2007e4 Received: from smtp-fw-9102.amazon.com (unknown [207.171.184.29]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 9576329e-c3ec-11e9-b95f-bc764e2007e4; Wed, 21 Aug 2019 08:20:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.de; i=@amazon.de; q=dns/txt; s=amazon201209; t=1566375650; x=1597911650; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version; bh=lAB+FU7pGkIP7OdOzrwgcApWz6XZkWbBT7jjneGSsUo=; b=ozd+A4ErW3OcJw8DhlIqZ9z8+FMhEY5mkZnVumu9vxen13jTtyy2HXc8 rUwubMs0v9ukEoruRn8bE11oXWqKI3XmbB43mSn2kyc19cLCm1zxq8RnP g94Fb1Zf1eo6mE9K7u6o1/NHEQf6YDp8AYvW4TQjebr0Rq8AQudo1WmTm Q=; X-IronPort-AV: E=Sophos;i="5.64,412,1559520000"; d="scan'208";a="695968363" Received: from sea3-co-svc-lb6-vlan3.sea.amazon.com (HELO email-inbound-relay-2a-90c42d1d.us-west-2.amazon.com) ([10.47.22.38]) by smtp-border-fw-out-9102.sea19.amazon.com with ESMTP; 21 Aug 2019 08:20:49 +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 D4FF9A1DE8; Wed, 21 Aug 2019 08:20:48 +0000 (UTC) Received: from EX13D03EUC004.ant.amazon.com (10.43.164.33) by EX13MTAUEA001.ant.amazon.com (10.43.61.243) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 21 Aug 2019 08:20:15 +0000 Received: from EX13MTAUWB001.ant.amazon.com (10.43.161.207) by EX13D03EUC004.ant.amazon.com (10.43.164.33) with Microsoft SMTP Server (TLS) id 15.0.1367.3; Wed, 21 Aug 2019 08:20:13 +0000 Received: from dev-dsk-wipawel-1a-0c4e6d58.eu-west-1.amazon.com (10.4.134.33) by mail-relay.amazon.com (10.43.161.249) with Microsoft SMTP Server id 15.0.1367.3 via Frontend Transport; Wed, 21 Aug 2019 08:20:11 +0000 From: Pawel Wieczorkiewicz To: , Date: Wed, 21 Aug 2019 08:19:23 +0000 Message-ID: <20190821081931.90887-7-wipawel@amazon.de> X-Mailer: git-send-email 2.16.5 In-Reply-To: <20190821081931.90887-1-wipawel@amazon.de> References: <20190821081931.90887-1-wipawel@amazon.de> MIME-Version: 1.0 Precedence: Bulk Subject: [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks 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: Pawel Wieczorkiewicz , wipawel@amazon.com, Ross Lagerwall , mpohlack@amazon.com, Konrad Rzeszutek Wilk Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" By default, in the quiescing zone, a hotpatch payload is applied with apply_payload() and reverted with revert_payload() functions. Both of the functions receive the payload struct pointer as a parameter. The functions are also a place where standard 'load' and 'unload' module hooks are executed. To increase hotpatching system's agility and provide more flexiable long-term hotpatch solution, allow to overwrite the default apply and revert action functions with hook-like supplied alternatives. The alternative functions are optional and the default functions are used by default. Since the alternative functions have direct access to the hotpatch payload structure, they can better control context of the 'load' and 'unload' hooks execution as well as exact instructions replacement workflows. They can be also easily extended to support extra features in the future. To simplify the alternative function generation move code responsible for payload and hotpatch region registration outside of the function. That way it is guaranteed that the registration step occurs even for newly supplied functions. Signed-off-by: Pawel Wieczorkiewicz Reviewed-by: Petre Eftime Reviewed-by: Martin Pohlack Reviewed-by: Norbert Manthey Reviewed-by: Andra-Irina Paraschiv Reviewed-by: Bjoern Doebel --- xen/common/livepatch.c | 66 +++++++++++++++++++++++++++++++------ xen/include/xen/livepatch_payload.h | 10 ++++++ 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index 464c07ad28..38fab8b240 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -587,8 +587,11 @@ static int prepare_payload(struct payload *payload, LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ".livepatch.hooks.unload"); LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.pre, ".livepatch.hooks.preapply"); + LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.action, ".livepatch.hooks.apply"); LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.post, ".livepatch.hooks.postapply"); + LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.pre, ".livepatch.hooks.prerevert"); + LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.action, ".livepatch.hooks.revert"); LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.post, ".livepatch.hooks.postrevert"); sec = livepatch_elf_sec_by_name(elf, ELF_BUILD_ID_NOTE); @@ -1114,6 +1117,11 @@ static int apply_payload(struct payload *data) arch_livepatch_revive(); + return 0; +} + +static inline void apply_payload_tail(struct payload *data) +{ /* * We need RCU variant (which has barriers) in case we crash here. * The applied_list is iterated by the trap code. @@ -1121,7 +1129,7 @@ static int apply_payload(struct payload *data) list_add_tail_rcu(&data->applied_list, &applied_list); register_virtual_region(&data->region); - return 0; + data->state = LIVEPATCH_STATE_APPLIED; } static int revert_payload(struct payload *data) @@ -1154,6 +1162,11 @@ static int revert_payload(struct payload *data) ASSERT(!local_irq_is_enabled()); arch_livepatch_revive(); + return 0; +} + +static inline void revert_payload_tail(struct payload *data) +{ /* * We need RCU variant (which has barriers) in case we crash here. @@ -1163,7 +1176,7 @@ static int revert_payload(struct payload *data) unregister_virtual_region(&data->region); data->reverted = true; - return 0; + data->state = LIVEPATCH_STATE_CHECKED; } /* @@ -1183,15 +1196,31 @@ static void livepatch_do_action(void) switch ( livepatch_work.cmd ) { case LIVEPATCH_ACTION_APPLY: - rc = apply_payload(data); + if ( is_hook_enabled(data->hooks.apply.action) ) + { + printk(XENLOG_INFO LIVEPATCH "%s: Calling apply action hook function\n", data->name); + + rc = (*data->hooks.apply.action)(data); + } + else + rc = apply_payload(data); + if ( rc == 0 ) - data->state = LIVEPATCH_STATE_APPLIED; + apply_payload_tail(data); break; case LIVEPATCH_ACTION_REVERT: - rc = revert_payload(data); + if ( is_hook_enabled(data->hooks.revert.action) ) + { + printk(XENLOG_INFO LIVEPATCH "%s: Calling revert action hook function\n", data->name); + + rc = (*data->hooks.revert.action)(data); + } + else + rc = revert_payload(data); + if ( rc == 0 ) - data->state = LIVEPATCH_STATE_CHECKED; + revert_payload_tail(data); break; case LIVEPATCH_ACTION_REPLACE: @@ -1202,9 +1231,18 @@ static void livepatch_do_action(void) */ list_for_each_entry_safe_reverse ( other, tmp, &applied_list, applied_list ) { - other->rc = revert_payload(other); + if ( is_hook_enabled(other->hooks.revert.action) ) + { + printk(XENLOG_INFO LIVEPATCH "%s: Calling revert action hook function\n", other->name); + + other->rc = (*other->hooks.revert.action)(other); + } + else + other->rc = revert_payload(other); + + if ( other->rc == 0 ) - other->state = LIVEPATCH_STATE_CHECKED; + revert_payload_tail(other); else { rc = -EINVAL; @@ -1214,9 +1252,17 @@ static void livepatch_do_action(void) if ( rc == 0 ) { - rc = apply_payload(data); + if ( is_hook_enabled(data->hooks.apply.action) ) + { + printk(XENLOG_INFO LIVEPATCH "%s: Calling apply action hook function\n", data->name); + + rc = (*data->hooks.apply.action)(data); + } + else + rc = apply_payload(data); + if ( rc == 0 ) - data->state = LIVEPATCH_STATE_APPLIED; + apply_payload_tail(data); } break; diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h index cd20944cc4..ff16af0dd6 100644 --- a/xen/include/xen/livepatch_payload.h +++ b/xen/include/xen/livepatch_payload.h @@ -22,11 +22,13 @@ typedef void livepatch_loadcall_t(void); typedef void livepatch_unloadcall_t(void); typedef int livepatch_precall_t(livepatch_payload_t *arg); +typedef int livepatch_actioncall_t(livepatch_payload_t *arg); typedef void livepatch_postcall_t(livepatch_payload_t *arg); struct livepatch_hooks { struct { livepatch_precall_t *const *pre; + livepatch_actioncall_t *const *action; livepatch_postcall_t *const *post; } apply, revert; }; @@ -91,6 +93,10 @@ struct payload { livepatch_precall_t *__attribute__((weak, used)) \ const livepatch_preapply_data_##_fn __section(".livepatch.hooks.preapply") = _fn; +#define LIVEPATCH_APPLY_HOOK(_fn) \ + livepatch_actioncall_t *__attribute__((weak, used)) \ + const livepatch_apply_data_##_fn __section(".livepatch.hooks.apply") = _fn; + #define LIVEPATCH_POSTAPPLY_HOOK(_fn) \ livepatch_postcall_t *__attribute__((weak, used)) \ const livepatch_postapply_data_##_fn __section(".livepatch.hooks.postapply") = _fn; @@ -99,6 +105,10 @@ struct payload { livepatch_precall_t *__attribute__((weak, used)) \ const livepatch_prerevert_data_##_fn __section(".livepatch.hooks.prerevert") = _fn; +#define LIVEPATCH_REVERT_HOOK(_fn) \ + livepatch_actioncall_t *__attribute__((weak, used)) \ + const livepatch_revert_data_##_fn __section(".livepatch.hooks.revert") = _fn; + #define LIVEPATCH_POSTREVERT_HOOK(_fn) \ livepatch_postcall_t *__attribute__((weak, used)) \ const livepatch_postrevert_data_##_fn __section(".livepatch.hooks.postrevert") = _fn;