From nobody Thu May 16 08:08:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=reject dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1700733179; cv=none; d=zohomail.com; s=zohoarc; b=n7qycUs97clYVp67spl+YzoSNdmGKnYtWHZajp4TollH9eE73alTcH4wM3B+ERqqYnJeOW71Jv1T7yIDE55jdmw4Y8OkgCo0Ln3T38KQrbohfsB8PoAV6LlxqFz2y1CVGTr7s/kbcziZaBAsrpU+94AV4iS+fXsIYf3LiKuCCJA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1700733179; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=sS4R3HKC+GvMZmIS4Qhf9RmF8Jn/8ENgZIRuzqHPj4k=; b=TOkfbholFxcq8mwfBRh0/MkqOYaZzM7yeQGG24x8GbuiLlVTAiGhAiCA9i5XAjvfLuK6pO3H2gMMMm4IE7YgwfVqK9nfv6NY4LADkKhJTpV7SOiceWZ6GlJ8aebMSD5/giIgXPP9nFCHzRXgsiVW3TJ+xlezXePnZ/dxR+YhRgs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1700733179726192.88272461123836; Thu, 23 Nov 2023 01:52:59 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.639489.996920 (Exim 4.92) (envelope-from ) id 1r66Nt-0004ZW-5H; Thu, 23 Nov 2023 09:52:33 +0000 Received: by outflank-mailman (output) from mailman id 639489.996920; Thu, 23 Nov 2023 09:52:33 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r66Nt-0004ZP-1K; Thu, 23 Nov 2023 09:52:33 +0000 Received: by outflank-mailman (input) for mailman id 639489; Thu, 23 Nov 2023 09:52:31 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r66Nr-0004ZI-Ir for xen-devel@lists.xenproject.org; Thu, 23 Nov 2023 09:52:31 +0000 Received: from mail-lf1-x12a.google.com (mail-lf1-x12a.google.com [2a00:1450:4864:20::12a]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 044571af-89e6-11ee-98e2-6d05b1d4d9a1; Thu, 23 Nov 2023 10:52:30 +0100 (CET) Received: by mail-lf1-x12a.google.com with SMTP id 2adb3069b0e04-50970c2115eso838464e87.1 for ; Thu, 23 Nov 2023 01:52:30 -0800 (PST) Received: from localhost ([213.195.113.99]) by smtp.gmail.com with ESMTPSA id g20-20020a05600c4c9400b004064741f855sm1368653wmp.47.2023.11.23.01.52.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Nov 2023 01:52:28 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 044571af-89e6-11ee-98e2-6d05b1d4d9a1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=citrix.com; s=google; t=1700733149; x=1701337949; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=sS4R3HKC+GvMZmIS4Qhf9RmF8Jn/8ENgZIRuzqHPj4k=; b=IWn1qrb155cP7pGMj2opru+mS6kMAEvRONd/QAVySGXr1iGiaYvuG7XjVSFW4h5Doc EEDDFH6NsU/JEAIQ8wIblQ3QdrihH+k5HU8vcjyb9w8+MFoO2YHwewv+HSFaJboz7+0h q1mhCdQW3zp29cLQkKCRmd8IXrj4EvGRgkDFY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700733149; x=1701337949; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=sS4R3HKC+GvMZmIS4Qhf9RmF8Jn/8ENgZIRuzqHPj4k=; b=vu9ry1A1PiKlhCwcFZzYbm7RY/q1Op94CRt0jzvbFbfRdU3nc42oYniUEyCbKKkucD XAAb/Ws/iRPC8yDfd0q90/M1pIoigDTWN9/dDa/wRdEv9ejIYuMIVfVdBPiIsTFH4OGa 1DanaIKz6NfAZYWMiAJXl83YwR+hk7tWJg1A1gixWz7G0CZTBeP9V8jXufWB/LenqvY3 0xaftRdcTwv0ByM7lfdL/sP4cu4SXV94DSTHxdxLbxard1Ar8IIsSDMaAnkaMO0yRr39 1P9YLrtPoKxP2TISskWJV+g/lBRy3/8Vv7Pgr5ZU05IckgPjZiH6Lp9BQJl+vXweqXjY JsWQ== X-Gm-Message-State: AOJu0YwF5YqF1u9smIkCoCq2qyHm8+eZ9Y5xtHSCWALUx6dFhdS2qSKV Ti9XZQPI12Ih74zLHdfc5vxsE0TMqQ5cJmSahrE= X-Google-Smtp-Source: AGHT+IFJKJOiett4eoZgsjohTECKlKyFH/HKESIntahYXdU2bCMfTuKNhGGbsfY2yf1nDOuC+awY6w== X-Received: by 2002:a19:4f07:0:b0:502:a4f4:ced9 with SMTP id d7-20020a194f07000000b00502a4f4ced9mr2661261lfb.62.1700733148980; Thu, 23 Nov 2023 01:52:28 -0800 (PST) From: Roger Pau Monne To: xen-devel@lists.xenproject.org Cc: Roger Pau Monne , Konrad Rzeszutek Wilk , Ross Lagerwall , Stefano Stabellini , Julien Grall , Bertrand Marquis , Michal Orzel , Volodymyr Babchuk , Andrew Cooper , George Dunlap , Jan Beulich , Wei Liu Subject: [PATCH v2] livepatch: do not use .livepatch.funcs section to store internal state Date: Thu, 23 Nov 2023 10:52:24 +0100 Message-ID: <20231123095224.13720-1-roger.pau@citrix.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @citrix.com) X-ZM-MESSAGEID: 1700733180364100001 Currently the livepatch logic inside of Xen will use fields of struct livepatch_func in order to cache internal state of patched functions. Note this is a field that is part of the payload, and is loaded as an ELF section (.livepatch.funcs), taking into account the SHF_* flags in the section header. The flags for the .livepatch.funcs section, as set by livepatch-build-tools, are SHF_ALLOC, which leads to its contents (the array of livepatch_func structures) being placed in read-only memory: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [...] [ 4] .livepatch.funcs PROGBITS 0000000000000000 00000080 0000000000000068 0000000000000000 A 0 0 8 This previously went unnoticed, as all writes to the fields of livepatch_fu= nc happen in the critical region that had WP disabled in CR0. After 8676092a0= f16 however WP is no longer toggled in CR0 for patch application, and only the hypervisor .text mappings are made write-accessible. That leads to the following page fault when attempting to apply a livepatch: Reviewed-by: Ross Lagerwall ----[ Xen-4.19-unstable x86_64 debug=3Dy Tainted: C ]---- CPU: 4 RIP: e008:[] common/livepatch.c#apply_payload+0x45/0x1= e1 [...] Xen call trace: [] R common/livepatch.c#apply_payload+0x45/0x1e1 [] F check_for_livepatch_work+0x385/0xaa5 [] F arch/x86/domain.c#idle_loop+0x92/0xee Pagetable walk from ffff82d040625079: L4[0x105] =3D 000000008c6c9063 ffffffffffffffff L3[0x141] =3D 000000008c6c6063 ffffffffffffffff L2[0x003] =3D 000000086a1e7063 ffffffffffffffff L1[0x025] =3D 800000086ca5d121 ffffffffffffffff **************************************** Panic on CPU 4: FATAL PAGE FAULT [error_code=3D0003] Faulting linear address: ffff82d040625079 **************************************** Fix this by moving the internal Xen function patching state out of livepatch_func into an area not allocated as part of the ELF payload. While there also constify the array of livepatch_func structures in order to prev= ent further surprises. Note there's still one field (old_addr) that gets set during livepatch load= . I consider this fine since the field is read-only after load, and at the point the field gets set the underlying mapping hasn't been made read-only yet. Fixes: 8676092a0f16 ('x86/livepatch: Fix livepatch application when CET is = active') Signed-off-by: Roger Pau Monn=C3=A9 --- Changes since v1: - Rename opaque state field to insn_buffer. --- xen/arch/arm/arm32/livepatch.c | 9 ++++--- xen/arch/arm/arm64/livepatch.c | 9 ++++--- xen/arch/arm/livepatch.c | 9 ++++--- xen/arch/x86/livepatch.c | 26 +++++++++++--------- xen/common/livepatch.c | 25 +++++++++++++------ xen/include/public/sysctl.h | 5 +--- xen/include/xen/livepatch.h | 38 ++++++++++++++++++++--------- xen/include/xen/livepatch_payload.h | 3 ++- 8 files changed, 76 insertions(+), 48 deletions(-) diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c index 3c50283b2ab7..80d2659b7861 100644 --- a/xen/arch/arm/arm32/livepatch.c +++ b/xen/arch/arm/arm32/livepatch.c @@ -11,23 +11,24 @@ #include #include =20 -void arch_livepatch_apply(struct livepatch_func *func) +void arch_livepatch_apply(const struct livepatch_func *func, + struct livepatch_fstate *state) { uint32_t insn; uint32_t *new_ptr; unsigned int i, len; =20 - BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque)); + BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(state->insn_buffer)); BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE !=3D sizeof(insn)); =20 ASSERT(vmap_of_xen_text); =20 - len =3D livepatch_insn_len(func); + len =3D livepatch_insn_len(func, state); if ( !len ) return; =20 /* Save old ones. */ - memcpy(func->opaque, func->old_addr, len); + memcpy(state->insn_buffer, func->old_addr, len); =20 if ( func->new_addr ) { diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c index 62d2ef373a0e..df2cebeddefb 100644 --- a/xen/arch/arm/arm64/livepatch.c +++ b/xen/arch/arm/arm64/livepatch.c @@ -15,23 +15,24 @@ #include #include =20 -void arch_livepatch_apply(struct livepatch_func *func) +void arch_livepatch_apply(const struct livepatch_func *func, + struct livepatch_fstate *state) { uint32_t insn; uint32_t *new_ptr; unsigned int i, len; =20 - BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque)); + BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(state->insn_buffer)); BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE !=3D sizeof(insn)); =20 ASSERT(vmap_of_xen_text); =20 - len =3D livepatch_insn_len(func); + len =3D livepatch_insn_len(func, state); if ( !len ) return; =20 /* Save old ones. */ - memcpy(func->opaque, func->old_addr, len); + memcpy(state->insn_buffer, func->old_addr, len); =20 if ( func->new_addr ) insn =3D aarch64_insn_gen_branch_imm((unsigned long)func->old_addr, diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c index d646379c8c5e..bbca1e5a5ed3 100644 --- a/xen/arch/arm/livepatch.c +++ b/xen/arch/arm/livepatch.c @@ -69,7 +69,7 @@ void arch_livepatch_revive(void) int arch_livepatch_verify_func(const struct livepatch_func *func) { /* If NOPing only do up to maximum amount we can put in the ->opaque. = */ - if ( !func->new_addr && (func->new_size > sizeof(func->opaque) || + if ( !func->new_addr && (func->new_size > LIVEPATCH_OPAQUE_SIZE || func->new_size % ARCH_PATCH_INSN_SIZE) ) return -EOPNOTSUPP; =20 @@ -79,15 +79,16 @@ int arch_livepatch_verify_func(const struct livepatch_f= unc *func) return 0; } =20 -void arch_livepatch_revert(const struct livepatch_func *func) +void arch_livepatch_revert(const struct livepatch_func *func, + struct livepatch_fstate *state) { uint32_t *new_ptr; unsigned int len; =20 new_ptr =3D func->old_addr - (void *)_start + vmap_of_xen_text; =20 - len =3D livepatch_insn_len(func); - memcpy(new_ptr, func->opaque, len); + len =3D livepatch_insn_len(func, state); + memcpy(new_ptr, state->insn_buffer, len); =20 clean_and_invalidate_dcache_va_range(new_ptr, len); } diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c index a54d991c5f0f..ee539f001b73 100644 --- a/xen/arch/x86/livepatch.c +++ b/xen/arch/x86/livepatch.c @@ -95,7 +95,7 @@ int arch_livepatch_verify_func(const struct livepatch_fun= c *func) if ( !func->new_addr ) { /* Only do up to maximum amount we can put in the ->opaque. */ - if ( func->new_size > sizeof(func->opaque) ) + if ( func->new_size > LIVEPATCH_OPAQUE_SIZE ) return -EOPNOTSUPP; =20 if ( func->old_size < func->new_size ) @@ -123,13 +123,14 @@ int arch_livepatch_verify_func(const struct livepatch= _func *func) * "noinline" to cause control flow change and thus invalidate I$ and * cause refetch after modification. */ -void noinline arch_livepatch_apply(struct livepatch_func *func) +void noinline arch_livepatch_apply(const struct livepatch_func *func, + struct livepatch_fstate *state) { uint8_t *old_ptr; - uint8_t insn[sizeof(func->opaque)]; + uint8_t insn[sizeof(state->insn_buffer)]; unsigned int len; =20 - func->patch_offset =3D 0; + state->patch_offset =3D 0; old_ptr =3D func->old_addr; =20 /* @@ -141,14 +142,14 @@ void noinline arch_livepatch_apply(struct livepatch_f= unc *func) * ENDBR64 or similar instructions). */ if ( is_endbr64(old_ptr) || is_endbr64_poison(func->old_addr) ) - func->patch_offset +=3D ENDBR64_LEN; + state->patch_offset +=3D ENDBR64_LEN; =20 /* This call must be done with ->patch_offset already set. */ - len =3D livepatch_insn_len(func); + len =3D livepatch_insn_len(func, state); if ( !len ) return; =20 - memcpy(func->opaque, old_ptr + func->patch_offset, len); + memcpy(state->insn_buffer, old_ptr + state->patch_offset, len); if ( func->new_addr ) { int32_t val; @@ -156,7 +157,7 @@ void noinline arch_livepatch_apply(struct livepatch_fun= c *func) BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE !=3D (1 + sizeof(val))); =20 insn[0] =3D 0xe9; /* Relative jump. */ - val =3D func->new_addr - (func->old_addr + func->patch_offset + + val =3D func->new_addr - (func->old_addr + state->patch_offset + ARCH_PATCH_INSN_SIZE); =20 memcpy(&insn[1], &val, sizeof(val)); @@ -164,17 +165,18 @@ void noinline arch_livepatch_apply(struct livepatch_f= unc *func) else add_nops(insn, len); =20 - memcpy(old_ptr + func->patch_offset, insn, len); + memcpy(old_ptr + state->patch_offset, insn, len); } =20 /* * "noinline" to cause control flow change and thus invalidate I$ and * cause refetch after modification. */ -void noinline arch_livepatch_revert(const struct livepatch_func *func) +void noinline arch_livepatch_revert(const struct livepatch_func *func, + struct livepatch_fstate *state) { - memcpy(func->old_addr + func->patch_offset, func->opaque, - livepatch_insn_len(func)); + memcpy(func->old_addr + state->patch_offset, state->insn_buffer, + livepatch_insn_len(func, state)); } =20 /* diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index 845340c7f398..1209fea2566c 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -260,6 +260,9 @@ static void free_payload_data(struct payload *payload) vfree((void *)payload->text_addr); =20 payload->pages =3D 0; + + /* fstate gets allocated strictly after move_payload. */ + XFREE(payload->fstate); } =20 /* @@ -656,6 +659,7 @@ static int prepare_payload(struct payload *payload, { const struct livepatch_elf_sec *sec; unsigned int i; + struct livepatch_func *funcs; struct livepatch_func *f; struct virtual_region *region; const Elf_Note *n; @@ -666,14 +670,19 @@ static int prepare_payload(struct payload *payload, if ( !section_ok(elf, sec, sizeof(*payload->funcs)) ) return -EINVAL; =20 - payload->funcs =3D sec->load_addr; + payload->funcs =3D funcs =3D sec->load_addr; payload->nfuncs =3D sec->sec->sh_size / sizeof(*payload->funcs); =20 + payload->fstate =3D xzalloc_array(typeof(*payload->fstate), + payload->nfuncs); + if ( !payload->fstate ) + return -ENOMEM; + for ( i =3D 0; i < payload->nfuncs; i++ ) { int rc; =20 - f =3D &(payload->funcs[i]); + f =3D &(funcs[i]); =20 if ( f->version !=3D LIVEPATCH_PAYLOAD_VERSION ) { @@ -1361,7 +1370,7 @@ static int apply_payload(struct payload *data) ASSERT(!local_irq_is_enabled()); =20 for ( i =3D 0; i < data->nfuncs; i++ ) - common_livepatch_apply(&data->funcs[i]); + common_livepatch_apply(&data->funcs[i], &data->fstate[i]); =20 arch_livepatch_revive(); =20 @@ -1397,7 +1406,7 @@ static int revert_payload(struct payload *data) } =20 for ( i =3D 0; i < data->nfuncs; i++ ) - common_livepatch_revert(&data->funcs[i]); + common_livepatch_revert(&data->funcs[i], &data->fstate[i]); =20 /* * Since we are running with IRQs disabled and the hooks may call comm= on @@ -1438,9 +1447,10 @@ static inline bool was_action_consistent(const struc= t payload *data, livepatch_f =20 for ( i =3D 0; i < data->nfuncs; i++ ) { - struct livepatch_func *f =3D &(data->funcs[i]); + const struct livepatch_func *f =3D &(data->funcs[i]); + const struct livepatch_fstate *s =3D &(data->fstate[i]); =20 - if ( f->applied !=3D expected_state ) + if ( s->applied !=3D expected_state ) { printk(XENLOG_ERR LIVEPATCH "%s: Payload has a function: '%s' = with inconsistent applied state.\n", data->name, f->name ?: "noname"); @@ -2157,7 +2167,8 @@ static void cf_check livepatch_printall(unsigned char= key) =20 for ( i =3D 0; i < data->nfuncs; i++ ) { - struct livepatch_func *f =3D &(data->funcs[i]); + const struct livepatch_func *f =3D &(data->funcs[i]); + printk(" %s patch %p(%u) with %p (%u)\n", f->name, f->old_addr, f->old_size, f->new_addr, f->new_= size); =20 diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index f1eba784059a..9b19679caeb1 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -991,10 +991,7 @@ struct livepatch_func { uint32_t new_size; uint32_t old_size; uint8_t version; /* MUST be LIVEPATCH_PAYLOAD_VERSION. */ - uint8_t opaque[LIVEPATCH_OPAQUE_SIZE]; - uint8_t applied; - uint8_t patch_offset; - uint8_t _pad[6]; + uint8_t _pad[39]; livepatch_expectation_t expect; }; typedef struct livepatch_func livepatch_func_t; diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h index 458eef57a7d1..df339a134e40 100644 --- a/xen/include/xen/livepatch.h +++ b/xen/include/xen/livepatch.h @@ -13,6 +13,9 @@ struct xen_sysctl_livepatch_op; =20 #include #include /* For -ENOSYS or -EOVERFLOW */ + +#include /* For LIVEPATCH_OPAQUE_SIZE */ + #ifdef CONFIG_LIVEPATCH =20 /* @@ -51,6 +54,12 @@ struct livepatch_symbol { bool new_symbol; }; =20 +struct livepatch_fstate { + unsigned int patch_offset; + enum livepatch_func_state applied; + uint8_t insn_buffer[LIVEPATCH_OPAQUE_SIZE]; +}; + int livepatch_op(struct xen_sysctl_livepatch_op *); void check_for_livepatch_work(void); unsigned long livepatch_symbols_lookup_by_name(const char *symname); @@ -87,10 +96,11 @@ void arch_livepatch_init(void); int arch_livepatch_verify_func(const struct livepatch_func *func); =20 static inline -unsigned int livepatch_insn_len(const struct livepatch_func *func) +unsigned int livepatch_insn_len(const struct livepatch_func *func, + const struct livepatch_fstate *state) { if ( !func->new_addr ) - return func->new_size - func->patch_offset; + return func->new_size - state->patch_offset; =20 return ARCH_PATCH_INSN_SIZE; } @@ -117,39 +127,43 @@ int arch_livepatch_safety_check(void); int arch_livepatch_quiesce(void); void arch_livepatch_revive(void); =20 -void arch_livepatch_apply(struct livepatch_func *func); -void arch_livepatch_revert(const struct livepatch_func *func); +void arch_livepatch_apply(const struct livepatch_func *func, + struct livepatch_fstate *state); +void arch_livepatch_revert(const struct livepatch_func *func, + struct livepatch_fstate *state); void arch_livepatch_post_action(void); =20 void arch_livepatch_mask(void); void arch_livepatch_unmask(void); =20 -static inline void common_livepatch_apply(struct livepatch_func *func) +static inline void common_livepatch_apply(const struct livepatch_func *fun= c, + struct livepatch_fstate *state) { /* If the action has been already executed on this function, do nothin= g. */ - if ( func->applied =3D=3D LIVEPATCH_FUNC_APPLIED ) + if ( state->applied =3D=3D LIVEPATCH_FUNC_APPLIED ) { printk(XENLOG_WARNING LIVEPATCH "%s: %s has been already applied b= efore\n", __func__, func->name); return; } =20 - arch_livepatch_apply(func); - func->applied =3D LIVEPATCH_FUNC_APPLIED; + arch_livepatch_apply(func, state); + state->applied =3D LIVEPATCH_FUNC_APPLIED; } =20 -static inline void common_livepatch_revert(struct livepatch_func *func) +static inline void common_livepatch_revert(const struct livepatch_func *fu= nc, + struct livepatch_fstate *state) { /* If the apply action hasn't been executed on this function, do nothi= ng. */ - if ( !func->old_addr || func->applied =3D=3D LIVEPATCH_FUNC_NOT_APPLIE= D ) + if ( !func->old_addr || state->applied =3D=3D LIVEPATCH_FUNC_NOT_APPLI= ED ) { printk(XENLOG_WARNING LIVEPATCH "%s: %s has not been applied befor= e\n", __func__, func->name); return; } =20 - arch_livepatch_revert(func); - func->applied =3D LIVEPATCH_FUNC_NOT_APPLIED; + arch_livepatch_revert(func, state); + state->applied =3D LIVEPATCH_FUNC_NOT_APPLIED; } #else =20 diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatc= h_payload.h index 9f5f0642057c..b9cd4f209670 100644 --- a/xen/include/xen/livepatch_payload.h +++ b/xen/include/xen/livepatch_payload.h @@ -52,7 +52,8 @@ struct payload { size_t ro_size; /* .. and its size (if any). */ unsigned int pages; /* Total pages for [text,rw,ro]_a= ddr */ struct list_head applied_list; /* Linked to 'applied_list'. */ - struct livepatch_func *funcs; /* The array of functions to patc= h. */ + const struct livepatch_func *funcs; /* The array of functions to patc= h. */ + struct livepatch_fstate *fstate; /* State of patched functions. */ unsigned int nfuncs; /* Nr of functions to patch. */ const struct livepatch_symbol *symtab; /* All symbols. */ const char *strtab; /* Pointer to .strtab. */ --=20 2.43.0