Xen-Devel Archive on lore.kernel.org
 help / color / Atom feed
From: Pawel Wieczorkiewicz <wipawel@amazon.de>
To: <xen-devel@lists.xen.org>, <xen-devel@lists.xenproject.org>
Cc: wipawel@amazon.com, "Stefano Stabellini" <sstabellini@kernel.org>,
	"Wei Liu" <wl@xen.org>,
	"Konrad Rzeszutek Wilk" <konrad.wilk@oracle.com>,
	"George Dunlap" <George.Dunlap@eu.citrix.com>,
	"Andrew Cooper" <andrew.cooper3@citrix.com>,
	"Ross Lagerwall" <ross.lagerwall@citrix.com>,
	"Ian Jackson" <ian.jackson@eu.citrix.com>,
	mpohlack@amazon.com, "Tim Deegan" <tim@xen.org>,
	"Pawel Wieczorkiewicz" <wipawel@amazon.de>,
	"Julien Grall" <julien.grall@arm.com>,
	"Jan Beulich" <jbeulich@suse.com>,
	"Volodymyr Babchuk" <Volodymyr_Babchuk@epam.com>,
	"Roger Pau Monné" <roger.pau@citrix.com>
Subject: [Xen-devel] [PATCH v2 07/12] livepatch: Add per-function applied/reverted state tracking marker
Date: Tue, 27 Aug 2019 08:46:19 +0000
Message-ID: <20190827084624.116917-8-wipawel@amazon.de> (raw)
In-Reply-To: <20190827084624.116917-1-wipawel@amazon.de>

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.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Bjoern Doebel <doebel@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
---
Changed since v1:
  * support the feature for all arch (add handling for Arm)
  * add common is_func_applied() and is_func_reverted() to be
    used by all arch
  * remove explicit enum values from enum livepatch_func_state
  * added corresponding documentation
  * added tests

 docs/misc/livepatch.pandoc                     |  15 ++-
 xen/arch/arm/arm32/livepatch.c                 |  12 ++-
 xen/arch/arm/arm64/livepatch.c                 |  12 ++-
 xen/arch/arm/livepatch.c                       |  10 +-
 xen/arch/x86/livepatch.c                       |  22 +++-
 xen/common/livepatch.c                         |  35 ++++++
 xen/include/public/sysctl.h                    |   9 +-
 xen/include/xen/livepatch.h                    |  27 ++++-
 xen/test/livepatch/Makefile                    |  27 ++++-
 xen/test/livepatch/xen_action_hooks.c          |   2 +
 xen/test/livepatch/xen_action_hooks_marker.c   | 112 +++++++++++++++++++
 xen/test/livepatch/xen_action_hooks_noapply.c  | 136 +++++++++++++++++++++++
 xen/test/livepatch/xen_action_hooks_norevert.c | 143 +++++++++++++++++++++++++
 13 files changed, 553 insertions(+), 9 deletions(-)
 create mode 100644 xen/test/livepatch/xen_action_hooks_marker.c
 create mode 100644 xen/test/livepatch/xen_action_hooks_noapply.c
 create mode 100644 xen/test/livepatch/xen_action_hooks_norevert.c

diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index 6fafb9e4b1..6ab7f4c2d2 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -297,10 +297,14 @@ which describe the functions to be patched:
         uint32_t old_size;
         uint8_t version;
         uint8_t opaque[31];
+        /* Added to livepatch payload version 2: */
+        uint8_t applied;
+        uint8_t _pad[7];
     };
 
 The size of the structure is 64 bytes on 64-bit hypervisors. It will be
 52 on 32-bit hypervisors.
+The version 2 of the payload adds additional 8 bytes to the structure size.
 
  * `name` is the symbol name of the old function. Only used if `old_addr` is
    zero, otherwise will be used during dynamic linking (when hypervisor loads
@@ -324,9 +328,15 @@ The size of the structure is 64 bytes on 64-bit hypervisors. It will be
    * If the value of `new_addr` is zero then `new_size` determines how many
     instruction bytes to NOP (up to opaque size modulo smallest platform
     instruction - 1 byte x86 and 4 bytes on ARM).
- * `version` is to be one.
+ * `version` indicates version of the generated payload.
  * `opaque` **MUST** be zero.
 
+The version 2 of the payload adds the following fields to the structure:
+
+  * `applied` tracks function's applied/reverted state. It has a boolean type
+    either LIVEPATCH_FUNC_NOT_APPLIED or LIVEPATCH_FUNC_APPLIED.
+  * `_pad[7]` adds padding to align to 8 bytes.
+
 The size of the `livepatch_func` array is determined from the ELF section
 size.
 
@@ -378,6 +388,9 @@ A simple example of what a payload file can be:
         uint32_t old_size;
         uint8_t version;
         uint8_t pad[31];
+        /* Added to livepatch payload version 2: */
+        uint8_t applied;
+        uint8_t _pad[7];
     };
 
     /* Our replacement function for xen_extra_version. */
diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 41378a54ae..76780d69bf 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -22,9 +22,16 @@ void arch_livepatch_apply(struct livepatch_func *func)
 
     ASSERT(vmap_of_xen_text);
 
+    /*
+     * If the apply action has been already executed
+     * on this function, do nothing...
+     */
+    if ( is_func_applied(func) )
+        return;
+
     len = livepatch_insn_len(func);
     if ( !len )
-        return;
+        goto applied;
 
     /* Save old ones. */
     memcpy(func->opaque, func->old_addr, len);
@@ -73,6 +80,9 @@ void arch_livepatch_apply(struct livepatch_func *func)
     if ( func->new_addr )
         clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
     clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
+
+applied:
+    func->applied = LIVEPATCH_FUNC_APPLIED;
 }
 
 /* arch_livepatch_revert shared with ARM 32/ARM 64. */
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index 5c75779284..61a764816c 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -26,9 +26,16 @@ void arch_livepatch_apply(struct livepatch_func *func)
 
     ASSERT(vmap_of_xen_text);
 
+    /*
+     * If the apply action has been already executed
+     * on this function, do nothing...
+     */
+    if ( is_func_applied(func) )
+         return;
+
     len = livepatch_insn_len(func);
     if ( !len )
-        return;
+        goto applied;
 
     /* Save old ones. */
     memcpy(func->opaque, func->old_addr, len);
@@ -60,6 +67,9 @@ void arch_livepatch_apply(struct livepatch_func *func)
     if ( func->new_addr )
         clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
     clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
+
+applied:
+    func->applied = LIVEPATCH_FUNC_APPLIED;
 }
 
 /* arch_livepatch_revert shared with ARM 32/ARM 64. */
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 279d52cc6c..022402d55f 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -73,17 +73,25 @@ int arch_livepatch_verify_func(const struct livepatch_func *func)
     return 0;
 }
 
-void arch_livepatch_revert(const struct livepatch_func *func)
+void arch_livepatch_revert(struct livepatch_func *func)
 {
     uint32_t *new_ptr;
     unsigned int len;
 
+    /*
+     * If the apply action hasn't been executed
+     * on this function, do nothing...
+     */
+    if ( is_func_reverted(func) )
+        return;
+
     new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
 
     len = livepatch_insn_len(func);
     memcpy(new_ptr, func->opaque, len);
 
     clean_and_invalidate_dcache_va_range(new_ptr, len);
+    func->applied = LIVEPATCH_FUNC_NOT_APPLIED;
 }
 
 void arch_livepatch_post_action(void)
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index c82cf53b9e..5701c90e48 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -56,10 +56,17 @@ void noinline arch_livepatch_apply(struct livepatch_func *func)
     uint8_t insn[sizeof(func->opaque)];
     unsigned int len;
 
+    /*
+     * If the apply action has been already executed
+     * on this function, do nothing...
+     */
+    if ( is_func_applied(func) )
+         return;
+
     old_ptr = func->old_addr;
     len = livepatch_insn_len(func);
     if ( !len )
-        return;
+        goto applied;
 
     memcpy(func->opaque, old_ptr, len);
     if ( func->new_addr )
@@ -77,15 +84,26 @@ void noinline arch_livepatch_apply(struct livepatch_func *func)
         add_nops(insn, len);
 
     memcpy(old_ptr, insn, len);
+
+applied:
+    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 ( is_func_reverted(func) )
+        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 705b5b8151..d76619844c 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1240,6 +1240,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.
@@ -1266,6 +1289,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;
@@ -1280,6 +1306,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;
@@ -1302,6 +1331,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
@@ -1322,6 +1354,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 1b2b165a6d..3bcb892ce1 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,
+    LIVEPATCH_FUNC_APPLIED
+} livepatch_func_state_t;
+
 struct livepatch_func {
     const char *name;       /* Name of function to be patched. */
     void *new_addr;
@@ -834,6 +839,8 @@ struct livepatch_func {
     uint32_t old_size;
     uint8_t version;        /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
     uint8_t opaque[31];
+    uint8_t applied;
+    uint8_t _pad[7];
 };
 typedef struct livepatch_func livepatch_func_t;
 #endif
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index 2aec532ee2..28f9536776 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -109,6 +109,31 @@ static inline int livepatch_verify_distance(const struct livepatch_func *func)
 
     return 0;
 }
+
+static inline bool_t is_func_applied(const struct livepatch_func *func)
+{
+    if ( func->applied == LIVEPATCH_FUNC_APPLIED )
+    {
+        printk(XENLOG_WARNING LIVEPATCH "%s: %s has been already applied before\n",
+                __func__, func->name);
+        return true;
+    }
+
+    return false;
+}
+
+static inline bool_t is_func_reverted(const struct livepatch_func *func)
+{
+    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 true;
+    }
+
+    return false;
+}
+
 /*
  * These functions are called around the critical region patching live code,
  * for an architecture to take make appropratie global state adjustments.
@@ -117,7 +142,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);
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index bbc6bdaf64..23113d3418 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -24,6 +24,9 @@ LIVEPATCH_PREPOST_HOOKS := xen_prepost_hooks.livepatch
 LIVEPATCH_PREPOST_HOOKS_FAIL := xen_prepost_hooks_fail.livepatch
 LIVEPATCH_ACTION_HOOKS := xen_action_hooks.livepatch
 LIVEPATCH_ACTION_HOOKS_NOFUNC := xen_action_hooks_nofunc.livepatch
+LIVEPATCH_ACTION_HOOKS_MARKER:= xen_action_hooks_marker.livepatch
+LIVEPATCH_ACTION_HOOKS_NOAPPLY:= xen_action_hooks_noapply.livepatch
+LIVEPATCH_ACTION_HOOKS_NOREVERT:= xen_action_hooks_norevert.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
@@ -34,6 +37,9 @@ LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS)
 LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS_FAIL)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
+LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_MARKER)
+LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOAPPLY)
+LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -158,7 +164,26 @@ $(LIVEPATCH_ACTION_HOOKS): xen_action_hooks.o xen_hello_world_func.o note.o xen_
 $(LIVEPATCH_ACTION_HOOKS_NOFUNC): xen_action_hooks_nofunc.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOFUNC) $^
 
+xen_actions_hooks_marker.o: config.h
+
+.PHONY: $(LIVEPATCH_ACTION_HOOKS_MARKER)
+$(LIVEPATCH_ACTION_HOOKS_MARKER): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_MARKER) $^
+
+xen_actions_hooks_noapply.o: config.h
+
+.PHONY: $(LIVEPATCH_ACTION_HOOKS_NOAPPLY)
+$(LIVEPATCH_ACTION_HOOKS_NOAPPLY): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) $^
+
+xen_actions_hooks_norevert.o: config.h
+
+.PHONY: $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
+$(LIVEPATCH_ACTION_HOOKS_NOREVERT): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOREVERT) $^
+
 .PHONY: livepatch
 livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID) \
            $(LIVEPATCH_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL) $(LIVEPATCH_ACTION_HOOKS) \
-           $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
+           $(LIVEPATCH_ACTION_HOOKS_NOFUNC) $(LIVEPATCH_ACTION_HOOKS_MARKER) $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) \
+           $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
diff --git a/xen/test/livepatch/xen_action_hooks.c b/xen/test/livepatch/xen_action_hooks.c
index a947afc41f..39b5313027 100644
--- a/xen/test/livepatch/xen_action_hooks.c
+++ b/xen/test/livepatch/xen_action_hooks.c
@@ -28,6 +28,7 @@ static int apply_hook(livepatch_payload_t *payload)
     {
         struct livepatch_func *func = &payload->funcs[i];
 
+        func->applied = LIVEPATCH_FUNC_APPLIED;
         apply_cnt++;
 
         printk(KERN_DEBUG "%s: applying: %s\n", __func__, func->name);
@@ -48,6 +49,7 @@ static int revert_hook(livepatch_payload_t *payload)
     {
         struct livepatch_func *func = &payload->funcs[i];
 
+        func->applied = LIVEPATCH_FUNC_NOT_APPLIED;
         revert_cnt++;
 
         printk(KERN_DEBUG "%s: reverting: %s\n", __func__, func->name);
diff --git a/xen/test/livepatch/xen_action_hooks_marker.c b/xen/test/livepatch/xen_action_hooks_marker.c
new file mode 100644
index 0000000000..4f807a577f
--- /dev/null
+++ b/xen/test/livepatch/xen_action_hooks_marker.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#include "config.h"
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/version.h>
+#include <xen/livepatch.h>
+#include <xen/livepatch_payload.h>
+
+#include <public/sysctl.h>
+
+static const char hello_world_patch_this_fnc[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+static int pre_apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: pre applied: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return 0;
+}
+
+static void post_apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: post applied: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+static int pre_revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: pre reverted: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return 0;
+}
+
+static void post_revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook);
+LIVEPATCH_POSTAPPLY_HOOK(post_apply_hook);
+LIVEPATCH_PREREVERT_HOOK(pre_revert_hook);
+LIVEPATCH_POSTREVERT_HOOK(post_revert_hook);
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_xen_hello_world = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = hello_world_patch_this_fnc,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = NEW_CODE_SZ,
+    .old_size = OLD_CODE_SZ,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/test/livepatch/xen_action_hooks_noapply.c b/xen/test/livepatch/xen_action_hooks_noapply.c
new file mode 100644
index 0000000000..4c55c156a6
--- /dev/null
+++ b/xen/test/livepatch/xen_action_hooks_noapply.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#include "config.h"
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/version.h>
+#include <xen/livepatch.h>
+#include <xen/livepatch_payload.h>
+
+#include <public/sysctl.h>
+
+static const char hello_world_patch_this_fnc[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+static unsigned int apply_cnt;
+
+static int pre_apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: pre applied: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return 0;
+}
+
+static int apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        apply_cnt++;
+        printk(KERN_DEBUG "%s: applying: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return -EINVAL; /* Mark action as inconsistent */
+}
+
+static void post_apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(apply_cnt != 1);
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: post applied: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+static int pre_revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: pre reverted: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return 0;
+}
+
+static void post_revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+LIVEPATCH_APPLY_HOOK(apply_hook);
+
+LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook);
+LIVEPATCH_POSTAPPLY_HOOK(post_apply_hook);
+LIVEPATCH_PREREVERT_HOOK(pre_revert_hook);
+LIVEPATCH_POSTREVERT_HOOK(post_revert_hook);
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_xen_hello_world = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = hello_world_patch_this_fnc,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = NEW_CODE_SZ,
+    .old_size = OLD_CODE_SZ,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/test/livepatch/xen_action_hooks_norevert.c b/xen/test/livepatch/xen_action_hooks_norevert.c
new file mode 100644
index 0000000000..4408166f47
--- /dev/null
+++ b/xen/test/livepatch/xen_action_hooks_norevert.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#include "config.h"
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/version.h>
+#include <xen/livepatch.h>
+#include <xen/livepatch_payload.h>
+
+#include <public/sysctl.h>
+
+static const char hello_world_patch_this_fnc[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+static unsigned int revert_cnt;
+
+static int pre_apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: pre applied: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return 0;
+}
+
+static void post_apply_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: post applied: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+static int pre_revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED);
+        printk(KERN_DEBUG "%s: pre reverted: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return 0;
+}
+
+static int revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        revert_cnt++;
+        printk(KERN_DEBUG "%s: reverting: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return -EINVAL; /* Mark action as inconsistent */
+}
+
+static void post_revert_hook(livepatch_payload_t *payload)
+{
+    int i;
+
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+
+    for (i = 0; i < payload->nfuncs; i++)
+    {
+        struct livepatch_func *func = &payload->funcs[i];
+
+        BUG_ON(revert_cnt != 1);
+        BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED);
+
+        /* Outside of quiesce zone: MAY TRIGGER HOST CRASH/UNDEFINED BEHAVIOR */
+        arch_livepatch_quiesce();
+        arch_livepatch_revert(payload);
+        arch_livepatch_revive();
+        BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED);
+
+        printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+LIVEPATCH_APPLY_HOOK(revert_hook);
+
+LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook);
+LIVEPATCH_POSTAPPLY_HOOK(post_apply_hook);
+LIVEPATCH_PREREVERT_HOOK(pre_revert_hook);
+LIVEPATCH_POSTREVERT_HOOK(post_revert_hook);
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_xen_hello_world = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = hello_world_patch_this_fnc,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = NEW_CODE_SZ,
+    .old_size = OLD_CODE_SZ,
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
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@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

  parent reply index

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 01/14] livepatch: Always check hypervisor build ID upon hotpatch upload Pawel Wieczorkiewicz
2019-08-21 18:16   ` Konrad Rzeszutek Wilk
2019-08-21  8:19 ` [Xen-devel] [PATCH 02/14] livepatch: Allow to override inter-modules buildid dependency Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 03/14] python: Add XC binding for Xen build ID Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 04/14] livepatch: Export payload structure via livepatch_payload.h Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 05/14] livepatch: Implement pre-|post- apply|revert hooks Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks Pawel Wieczorkiewicz
2019-08-21 18:31   ` Konrad Rzeszutek Wilk
2019-08-21 19:06     ` Wieczorkiewicz, Pawel
2019-08-26 14:30       ` Konrad Rzeszutek Wilk
2019-08-21  8:19 ` [Xen-devel] [PATCH 07/14] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 08/14] livepatch: always print XENLOG_ERR information Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker Pawel Wieczorkiewicz
2019-08-21 18:28   ` Konrad Rzeszutek Wilk
2019-08-21 19:00     ` Wieczorkiewicz, Pawel
2019-08-21 21:34   ` Julien Grall
2019-08-22  7:44     ` Wieczorkiewicz, Pawel
2019-08-22 10:07       ` Julien Grall
2019-08-22 10:20         ` Wieczorkiewicz, Pawel
2019-08-22 10:43           ` Julien Grall
2019-08-22 11:15             ` Wieczorkiewicz, Pawel
2019-08-22 15:02               ` Julien Grall
2019-08-22 10:29   ` Julien Grall
2019-08-22 11:02     ` Wieczorkiewicz, Pawel
2019-08-22 15:30       ` Julien Grall
2019-08-22 15:42         ` Wieczorkiewicz, Pawel
2019-08-21  8:19 ` [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations Pawel Wieczorkiewicz
2019-08-21 18:30   ` Konrad Rzeszutek Wilk
2019-08-21 19:02     ` Wieczorkiewicz, Pawel
2019-08-22 10:31   ` Julien Grall
2019-08-22 11:03     ` Wieczorkiewicz, Pawel
2019-08-21  8:19 ` [Xen-devel] [PATCH 11/14] livepatch: Add support for modules .modinfo section metadata Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 12/14] livepatch: Handle arbitrary size names with the list operation Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 13/14] livepatch: Add metadata runtime retrieval mechanism Pawel Wieczorkiewicz
2019-08-21  8:19 ` [Xen-devel] [PATCH 14/14] livepatch: Add python bindings for livepatch operations Pawel Wieczorkiewicz
2019-08-22 21:55   ` Marek Marczykowski-Górecki
2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 01/12] livepatch: Always check hypervisor build ID upon hotpatch upload Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 02/12] livepatch: Allow to override inter-modules buildid dependency Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 03/12] livepatch: Export payload structure via livepatch_payload.h Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 04/12] livepatch: Implement pre-|post- apply|revert hooks Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 05/12] livepatch: Add support for apply|revert action replacement hooks Pawel Wieczorkiewicz
2019-08-27 16:58     ` Konrad Rzeszutek Wilk
2019-08-28  7:37       ` Wieczorkiewicz, Pawel
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 06/12] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence Pawel Wieczorkiewicz
2019-08-27  8:46   ` Pawel Wieczorkiewicz [this message]
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations Pawel Wieczorkiewicz
2019-08-29 14:34     ` Konrad Rzeszutek Wilk
2019-08-29 15:29       ` Wieczorkiewicz, Pawel
2019-08-29 15:58     ` Konrad Rzeszutek Wilk
2019-08-29 16:16       ` Wieczorkiewicz, Pawel
2019-08-29 17:49         ` Konrad Rzeszutek Wilk
2019-08-29 19:07           ` Wieczorkiewicz, Pawel
2019-08-29 20:48             ` Konrad Rzeszutek Wilk
2019-09-05 18:05     ` Konrad Rzeszutek Wilk
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 09/12] livepatch: Add support for modules .modinfo section metadata Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 10/12] livepatch: Handle arbitrary size names with the list operation Pawel Wieczorkiewicz
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 11/12] livepatch: Add metadata runtime retrieval mechanism Pawel Wieczorkiewicz
2019-08-29 20:48     ` Konrad Rzeszutek Wilk
2019-08-27  8:46   ` [Xen-devel] [PATCH v2 12/12] livepatch: Add python bindings for livepatch operations Pawel Wieczorkiewicz
2019-08-28 13:21     ` Marek Marczykowski-Górecki
2019-08-29 19:23   ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Konrad Rzeszutek Wilk
2019-09-05 19:13   ` Konrad Rzeszutek Wilk
2019-09-06 22:52     ` Julien Grall
2019-09-06 22:42   ` Julien Grall

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190827084624.116917-8-wipawel@amazon.de \
    --to=wipawel@amazon.de \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=Volodymyr_Babchuk@epam.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=konrad.wilk@oracle.com \
    --cc=mpohlack@amazon.com \
    --cc=roger.pau@citrix.com \
    --cc=ross.lagerwall@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=tim@xen.org \
    --cc=wipawel@amazon.com \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Xen-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/xen-devel/0 xen-devel/git/0.git
	git clone --mirror https://lore.kernel.org/xen-devel/1 xen-devel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 xen-devel xen-devel/ https://lore.kernel.org/xen-devel \
		xen-devel@lists.xenproject.org xen-devel@lists.xen.org
	public-inbox-index xen-devel

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.xenproject.lists.xen-devel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git