summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '0032-xen-livepatch-fix-norevert-test-attempt-to-open-code.patch')
-rw-r--r--0032-xen-livepatch-fix-norevert-test-attempt-to-open-code.patch186
1 files changed, 186 insertions, 0 deletions
diff --git a/0032-xen-livepatch-fix-norevert-test-attempt-to-open-code.patch b/0032-xen-livepatch-fix-norevert-test-attempt-to-open-code.patch
new file mode 100644
index 0000000..76af9ef
--- /dev/null
+++ b/0032-xen-livepatch-fix-norevert-test-attempt-to-open-code.patch
@@ -0,0 +1,186 @@
+From 5564323f643715f9d364df88e0eb9c7d6fd2c22b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com>
+Date: Tue, 5 Mar 2024 11:59:43 +0100
+Subject: [PATCH 32/67] xen/livepatch: fix norevert test attempt to open-code
+ revert
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The purpose of the norevert test is to install a dummy handler that replaces
+the internal Xen revert code, and then perform the revert in the post-revert
+hook. For that purpose the usage of the previous common_livepatch_revert() is
+not enough, as that just reverts specific functions, but not the whole state of
+the payload.
+
+Remove both common_livepatch_{apply,revert}() and instead expose
+revert_payload{,_tail}() in order to perform the patch revert from the
+post-revert hook.
+
+Fixes: 6047104c3ccc ('livepatch: Add per-function applied/reverted state tracking marker')
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
+master commit: cdae267ce10d04d71d1687b5701ff2911a96b6dc
+master date: 2024-02-28 16:57:25 +0000
+---
+ xen/common/livepatch.c | 41 +++++++++++++++++--
+ xen/include/xen/livepatch.h | 32 ++-------------
+ .../livepatch/xen_action_hooks_norevert.c | 22 +++-------
+ 3 files changed, 46 insertions(+), 49 deletions(-)
+
+diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
+index a129ab9973..a5068a2217 100644
+--- a/xen/common/livepatch.c
++++ b/xen/common/livepatch.c
+@@ -1310,7 +1310,22 @@ static int apply_payload(struct payload *data)
+ ASSERT(!local_irq_is_enabled());
+
+ for ( i = 0; i < data->nfuncs; i++ )
+- common_livepatch_apply(&data->funcs[i], &data->fstate[i]);
++ {
++ const struct livepatch_func *func = &data->funcs[i];
++ struct livepatch_fstate *state = &data->fstate[i];
++
++ /* If the action has been already executed on this function, do nothing. */
++ if ( state->applied == LIVEPATCH_FUNC_APPLIED )
++ {
++ printk(XENLOG_WARNING LIVEPATCH
++ "%s: %s has been already applied before\n",
++ __func__, func->name);
++ continue;
++ }
++
++ arch_livepatch_apply(func, state);
++ state->applied = LIVEPATCH_FUNC_APPLIED;
++ }
+
+ arch_livepatch_revive();
+
+@@ -1326,7 +1341,7 @@ static inline void apply_payload_tail(struct payload *data)
+ data->state = LIVEPATCH_STATE_APPLIED;
+ }
+
+-static int revert_payload(struct payload *data)
++int revert_payload(struct payload *data)
+ {
+ unsigned int i;
+ int rc;
+@@ -1341,7 +1356,25 @@ static int revert_payload(struct payload *data)
+ }
+
+ for ( i = 0; i < data->nfuncs; i++ )
+- common_livepatch_revert(&data->funcs[i], &data->fstate[i]);
++ {
++ const struct livepatch_func *func = &data->funcs[i];
++ struct livepatch_fstate *state = &data->fstate[i];
++
++ /*
++ * If the apply action hasn't been executed on this function, do
++ * nothing.
++ */
++ if ( !func->old_addr || state->applied == LIVEPATCH_FUNC_NOT_APPLIED )
++ {
++ printk(XENLOG_WARNING LIVEPATCH
++ "%s: %s has not been applied before\n",
++ __func__, func->name);
++ continue;
++ }
++
++ arch_livepatch_revert(func, state);
++ state->applied = LIVEPATCH_FUNC_NOT_APPLIED;
++ }
+
+ /*
+ * Since we are running with IRQs disabled and the hooks may call common
+@@ -1359,7 +1392,7 @@ static int revert_payload(struct payload *data)
+ return 0;
+ }
+
+-static inline void revert_payload_tail(struct payload *data)
++void revert_payload_tail(struct payload *data)
+ {
+ list_del(&data->applied_list);
+
+diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
+index 537d3d58b6..c9ee58fd37 100644
+--- a/xen/include/xen/livepatch.h
++++ b/xen/include/xen/livepatch.h
+@@ -136,35 +136,11 @@ void arch_livepatch_post_action(void);
+ void arch_livepatch_mask(void);
+ void arch_livepatch_unmask(void);
+
+-static inline void common_livepatch_apply(const struct livepatch_func *func,
+- struct livepatch_fstate *state)
+-{
+- /* If the action has been already executed on this function, do nothing. */
+- if ( state->applied == LIVEPATCH_FUNC_APPLIED )
+- {
+- printk(XENLOG_WARNING LIVEPATCH "%s: %s has been already applied before\n",
+- __func__, func->name);
+- return;
+- }
+-
+- arch_livepatch_apply(func, state);
+- state->applied = LIVEPATCH_FUNC_APPLIED;
+-}
++/* Only for testing purposes. */
++struct payload;
++int revert_payload(struct payload *data);
++void revert_payload_tail(struct payload *data);
+
+-static inline void common_livepatch_revert(const struct livepatch_func *func,
+- struct livepatch_fstate *state)
+-{
+- /* If the apply action hasn't been executed on this function, do nothing. */
+- if ( !func->old_addr || state->applied == LIVEPATCH_FUNC_NOT_APPLIED )
+- {
+- printk(XENLOG_WARNING LIVEPATCH "%s: %s has not been applied before\n",
+- __func__, func->name);
+- return;
+- }
+-
+- arch_livepatch_revert(func, state);
+- state->applied = LIVEPATCH_FUNC_NOT_APPLIED;
+-}
+ #else
+
+ /*
+diff --git a/xen/test/livepatch/xen_action_hooks_norevert.c b/xen/test/livepatch/xen_action_hooks_norevert.c
+index c173855192..c5fbab1746 100644
+--- a/xen/test/livepatch/xen_action_hooks_norevert.c
++++ b/xen/test/livepatch/xen_action_hooks_norevert.c
+@@ -96,26 +96,14 @@ static int revert_hook(livepatch_payload_t *payload)
+
+ static void post_revert_hook(livepatch_payload_t *payload)
+ {
+- int i;
++ unsigned long flags;
+
+ printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+- for (i = 0; i < payload->nfuncs; i++)
+- {
+- const struct livepatch_func *func = &payload->funcs[i];
+- struct livepatch_fstate *fstate = &payload->fstate[i];
+-
+- BUG_ON(revert_cnt != 1);
+- BUG_ON(fstate->applied != LIVEPATCH_FUNC_APPLIED);
+-
+- /* Outside of quiesce zone: MAY TRIGGER HOST CRASH/UNDEFINED BEHAVIOR */
+- arch_livepatch_quiesce();
+- common_livepatch_revert(payload);
+- arch_livepatch_revive();
+- BUG_ON(fstate->applied == LIVEPATCH_FUNC_APPLIED);
+-
+- printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name);
+- }
++ local_irq_save(flags);
++ BUG_ON(revert_payload(payload));
++ revert_payload_tail(payload);
++ local_irq_restore(flags);
+
+ printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+ }
+--
+2.44.0
+