|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [livepatch-hooks-2 PATCH 4/4] livepatch: Add per-function applied/reverted state tracking marker
Livepatch only tracks an entire payload applied/reverted state. But,
with an option to supply the apply_payload() and/or revert_payload()
functions as optional hooks, it becomes possible to intermix the
execution of the original apply_payload()/revert_payload() functions
with their dynamically supplied counterparts.
It is important then to track the current state of every function
being patched and prevent situations of unintentional double-apply
or unapplied revert.
To support that, it is necessary to extend public interface of the
livepatch. The struct livepatch_func gets additional field holding
the applied/reverted state marker.
To reflect the livepatch payload ABI change, bump the version flag
LIVEPATCH_PAYLOAD_VERSION up to 2.
The above solution only applies to x86 architecture for now.
Signed-off-by: Pawel Wieczorkiewicz <wipawel@xxxxxxxxx>
Reviewed-by: Andra-Irina Paraschiv <andraprs@xxxxxxxxxx>
Reviewed-by: Bjoern Doebel <doebel@xxxxxxxxx>
Reviewed-by: Martin Pohlack <mpohlack@xxxxxxxxx>
---
xen/arch/x86/livepatch.c | 20 +++++++++++++++++++-
xen/common/livepatch.c | 35 +++++++++++++++++++++++++++++++++++
xen/include/public/sysctl.h | 11 ++++++++++-
xen/include/xen/livepatch.h | 2 +-
4 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index 436ee40fe1..76fa91a082 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -61,6 +61,14 @@ void noinline arch_livepatch_apply(struct livepatch_func
*func)
if ( !len )
return;
+ /* If the apply action has been already executed on this function, do
nothing... */
+ if ( func->applied == LIVEPATCH_FUNC_APPLIED )
+ {
+ printk(XENLOG_WARNING LIVEPATCH "%s: %s has been already applied
before\n",
+ __func__, func->name);
+ return;
+ }
+
memcpy(func->opaque, old_ptr, len);
if ( func->new_addr )
{
@@ -77,15 +85,25 @@ void noinline arch_livepatch_apply(struct livepatch_func
*func)
add_nops(insn, len);
memcpy(old_ptr, insn, len);
+ func->applied = LIVEPATCH_FUNC_APPLIED;
}
/*
* "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(struct livepatch_func *func)
{
+ /* If the apply action hasn't been executed on this function, do
nothing... */
+ if ( !func->old_addr || func->applied == LIVEPATCH_FUNC_NOT_APPLIED )
+ {
+ printk(XENLOG_WARNING LIVEPATCH "%s: %s has not been applied before\n",
+ __func__, func->name);
+ return;
+ }
+
memcpy(func->old_addr, func->opaque, livepatch_insn_len(func));
+ func->applied = LIVEPATCH_FUNC_NOT_APPLIED;
}
/*
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 585ec9819a..090a48977b 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1242,6 +1242,29 @@ static inline void revert_payload_tail(struct payload
*data)
data->state = LIVEPATCH_STATE_CHECKED;
}
+/*
+ * Check if an action has applied the same state to all payload's functions
consistently.
+ */
+static inline bool was_action_consistent(const struct payload *data,
livepatch_func_state_t expected_state)
+{
+ int i;
+
+ for ( i = 0; i < data->nfuncs; i++ )
+ {
+ struct livepatch_func *f = &(data->funcs[i]);
+
+ if ( f->applied != expected_state )
+ {
+ printk(XENLOG_ERR LIVEPATCH "%s: Payload has a function: '%s' with
inconsistent applied state.\n",
+ data->name, f->name ?: "noname");
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
/*
* This function is executed having all other CPUs with no deep stack (we may
* have cpu_idle on it) and IRQs disabled.
@@ -1268,6 +1291,9 @@ static void livepatch_do_action(void)
else
rc = apply_payload(data);
+ if ( !was_action_consistent(data, rc ? LIVEPATCH_FUNC_NOT_APPLIED :
LIVEPATCH_FUNC_APPLIED) )
+ panic("livepatch: partially applied payload '%s'!\n", data->name);
+
if ( rc == 0 )
apply_payload_tail(data);
break;
@@ -1282,6 +1308,9 @@ static void livepatch_do_action(void)
else
rc = revert_payload(data);
+ if ( !was_action_consistent(data, rc ? LIVEPATCH_FUNC_APPLIED :
LIVEPATCH_FUNC_NOT_APPLIED) )
+ panic("livepatch: partially reverted payload '%s'!\n", data->name);
+
if ( rc == 0 )
revert_payload_tail(data);
break;
@@ -1304,6 +1333,9 @@ static void livepatch_do_action(void)
other->rc = revert_payload(other);
+ if ( !was_action_consistent(other, rc ? LIVEPATCH_FUNC_APPLIED :
LIVEPATCH_FUNC_NOT_APPLIED) )
+ panic("livepatch: partially reverted payload '%s'!\n",
other->name);
+
if ( other->rc == 0 )
revert_payload_tail(other);
else
@@ -1324,6 +1356,9 @@ static void livepatch_do_action(void)
else
rc = apply_payload(data);
+ if ( !was_action_consistent(data, rc ? LIVEPATCH_FUNC_NOT_APPLIED
: LIVEPATCH_FUNC_APPLIED) )
+ panic("livepatch: partially applied payload '%s'!\n",
data->name);
+
if ( rc == 0 )
apply_payload_tail(data);
}
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index cfbb8760d4..98cdcc64bb 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 1
+#define LIVEPATCH_PAYLOAD_VERSION 2
/*
* .livepatch.funcs structure layout defined in the `Payload format`
* section in the Live Patch design document.
@@ -826,6 +826,11 @@ struct xen_sysctl_cpu_featureset {
* We guard this with __XEN__ as toolstacks SHOULD not use it.
*/
#ifdef __XEN__
+typedef enum livepatch_func_state {
+ LIVEPATCH_FUNC_NOT_APPLIED = 0,
+ LIVEPATCH_FUNC_APPLIED = 1
+} livepatch_func_state_t;
+
struct livepatch_func {
const char *name; /* Name of function to be patched. */
void *new_addr;
@@ -834,6 +839,10 @@ struct livepatch_func {
uint32_t old_size;
uint8_t version; /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
uint8_t opaque[31];
+#if defined CONFIG_X86
+ uint8_t applied;
+ uint8_t _pad[7];
+#endif
};
typedef struct livepatch_func livepatch_func_t;
#endif
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index 2aec532ee2..a93126f631 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -117,7 +117,7 @@ int arch_livepatch_quiesce(void);
void arch_livepatch_revive(void);
void arch_livepatch_apply(struct livepatch_func *func);
-void arch_livepatch_revert(const struct livepatch_func *func);
+void arch_livepatch_revert(struct livepatch_func *func);
void arch_livepatch_post_action(void);
void arch_livepatch_mask(void);
--
2.16.5
Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Ralf Herbrich
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |