xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [Xen-devel] [PATCH 00/14] livepatch: new features and fixes
@ 2019-08-21  8:19 Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 01/14] livepatch: Always check hypervisor build ID upon hotpatch upload Pawel Wieczorkiewicz
                   ` (14 more replies)
  0 siblings, 15 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Marek Marczykowski-Górecki, wipawel, Stefano Stabellini,
	Wei Liu, Konrad Rzeszutek Wilk, George Dunlap, Andrew Cooper,
	Ross Lagerwall, Ian Jackson, mpohlack, Tim Deegan,
	Pawel Wieczorkiewicz, Julien Grall, Jan Beulich,
	Roger Pau Monné

This series introduces new features to the livepatch functionality as
briefly discussed during Xen Developer Summit 2019: [a] and [b].
It also provides a few fixes and some small improvements.

FEATURES:

1. independent modules (patches: [1], [2], [3])

  * livepatch-build-tools repo dependency [A]

  Livepatch enforces the following buildid-based dependency chain
  between hotpatch modules:
    1) first module depends on given hypervisor buildid
    2) every consecutive module depends on previous module's buildid
  This way proper hotpatch stack order is maintained and enforced.
  While it is important for production hotpatches it limits agility and
  blocks usage of testing or debug hotpatches. These kinds of hotpatch
  modules are typically expected to be loaded at any time irrespective
  of current state of the modules stack.

  [A] livepatch-build: Embed hypervisor build id into every hotpatch

2. pre- and post- apply|revert actions hooks (patches: [4], [5])

  * livepatch-build-tools repo dependency [B]

  This is an implementation of 4 new livepatch module vetoing hooks,
  that can be optionally supplied along with modules.
  Hooks that currently exists in the livepatch mechanism aren't agile
  enough and have various limitations:
  * run only from within a quiescing zone
  * cannot conditionally prevent applying or reverting
  * do not have access to the module context
  To address these limitations the following has been implemented:
  1) pre-apply hook
  2) post-apply hook
  3) pre-revert hook
  4) post-revert hook

  [B] create-diff-object: Handle extra pre-|post- hooks

3. apply|revert actions replacement hooks (patches: [6], [7], [9])

  * livepatch-build-tools repo dependency: [C], [D], [E]

  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.

  [C] create-diff-object: Do not create empty .livepatch.funcs section
  [D] create-diff-object: Handle optional apply|revert hooks
  [E] create-diff-object: Add support for applied/reverted marker

4. inline asm hotpatching expectations (patches: [10])

  * livepatch-build-tools repo dependency: [F]

  Expectations are designed as optional feature, since the main use of
  them is planned for inline asm hotpatching.
  The payload structure is modified as each expectation structure is
  part of the livepatch_func structure and hence extends the payload.
  The payload version is bumped to 3 with this change to highlight the
  ABI modification and enforce proper support.
  The expectation is manually enabled during inline asm module
  construction. If enabled, expectation ensures that the expected
  content of memory is to be found at a given patching (old_addr)
  location.

  [F] create-diff-object: Add support for expectations

5. runtime hotpatch metadata support (patches: [11], [12], [13])

  Having detailed hotpatch metadata helps to properly identify module's
  origin and version. It also allows to keep track of the history of
  hotpatch loads in the system (at least within dmesg buffer size
  limits).
  Extend the livepatch list operation to fetch also payloads' metadata.
  This is achieved by extending the sysctl list interface with 2 extra
  guest handles:
  * metadata     - an array of arbitrary size strings
  * metadata_len - an array of metadata strings' lengths (uin32_t each)
  To unify and simplify the interface, handle the modules' name strings
  of arbitrary size by copying them in adhering chunks to the userland.

6. python bindings for livepatch operations (patches: [14])

  Extend the XC python bindings library to support all common livepatch
  operations and actions:
  - status (pyxc_livepatch_status):
  - action (pyxc_livepatch_action):
  - upload (pyxc_livepatch_upload):
  - list (pyxc_livepatch_list):

FIXES:

1. always print XENLOG_ERR information (patches: [8])

[a] https://wiki.xenproject.org/wiki/Design_Sessions_2019#LivePatch_improvements_and_features
[b] https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg00846.html

Pawel Wieczorkiewicz (14):
  [1] livepatch: Always check hypervisor build ID upon hotpatch upload
  [2] livepatch: Allow to override inter-modules buildid dependency
  [3] python: Add XC binding for Xen build ID
  [4] livepatch: Export payload structure via livepatch_payload.h
  [5] livepatch: Implement pre-|post- apply|revert hooks
  [6] livepatch: Add support for apply|revert action replacement hooks
  [7] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence
  [8] livepatch: always print XENLOG_ERR information
  [9] livepatch: Add per-function applied/reverted state tracking marker
  [10] livepatch: Add support for inline asm hotpatching expectations
  [11] livepatch: Add support for modules .modinfo section metadata
  [12] livepatch: Handle arbitrary size names with the list operation
  [13] livepatch: Add metadata runtime retrieval mechanism
  [14] livepatch: Add python bindings for livepatch operations

 .gitignore                          |   1 +
 docs/misc/livepatch.pandoc          |  28 +-
 tools/libxc/include/xenctrl.h       |  68 +++-
 tools/libxc/xc_misc.c               | 162 +++++++--
 tools/misc/xen-livepatch.c          | 258 ++++++++++----
 tools/python/xen/lowlevel/xc/xc.c   | 300 ++++++++++++++++
 xen/arch/x86/livepatch.c            |  36 +-
 xen/common/livepatch.c              | 671 ++++++++++++++++++++++++++++++------
 xen/include/public/sysctl.h         |  63 +++-
 xen/include/xen/livepatch.h         |  17 +-
 xen/include/xen/livepatch_payload.h |  83 +++++
 xen/test/livepatch/Makefile         |  31 +-
 12 files changed, 1444 insertions(+), 274 deletions(-)

-- 
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

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 01/14] livepatch: Always check hypervisor build ID upon hotpatch upload
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` 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
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

This change is part of a independant stacked hotpatch modules
feature. This feature allows to bypass dependencies between modules
upon loading, but still verifies Xen build ID matching.

In order to prevent (up)loading any hotpatches built for different
hypervisor version as indicated by the Xen Build ID, add checking for
the payload's vs Xen's build id match.

To achieve that embed into every hotpatch another section with a
dedicated hypervisor build id in it. After the payload is loaded and
the .livepatch.xen_depends section becomes available, perform the
check and reject the payload if there is no match.

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: Eslam Elnikety <elnikety@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
---
 .gitignore                  |  1 +
 docs/misc/livepatch.pandoc  | 28 +++++++++++++++++++--------
 xen/common/livepatch.c      | 47 +++++++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/livepatch.h |  7 ++++---
 xen/test/livepatch/Makefile | 31 +++++++++++++++++++++++++-----
 5 files changed, 98 insertions(+), 16 deletions(-)

diff --git a/.gitignore b/.gitignore
index 3c947ac948..6f83fc8728 100644
--- a/.gitignore
+++ b/.gitignore
@@ -312,6 +312,7 @@ xen/test/livepatch/xen_bye_world.livepatch
 xen/test/livepatch/xen_hello_world.livepatch
 xen/test/livepatch/xen_nop.livepatch
 xen/test/livepatch/xen_replace_world.livepatch
+xen/test/livepatch/xen_no_xen_buildid.livepatch
 xen/tools/kconfig/.tmp_gtkcheck
 xen/tools/kconfig/.tmp_qtcheck
 xen/tools/symbols
diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index 6d9f72f49b..fd1f5d0126 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -270,6 +270,8 @@ like what the Linux kernel module loader does.
 The payload contains at least three sections:
 
  * `.livepatch.funcs` - which is an array of livepatch_func structures.
+ * `.livepatch.xen_depends` - which is an ELF Note that describes what Xen
+    build-id the payload depends on. **MUST** have one.
  * `.livepatch.depends` - which is an ELF Note that describes what the payload
     depends on. **MUST** have one.
  *  `.note.gnu.build-id` - the build-id of this payload. **MUST** have one.
@@ -383,16 +385,16 @@ The type definition of the function are as follow:
     typedef void (*livepatch_loadcall_t)(void);
     typedef void (*livepatch_unloadcall_t)(void);
 
-### .livepatch.depends and .note.gnu.build-id
+### .livepatch.xen_depends, .livepatch.depends and .note.gnu.build-id
 
 To support dependencies checking and safe loading (to load the
 appropiate payload against the right hypervisor) there is a need
 to embbed an build-id dependency.
 
-This is done by the payload containing an section `.livepatch.depends`
-which follows the format of an ELF Note. The contents of this
-(name, and description) are specific to the linker utilized to
-build the hypevisor and payload.
+This is done by the payload containing sections `.livepatch.xen_depends`
+and `.livepatch.depends` which follow the format of an ELF Note.
+The contents of these (name, and description) are specific to the linker
+utilized to build the hypevisor and payload.
 
 If GNU linker is used then the name is `GNU` and the description
 is a NT_GNU_BUILD_ID type ID. The description can be an SHA1
@@ -400,6 +402,13 @@ checksum, MD5 checksum or any unique value.
 
 The size of these structures varies with the `--build-id` linker option.
 
+There are two kinds of build-id dependencies:
+
+ * Xen build-id dependency (.livepatch.xen_depends section)
+ * previous payload build-id dependency (.livepatch.depends section)
+
+See "Live patch interdependencies" for more information.
+
 ## Hypercalls
 
 We will employ the sub operations of the system management hypercall (sysctl).
@@ -894,13 +903,16 @@ but is more complex to implement.
 The second option which requires an build-id of the hypervisor
 is implemented in the Xen hypervisor.
 
-Specifically each payload has two build-id ELF notes:
+Specifically each payload has three build-id ELF notes:
  * The build-id of the payload itself (generated via --build-id).
+ * The build-id of the Xen hypervisor it depends on (extracted from the
+   hypervisor during build time).
  * The build-id of the payload it depends on (extracted from the
    the previous payload or hypervisor during build time).
 
-This means that the very first payload depends on the hypervisor
-build-id.
+This means that every payload depends on the hypervisor build-id and on
+the build-id of the previous payload in the stack.
+The very first payload depends on the hypervisor build-id only.
 
 # Not Yet Done
 
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index d6eaae6d3b..6a4af6ce57 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -74,6 +74,7 @@ struct payload {
     unsigned int nsyms;                  /* Nr of entries in .strtab and symbols. */
     struct livepatch_build_id id;        /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */
     struct livepatch_build_id dep;       /* ELFNOTE_DESC(.livepatch.depends). */
+    struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
     livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
     livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
     unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
@@ -476,11 +477,34 @@ static bool section_ok(const struct livepatch_elf *elf,
     return true;
 }
 
+static int check_xen_build_id(const struct payload *payload)
+{
+    const void *id = NULL;
+    unsigned int len = 0;
+    int rc;
+
+    ASSERT(payload->xen_dep.len);
+    ASSERT(payload->xen_dep.p);
+
+    rc = xen_build_id(&id, &len);
+    if ( rc )
+        return rc;
+
+    if ( payload->xen_dep.len != len || memcmp(id, payload->xen_dep.p, len) ) {
+        dprintk(XENLOG_ERR, "%s%s: check against hypervisor build-id failed!\n",
+                LIVEPATCH, payload->name);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 static int check_special_sections(const struct livepatch_elf *elf)
 {
     unsigned int i;
     static const char *const names[] = { ELF_LIVEPATCH_FUNC,
                                          ELF_LIVEPATCH_DEPENDS,
+                                         ELF_LIVEPATCH_XEN_DEPENDS,
                                          ELF_BUILD_ID_NOTE};
     DECLARE_BITMAP(found, ARRAY_SIZE(names)) = { 0 };
 
@@ -632,6 +656,22 @@ static int prepare_payload(struct payload *payload,
             return -EINVAL;
     }
 
+    sec = livepatch_elf_sec_by_name(elf, ELF_LIVEPATCH_XEN_DEPENDS);
+    if ( sec )
+    {
+        n = sec->load_addr;
+
+        if ( sec->sec->sh_size <= sizeof(*n) )
+            return -EINVAL;
+
+        if ( xen_build_id_check(n, sec->sec->sh_size,
+                                &payload->xen_dep.p, &payload->xen_dep.len) )
+            return -EINVAL;
+
+        if ( !payload->xen_dep.len || !payload->xen_dep.p )
+            return -EINVAL;
+    }
+
     /* Setup the virtual region with proper data. */
     region = &payload->region;
 
@@ -882,6 +922,10 @@ static int load_payload_data(struct payload *payload, void *raw, size_t len)
     if ( rc )
         goto out;
 
+    rc = check_xen_build_id(payload);
+    if ( rc )
+        goto out;
+
     rc = build_symbol_table(payload, &elf);
     if ( rc )
         goto out;
@@ -1655,6 +1699,9 @@ static void livepatch_printall(unsigned char key)
 
         if ( data->dep.len )
             printk("depend-on=%*phN\n", data->dep.len, data->dep.p);
+
+        if ( data->xen_dep.len )
+            printk("depend-on-xen=%*phN\n", data->xen_dep.len, data->xen_dep.p);
     }
 
     spin_unlock(&payload_lock);
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index 1b1817ca0d..ed997aa4cc 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -29,9 +29,10 @@ struct xen_sysctl_livepatch_op;
 /* Convenience define for printk. */
 #define LIVEPATCH             "livepatch: "
 /* ELF payload special section names. */
-#define ELF_LIVEPATCH_FUNC    ".livepatch.funcs"
-#define ELF_LIVEPATCH_DEPENDS ".livepatch.depends"
-#define ELF_BUILD_ID_NOTE      ".note.gnu.build-id"
+#define ELF_LIVEPATCH_FUNC        ".livepatch.funcs"
+#define ELF_LIVEPATCH_DEPENDS     ".livepatch.depends"
+#define ELF_LIVEPATCH_XEN_DEPENDS ".livepatch.xen_depends"
+#define ELF_BUILD_ID_NOTE         ".note.gnu.build-id"
 /* Arbitrary limit for payload size and .bss section size. */
 #define LIVEPATCH_MAX_SIZE     MB(2)
 
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 6831383db1..fdb82782d2 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -19,11 +19,13 @@ LIVEPATCH := xen_hello_world.livepatch
 LIVEPATCH_BYE := xen_bye_world.livepatch
 LIVEPATCH_REPLACE := xen_replace_world.livepatch
 LIVEPATCH_NOP := xen_nop.livepatch
+LIVEPATCH_NO_XEN_BUILDID := xen_no_xen_buildid.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
 LIVEPATCHES += $(LIVEPATCH_REPLACE)
 LIVEPATCHES += $(LIVEPATCH_NOP)
+LIVEPATCHES += $(LIVEPATCH_NO_XEN_BUILDID)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -59,7 +61,7 @@ config.h: xen_hello_world_func.o
 xen_hello_world.o: config.h
 
 .PHONY: $(LIVEPATCH)
-$(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
+$(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH) $^
 
 #
@@ -78,6 +80,17 @@ note.o:
 		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
 	rm -f $@.bin
 
+#
+# Append .livepatch.xen_depends section
+# with Xen build-id derived from xen-syms.
+#
+.PHONY: xen_note.o
+xen_note.o:
+	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
+	$(OBJCOPY) $(OBJCOPY_MAGIC) \
+		   --rename-section=.data=.livepatch.xen_depends,alloc,load,readonly,data,contents -S $@.bin $@
+	rm -f $@.bin
+
 #
 # Extract the build-id of the xen_hello_world.livepatch
 # (which xen_bye_world will depend on).
@@ -92,20 +105,28 @@ hello_world_note.o: $(LIVEPATCH)
 xen_bye_world.o: config.h
 
 .PHONY: $(LIVEPATCH_BYE)
-$(LIVEPATCH_BYE): xen_bye_world_func.o xen_bye_world.o hello_world_note.o
+$(LIVEPATCH_BYE): xen_bye_world_func.o xen_bye_world.o hello_world_note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_BYE) $^
 
 xen_replace_world.o: config.h
 
 .PHONY: $(LIVEPATCH_REPLACE)
-$(LIVEPATCH_REPLACE): xen_replace_world_func.o xen_replace_world.o note.o
+$(LIVEPATCH_REPLACE): xen_replace_world_func.o xen_replace_world.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_REPLACE) $^
 
 xen_nop.o: config.h
 
 .PHONY: $(LIVEPATCH_NOP)
-$(LIVEPATCH_NOP): xen_nop.o note.o
+$(LIVEPATCH_NOP): xen_nop.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NOP) $^
 
+# This one always fails upon upload, because it deliberetely
+# does not have a .livepatch.xen_depends (xen_note.o) section.
+xen_no_xen_buildid.o: config.h
+
+.PHONY: $(LIVEPATCH_NO_XEN_BUILDID)
+$(LIVEPATCH_NO_XEN_BUILDID): xen_nop.o note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NO_XEN_BUILDID) $^
+
 .PHONY: livepatch
-livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP)
+livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID)
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 02/14] livepatch: Allow to override inter-modules buildid dependency
  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  8:19 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 03/14] python: Add XC binding for Xen build ID Pawel Wieczorkiewicz
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

By default Livepatch enforces the following buildid-based dependency
chain between hotpatch modules:
  1) first module depends on given hypervisor buildid
  2) every consecutive module depends on previous module's buildid
This way proper hotpatch stack order is maintained and enforced.
While it is important for production hotpatches it limits agility and
blocks usage of testing or debug hotpatches. These kinds of hotpatch
modules are typically expected to be loaded at any time irrespective
of current state of the modules stack.

To enable testing and debug hotpatches allow user dynamically ignore
the inter-modules dependency. In this case only hypervisor buildid
match is verified and enforced.

To allow userland pass additional paremeters for livepatch actions
add support for action flags.
Each of the apply, revert, unload and revert action gets additional
64-bit parameter 'flags' where extra flags can be applied in a mask
form.
Initially only one flag '--nodeps' is added for the apply action.
This flag modifies the default buildid dependency check as described
above.
The global sysctl interface input flag parameter is defined with a
single corresponding flag macro:
  LIVEPATCH_ACTION_APPLY_NODEPS (1 << 0)

The userland xen-livepatch tool is modified to support the '--nodeps'
flag for apply and load commands. A general mechanism for specifying
more flags in the future for apply and other action is however added.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Eslam Elnikety <elnikety@amazon.de>
Reviewed-by: Petre Eftime <epetre@amazon.com>
Reviewed-by: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 tools/libxc/include/xenctrl.h |   9 ++--
 tools/libxc/xc_misc.c         |  20 +++----
 tools/misc/xen-livepatch.c    | 121 +++++++++++++++++++++++++++++++++++-------
 xen/common/livepatch.c        |  14 +++--
 xen/include/public/sysctl.h   |  11 +++-
 5 files changed, 139 insertions(+), 36 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 0ff6ed9e70..725697c132 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2607,11 +2607,12 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
  * to complete them. The `timeout` offers an option to expire the
  * operation if it could not be completed within the specified time
  * (in ns). Value of 0 means let hypervisor decide the best timeout.
+ * The `flags` allows to pass extra parameters to the actions.
  */
-int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout);
-int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout);
-int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout);
-int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout);
+int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
 
 /*
  * Ensure cache coherency after memory modifications. A call to this function
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 8e60b6e9f0..a8e9e7d1e2 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -854,7 +854,8 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
 static int _xc_livepatch_action(xc_interface *xch,
                                 char *name,
                                 unsigned int action,
-                                uint32_t timeout)
+                                uint32_t timeout,
+                                uint64_t flags)
 {
     int rc;
     DECLARE_SYSCTL;
@@ -880,6 +881,7 @@ static int _xc_livepatch_action(xc_interface *xch,
     sysctl.u.livepatch.pad = 0;
     sysctl.u.livepatch.u.action.cmd = action;
     sysctl.u.livepatch.u.action.timeout = timeout;
+    sysctl.u.livepatch.u.action.flags = flags;
 
     sysctl.u.livepatch.u.action.name = def_name;
     set_xen_guest_handle(sysctl.u.livepatch.u.action.name.name, name);
@@ -891,24 +893,24 @@ static int _xc_livepatch_action(xc_interface *xch,
     return rc;
 }
 
-int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_APPLY, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_APPLY, timeout, flags);
 }
 
-int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REVERT, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REVERT, timeout, flags);
 }
 
-int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_UNLOAD, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_UNLOAD, timeout, flags);
 }
 
-int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REPLACE, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REPLACE, timeout, flags);
 }
 
 /*
diff --git a/tools/misc/xen-livepatch.c b/tools/misc/xen-livepatch.c
index 3233472157..a37b2457ff 100644
--- a/tools/misc/xen-livepatch.c
+++ b/tools/misc/xen-livepatch.c
@@ -23,18 +23,23 @@ void show_help(void)
 {
     fprintf(stderr,
             "xen-livepatch: live patching tool\n"
-            "Usage: xen-livepatch <command> [args]\n"
+            "Usage: xen-livepatch <command> [args] [command-flags]\n"
             " <name> An unique name of payload. Up to %d characters.\n"
             "Commands:\n"
             "  help                   display this help\n"
             "  upload <name> <file>   upload file <file> with <name> name\n"
             "  list                   list payloads uploaded.\n"
-            "  apply <name>           apply <name> patch.\n"
+            "  apply <name> [flags]   apply <name> patch.\n"
+            "    Supported flags:\n"
+            "      --nodeps           Disable inter-module buildid dependency check.\n"
+            "                         Check only against hypervisor buildid.\n"
             "  revert <name>          revert name <name> patch.\n"
             "  replace <name>         apply <name> patch and revert all others.\n"
             "  unload <name>          unload name <name> patch.\n"
-            "  load  <file>           upload and apply <file>.\n"
-            "                         name is the <file> name\n",
+            "  load <file> [flags]    upload and apply <file> with name as the <file> name\n"
+            "    Supported flags:\n"
+            "      --nodeps           Disable inter-module buildid dependency check.\n"
+            "                         Check only against hypervisor buildid.\n",
             XEN_LIVEPATCH_NAME_SIZE);
 }
 
@@ -225,12 +230,13 @@ static int upload_func(int argc, char *argv[])
     return rc;
 }
 
-/* These MUST match to the 'action_options[]' array slots. */
+/* These MUST match to the 'action_options[]' and 'flag_options[]' array slots. */
 enum {
     ACTION_APPLY = 0,
     ACTION_REVERT = 1,
     ACTION_UNLOAD = 2,
     ACTION_REPLACE = 3,
+    ACTION_NUM
 };
 
 struct {
@@ -238,7 +244,7 @@ struct {
     int expected; /* The state to be in after the function. */
     const char *name;
     const char *verb;
-    int (*function)(xc_interface *xch, char *name, uint32_t timeout);
+    int (*function)(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
 } action_options[] = {
     {   .allow = LIVEPATCH_STATE_CHECKED,
         .expected = LIVEPATCH_STATE_APPLIED,
@@ -266,6 +272,66 @@ struct {
     },
 };
 
+/*
+ * This structure defines supported flag options for actions.
+ * It defines entries for each action and supports up to 64
+ * flags per action.
+ */
+struct {
+    const char *name;
+    const uint64_t flag;
+} flag_options[ACTION_NUM][8 * sizeof(uint64_t)] = {
+    { /* ACTION_APPLY */
+        {   .name = "--nodeps",
+            .flag = LIVEPATCH_ACTION_APPLY_NODEPS,
+        },
+    },
+    { /* ACTION_REVERT */
+    },
+    { /* ACTION_UNLOAD */
+    },
+    { /* ACTION_REPLACE */
+    }
+};
+
+/*
+ * Parse user provided action flags.
+ * This function expects to only receive an array of input parameters being flags.
+ * Expected action is specified via idx paramater (index of flag_options[]).
+ */
+static int get_flags(int argc, char *argv[], unsigned int idx, uint64_t *flags)
+{
+    int i, j;
+
+    if ( !flags || idx >= ARRAY_SIZE(flag_options) )
+        return -1;
+
+    *flags = 0;
+    for ( i = 0; i < argc; i++ )
+    {
+        for ( j = 0; j < ARRAY_SIZE(flag_options[idx]); j++ )
+        {
+            if ( !flag_options[idx][j].name )
+                goto error;
+
+            if ( !strcmp(flag_options[idx][j].name, argv[i]) )
+            {
+                *flags |= flag_options[idx][j].flag;
+                break;
+            }
+        }
+
+        if ( j == ARRAY_SIZE(flag_options[idx]) )
+            goto error;
+    }
+
+    return 0;
+error:
+    fprintf(stderr, "Unsupported flag: %s.\n", argv[i]);
+    errno = EINVAL;
+    return errno;
+}
+
 /* The hypervisor timeout for the live patching operation is 30 msec,
  * but it could take some time for the operation to start, so wait twice
  * that period. */
@@ -291,8 +357,9 @@ int action_func(int argc, char *argv[], unsigned int idx)
     char name[XEN_LIVEPATCH_NAME_SIZE];
     int rc;
     xen_livepatch_status_t status;
+    uint64_t flags;
 
-    if ( argc != 1 )
+    if ( argc < 1 )
     {
         show_help();
         return -1;
@@ -301,7 +368,10 @@ int action_func(int argc, char *argv[], unsigned int idx)
     if ( idx >= ARRAY_SIZE(action_options) )
         return -1;
 
-    if ( get_name(argc, argv, name) )
+    if ( get_name(argc--, argv++, name) )
+        return EINVAL;
+
+    if ( get_flags(argc, argv, idx, &flags) )
         return EINVAL;
 
     /* Check initial status. */
@@ -332,7 +402,7 @@ int action_func(int argc, char *argv[], unsigned int idx)
     if ( action_options[idx].allow & status.state )
     {
         printf("%s %s... ", action_options[idx].verb, name);
-        rc = action_options[idx].function(xch, name, HYPERVISOR_TIMEOUT_NS);
+        rc = action_options[idx].function(xch, name, HYPERVISOR_TIMEOUT_NS, flags);
         if ( rc )
         {
             int saved_errno = errno;
@@ -394,17 +464,23 @@ int action_func(int argc, char *argv[], unsigned int idx)
 
 static int load_func(int argc, char *argv[])
 {
-    int rc;
-    char *new_argv[2];
-    char *path, *name, *lastdot;
+    int i, rc = ENOMEM;
+    char *upload_argv[2];
+    char **apply_argv, *path, *name, *lastdot;
 
-    if ( argc != 1 )
+    if ( argc < 1 )
     {
         show_help();
         return -1;
     }
+
+    /* apply action has <id> [flags] input requirement, which must be constructed */
+    apply_argv = (char **) malloc(argc * sizeof(*apply_argv));
+    if ( !apply_argv )
+        return rc;
+
     /* <file> */
-    new_argv[1] = argv[0];
+    upload_argv[1] = argv[0];
 
     /* Synthesize the <id> */
     path = strdup(argv[0]);
@@ -413,16 +489,23 @@ static int load_func(int argc, char *argv[])
     lastdot = strrchr(name, '.');
     if ( lastdot != NULL )
         *lastdot = '\0';
-    new_argv[0] = name;
+    upload_argv[0] = name;
+    apply_argv[0] = name;
 
-    rc = upload_func(2 /* <id> <file> */, new_argv);
+    /* Fill in all user provided flags */
+    for ( i = 0; i < argc - 1; i++ )
+        apply_argv[i + 1] = argv[i + 1];
+
+    rc = upload_func(2 /* <id> <file> */, upload_argv);
     if ( rc )
-        return rc;
+        goto error;
 
-    rc = action_func(1 /* only <id> */, new_argv, ACTION_APPLY);
+    rc = action_func(argc, apply_argv, ACTION_APPLY);
     if ( rc )
-        action_func(1, new_argv, ACTION_UNLOAD);
+        action_func(1 /* only <id> */, upload_argv, ACTION_UNLOAD);
 
+error:
+    free(apply_argv);
     free(path);
     return rc;
 }
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 6a4af6ce57..fb91d5095c 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1575,9 +1575,17 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                 break;
             }
 
-            rc = build_id_dep(data, !!list_empty(&applied_list));
-            if ( rc )
-                break;
+            /*
+             * Check if action is issued with nodeps flags to ignore module
+             * stack dependencies.
+             */
+            if ( !(action->flags & LIVEPATCH_ACTION_APPLY_NODEPS) )
+            {
+                rc = build_id_dep(data, !!list_empty(&applied_list));
+                if ( rc )
+                    break;
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 91c48dcae0..1b2b165a6d 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -35,7 +35,7 @@
 #include "domctl.h"
 #include "physdev.h"
 
-#define XEN_SYSCTL_INTERFACE_VERSION 0x00000012
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000013
 
 /*
  * Read console content from Xen buffer ring.
@@ -956,6 +956,15 @@ struct xen_sysctl_livepatch_action {
                                             /* hypervisor default. */
                                             /* Or upper bound of time (ns) */
                                             /* for operation to take. */
+
+/*
+ * Overwrite default inter-module buildid dependency chain enforcement.
+ * Check only if module is built for given hypervisor by comparing buildid.
+ */
+#define LIVEPATCH_ACTION_APPLY_NODEPS (1 << 0)
+    uint64_t flags;                         /* IN: action flags. */
+                                            /* Provide additional parameters */
+                                            /* for an action. */
 };
 
 struct xen_sysctl_livepatch_op {
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 03/14] python: Add XC binding for Xen build ID
  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  8:19 ` [Xen-devel] [PATCH 02/14] livepatch: Allow to override inter-modules buildid dependency Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 04/14] livepatch: Export payload structure via livepatch_payload.h Pawel Wieczorkiewicz
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Wei Liu, Ian Jackson, mpohlack,
	Marek Marczykowski-Górecki, Pawel Wieczorkiewicz

Extend the list of xc() object methods with additional one to display
Xen's buildid. The implementation follows the libxl implementation
(e.g. max buildid size assumption being XC_PAGE_SIZE minus
sizeof(buildid->len)).

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Martin Mazein <amazein@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
 tools/python/xen/lowlevel/xc/xc.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 188bfa34da..7f0358ba9c 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -1214,6 +1214,26 @@ out:
     return ret_obj ? ret_obj : pyxc_error_to_exception(self->xc_handle);
 }
 
+static PyObject *pyxc_xenbuildid(XcObject *self)
+{
+    xen_build_id_t *buildid;
+    int i, r;
+    char *str;
+
+    buildid = alloca(XC_PAGE_SIZE);
+    buildid->len = XC_PAGE_SIZE - sizeof(*buildid);
+
+    r = xc_version(self->xc_handle, XENVER_build_id, buildid);
+    if ( r <= 0 )
+        return pyxc_error_to_exception(self->xc_handle);
+
+    str = alloca((r * 2) + 1);
+    for ( i = 0; i < r; i++ )
+        snprintf(&str[i * 2], 3, "%02hhx", buildid->buf[i]);
+
+    return Py_BuildValue("s", str);
+}
+
 static PyObject *pyxc_xeninfo(XcObject *self)
 {
     xen_extraversion_t xen_extra;
@@ -2297,6 +2317,13 @@ static PyMethodDef pyxc_methods[] = {
       "Returns [dict]: information about Xen"
       "        [None]: on failure.\n" },
 
+    { "buildid",
+      (PyCFunction)pyxc_xenbuildid,
+      METH_NOARGS, "\n"
+      "Get Xen buildid\n"
+      "Returns [str]: Xen buildid"
+      "        [None]: on failure.\n" },
+
     { "shadow_control", 
       (PyCFunction)pyxc_shadow_control, 
       METH_VARARGS | METH_KEYWORDS, "\n"
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 04/14] livepatch: Export payload structure via livepatch_payload.h
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (2 preceding siblings ...)
  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 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 05/14] livepatch: Implement pre-|post- apply|revert hooks Pawel Wieczorkiewicz
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

The payload structure will be used by the new hooks implementation and
therefore its definition has to be exported via the livepatch_payload
header.
The new hooks will make use of the payload structure fields and the
hooks' pointers will also be defined in the payload structure, so
the structure along with all field definitions needs to be available
to the code being patched in.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Eslam Elnikety <elnikety@amazon.de>
Reviewed-by: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 xen/common/livepatch.c              | 37 ----------------------------------
 xen/include/xen/livepatch_payload.h | 40 +++++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index fb91d5095c..ed5756a032 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -45,43 +45,6 @@ static LIST_HEAD(applied_list);
 static unsigned int payload_cnt;
 static unsigned int payload_version = 1;
 
-/* To contain the ELF Note header. */
-struct livepatch_build_id {
-   const void *p;
-   unsigned int len;
-};
-
-struct payload {
-    uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
-    int32_t rc;                          /* 0 or -XEN_EXX. */
-    bool reverted;                       /* Whether it was reverted. */
-    bool safe_to_reapply;                /* Can apply safely after revert. */
-    struct list_head list;               /* Linked to 'payload_list'. */
-    const void *text_addr;               /* Virtual address of .text. */
-    size_t text_size;                    /* .. and its size. */
-    const void *rw_addr;                 /* Virtual address of .data. */
-    size_t rw_size;                      /* .. and its size (if any). */
-    const void *ro_addr;                 /* Virtual address of .rodata. */
-    size_t ro_size;                      /* .. and its size (if any). */
-    unsigned int pages;                  /* Total pages for [text,rw,ro]_addr */
-    struct list_head applied_list;       /* Linked to 'applied_list'. */
-    struct livepatch_func *funcs;        /* The array of functions to patch. */
-    unsigned int nfuncs;                 /* Nr of functions to patch. */
-    const struct livepatch_symbol *symtab; /* All symbols. */
-    const char *strtab;                  /* Pointer to .strtab. */
-    struct virtual_region region;        /* symbol, bug.frame patching and
-                                            exception table (x86). */
-    unsigned int nsyms;                  /* Nr of entries in .strtab and symbols. */
-    struct livepatch_build_id id;        /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */
-    struct livepatch_build_id dep;       /* ELFNOTE_DESC(.livepatch.depends). */
-    struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
-    livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
-    livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
-    unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
-    unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
-    char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
-};
-
 /* Defines an outstanding patching action. */
 struct livepatch_work
 {
diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h
index 4a1a96d054..99613af2db 100644
--- a/xen/include/xen/livepatch_payload.h
+++ b/xen/include/xen/livepatch_payload.h
@@ -4,6 +4,15 @@
 
 #ifndef __XEN_LIVEPATCH_PAYLOAD_H__
 #define __XEN_LIVEPATCH_PAYLOAD_H__
+#include <xen/virtual_region.h>
+
+/* To contain the ELF Note header. */
+struct livepatch_build_id {
+   const void *p;
+   unsigned int len;
+};
+
+typedef struct payload livepatch_payload_t;
 
 /*
  * The following definitions are to be used in patches. They are taken
@@ -12,6 +21,37 @@
 typedef void livepatch_loadcall_t(void);
 typedef void livepatch_unloadcall_t(void);
 
+struct payload {
+    uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
+    int32_t rc;                          /* 0 or -XEN_EXX. */
+    bool reverted;                       /* Whether it was reverted. */
+    bool safe_to_reapply;                /* Can apply safely after revert. */
+    struct list_head list;               /* Linked to 'payload_list'. */
+    const void *text_addr;               /* Virtual address of .text. */
+    size_t text_size;                    /* .. and its size. */
+    const void *rw_addr;                 /* Virtual address of .data. */
+    size_t rw_size;                      /* .. and its size (if any). */
+    const void *ro_addr;                 /* Virtual address of .rodata. */
+    size_t ro_size;                      /* .. and its size (if any). */
+    unsigned int pages;                  /* Total pages for [text,rw,ro]_addr */
+    struct list_head applied_list;       /* Linked to 'applied_list'. */
+    struct livepatch_func *funcs;        /* The array of functions to patch. */
+    unsigned int nfuncs;                 /* Nr of functions to patch. */
+    const struct livepatch_symbol *symtab; /* All symbols. */
+    const char *strtab;                  /* Pointer to .strtab. */
+    struct virtual_region region;        /* symbol, bug.frame patching and
+                                            exception table (x86). */
+    unsigned int nsyms;                  /* Nr of entries in .strtab and symbols. */
+    struct livepatch_build_id id;        /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */
+    struct livepatch_build_id dep;       /* ELFNOTE_DESC(.livepatch.depends). */
+    struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
+    livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
+    livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
+    unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
+    unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
+    char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
+};
+
 /*
  * LIVEPATCH_LOAD_HOOK macro
  *
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 05/14] livepatch: Implement pre-|post- apply|revert hooks
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (3 preceding siblings ...)
  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 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks Pawel Wieczorkiewicz
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

This is an implementation of 4 new livepatch module vetoing hooks,
that can be optionally supplied along with modules.
Hooks that currently exists in the livepatch mechanism aren't agile
enough and have various limitations:
* run only from within a quiescing zone
* cannot conditionally prevent applying or reverting
* do not have access to the module context
To address these limitations the following has been implemented:
1) pre-apply hook
  runs before the apply action is scheduled for execution. Its main
  purpose is to prevent from applying a hotpatch when certain
  expected conditions aren't met or when mutating actions implemented
  in the hook fail or cannot be executed.

2) post-apply hook
  runs after the apply action has been executed and quiescing zone
  exited. Its main purpose is to provide an ability to follow-up on
  actions performed by the pre- hook, when module application was
  successful or undo certain preparation steps of the pre- hook in
  case of a failure. The success/failure error code is proviVded to
  the post- hooks via the rc field of the payload structure.

3) pre-revert hook
  runs before the revert action is scheduled for execution. Its main
  purpose is to prevent from reverting a hotpatch when certain
  expected conditions aren't met or when mutating actions implemented
  in the hook fail or cannot be executed.

4) post-revert hook
  runs after the revert action has been executed and quiescing zone
  exited. Its main purpose is to perform cleanup of all previously
  executed mutating actions in order to restore the original system
  state from before the current module application.
  The success/failure error code is provided to the post- hooks via
  the rc field of the payload structure.

The replace action performs atomically the following actions:
- revert all applied modules
- apply a single replacement module.
With the vetoing hooks in place various inter-hook dependencies may
arise. Also, during the revert part of the operation certain vetoing
hooks may detect failing conditions that previously were satisfied.
That could in turn lead to situation when the revert part must be
rolled back with all the pre- and post- hooks re-applied, which again
can't be guaranteed to always succeed.
The simplest response to this complication is to disallow the replace
action completely on modules with vetoing hooks.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Petre Eftime <epetre@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 xen/common/livepatch.c              | 179 ++++++++++++++++++++++++++++++++----
 xen/include/xen/livepatch_payload.h |  27 ++++++
 2 files changed, 189 insertions(+), 17 deletions(-)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index ed5756a032..464c07ad28 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -28,6 +28,8 @@
 #include <asm/alternative.h>
 #include <asm/event.h>
 
+#define is_hook_enabled(hook) ({ (hook) && *(hook); })
+
 /*
  * Protects against payload_list operations and also allows only one
  * caller in schedule_work.
@@ -501,6 +503,35 @@ static int check_special_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+/*
+ * Lookup specified section and when exists assign its address to a specified hook.
+ * Perform section pointer and size validation: single hook sections must contain a
+ * single pointer only.
+ */
+#define LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, hook, section_name) do {                        \
+    const struct livepatch_elf_sec *__sec = livepatch_elf_sec_by_name(elf, section_name); \
+    if ( !__sec )                                                                         \
+        break;                                                                            \
+    if ( !section_ok(elf, __sec, sizeof(*hook)) || __sec->sec->sh_size != sizeof(*hook) ) \
+        return -EINVAL;                                                                   \
+    hook = __sec->load_addr;                                                              \
+} while (0)
+
+/*
+ * Lookup specified section and when exists assign its address to a specified hook.
+ * Perform section pointer and size validation: multi hook sections must contain an
+ * array whose size must be a multiple of the array's items size.
+ */
+#define LIVEPATCH_ASSIGN_MULTI_HOOK(elf, hook, nhooks, section_name) do {                 \
+    const struct livepatch_elf_sec *__sec = livepatch_elf_sec_by_name(elf, section_name); \
+    if ( !__sec )                                                                         \
+        break;                                                                            \
+    if ( !section_ok(elf, __sec, sizeof(*hook)) )                                         \
+        return -EINVAL;                                                                   \
+    hook = __sec->load_addr;                                                              \
+    nhooks = __sec->sec->sh_size / sizeof(*hook);                                         \
+} while (0)
+
 static int prepare_payload(struct payload *payload,
                            struct livepatch_elf *elf)
 {
@@ -552,25 +583,14 @@ static int prepare_payload(struct payload *payload,
             return rc;
     }
 
-    sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.load");
-    if ( sec )
-    {
-        if ( !section_ok(elf, sec, sizeof(*payload->load_funcs)) )
-            return -EINVAL;
-
-        payload->load_funcs = sec->load_addr;
-        payload->n_load_funcs = sec->sec->sh_size / sizeof(*payload->load_funcs);
-    }
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->load_funcs, payload->n_load_funcs, ".livepatch.hooks.load");
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ".livepatch.hooks.unload");
 
-    sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.unload");
-    if ( sec )
-    {
-        if ( !section_ok(elf, sec, sizeof(*payload->unload_funcs)) )
-            return -EINVAL;
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.pre, ".livepatch.hooks.preapply");
+    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.post, ".livepatch.hooks.postrevert");
 
-        payload->unload_funcs = sec->load_addr;
-        payload->n_unload_funcs = sec->sec->sh_size / sizeof(*payload->unload_funcs);
-    }
     sec = livepatch_elf_sec_by_name(elf, ELF_BUILD_ID_NOTE);
     if ( sec )
     {
@@ -1217,6 +1237,39 @@ static bool_t is_work_scheduled(const struct payload *data)
     return livepatch_work.do_work && livepatch_work.data == data;
 }
 
+/*
+ * Check if payload has any of the vetoing, non-atomic hooks assigned.
+ * A vetoing, non-atmic hook may perform an operation that changes the
+ * hypervisor state and may not be guaranteed to succeed. Result of
+ * such operation may be returned and may change the livepatch workflow.
+ * Such hooks may require additional cleanup actions performed by other
+ * hooks. Thus they are not suitable for replace action.
+ */
+static inline bool_t has_payload_any_vetoing_hooks(const struct payload *payload)
+{
+    return is_hook_enabled(payload->hooks.apply.pre) ||
+           is_hook_enabled(payload->hooks.apply.post) ||
+           is_hook_enabled(payload->hooks.revert.pre) ||
+           is_hook_enabled(payload->hooks.revert.post);
+}
+
+/*
+ * Checks if any of the already applied hotpatches has any vetoing,
+ * non-atomic hooks assigned.
+ */
+static inline bool_t livepatch_applied_have_vetoing_hooks(void)
+{
+    struct payload *p;
+
+    list_for_each_entry ( p, &applied_list, applied_list )
+    {
+        if ( has_payload_any_vetoing_hooks(p) )
+            return true;
+    }
+
+    return false;
+}
+
 static int schedule_work(struct payload *data, uint32_t cmd, uint32_t timeout)
 {
     ASSERT(spin_is_locked(&payload_lock));
@@ -1317,6 +1370,7 @@ void check_for_livepatch_work(void)
     {
         struct payload *p;
         unsigned int cpus;
+        bool_t action_done = false;
 
         p = livepatch_work.data;
         if ( !get_cpu_maps() )
@@ -1369,6 +1423,7 @@ void check_for_livepatch_work(void)
             livepatch_do_action();
             /* Serialize and flush out the CPU via CPUID instruction (on x86). */
             arch_livepatch_post_action();
+            action_done = true;
             local_irq_restore(flags);
         }
 
@@ -1381,6 +1436,43 @@ void check_for_livepatch_work(void)
         /* put_cpu_maps has an barrier(). */
         put_cpu_maps();
 
+        if ( action_done )
+        {
+            switch ( livepatch_work.cmd )
+            {
+            case LIVEPATCH_ACTION_REVERT:
+                if ( is_hook_enabled(p->hooks.revert.post) )
+                {
+                    printk(XENLOG_INFO LIVEPATCH "%s: Calling post-revert hook function with rc=%d\n",
+                           p->name, p->rc);
+
+                    (*p->hooks.revert.post)(p);
+                }
+                break;
+
+            case LIVEPATCH_ACTION_APPLY:
+                if ( is_hook_enabled(p->hooks.apply.post) )
+                {
+                    printk(XENLOG_INFO LIVEPATCH "%s: Calling post-apply hook function with rc=%d\n",
+                           p->name, p->rc);
+
+                    (*p->hooks.apply.post)(p);
+                }
+                break;
+
+            case LIVEPATCH_ACTION_REPLACE:
+                if ( has_payload_any_vetoing_hooks(p) )
+                {
+                    /* It should be impossible to get here since livepatch_action() guards against that. */
+                    panic(LIVEPATCH "%s: REPLACE action is not supported on hotpatches with vetoing hooks!\n",
+                            p->name);
+                    ASSERT_UNREACHABLE();
+                }
+            default:
+                break;
+            }
+        }
+
         printk(XENLOG_INFO LIVEPATCH "%s finished %s with rc=%d\n",
                p->name, names[livepatch_work.cmd], p->rc);
     }
@@ -1516,6 +1608,21 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                 rc = -EBUSY;
                 break;
             }
+
+            if ( is_hook_enabled(data->hooks.revert.pre) )
+            {
+                printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-revert hook function\n", data->name);
+
+                rc = (*data->hooks.revert.pre)(data);
+                if ( rc )
+                {
+                    printk(XENLOG_ERR LIVEPATCH "%s: pre-revert hook failed (rc=%d), aborting!\n",
+                           data->name, rc);
+                    data->rc = rc;
+                    break;
+                }
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
@@ -1549,6 +1656,20 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                     break;
             }
 
+            if ( is_hook_enabled(data->hooks.apply.pre) )
+            {
+                printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-apply hook function\n", data->name);
+
+                rc = (*data->hooks.apply.pre)(data);
+                if ( rc )
+                {
+                    printk(XENLOG_ERR LIVEPATCH "%s: pre-apply hook failed (rc=%d), aborting!\n",
+                           data->name, rc);
+                    data->rc = rc;
+                    break;
+                }
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
@@ -1560,6 +1681,30 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
             rc = build_id_dep(data, 1 /* against hypervisor. */);
             if ( rc )
                 break;
+
+            /*
+             * REPLACE action is not supported on hotpatches with vetoing hooks.
+             * Vetoing hooks usually perform mutating actions on the system and
+             * typically exist in pairs (pre- hook doing an action and post- hook
+             * undoing the action). Coalescing all hooks from all applied modules
+             * cannot be performed without inspecting potential dependencies between
+             * the mutating hooks and hence cannot be performed automatically by
+             * the replace action. Also, the replace action cannot safely assume a
+             * successful revert of all the module with vetoing hooks. When one
+             * of the hooks fails due to not meeting certain conditions the whole
+             * replace operation must have been reverted with all previous pre- and
+             * post- hooks re-executed (which cannot be guaranteed to succeed).
+             * The simplest response to this complication is disallow replace
+             * action on modules with vetoing hooks.
+             */
+            if ( has_payload_any_vetoing_hooks(data) || livepatch_applied_have_vetoing_hooks() )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: REPLACE action is not supported on hotpatches with vetoing hooks!\n",
+                       data->name);
+                rc = -EOPNOTSUPP;
+                break;
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h
index 99613af2db..cd20944cc4 100644
--- a/xen/include/xen/livepatch_payload.h
+++ b/xen/include/xen/livepatch_payload.h
@@ -21,6 +21,16 @@ typedef struct payload livepatch_payload_t;
 typedef void livepatch_loadcall_t(void);
 typedef void livepatch_unloadcall_t(void);
 
+typedef int livepatch_precall_t(livepatch_payload_t *arg);
+typedef void livepatch_postcall_t(livepatch_payload_t *arg);
+
+struct livepatch_hooks {
+    struct {
+        livepatch_precall_t *const *pre;
+        livepatch_postcall_t *const *post;
+    } apply, revert;
+};
+
 struct payload {
     uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
     int32_t rc;                          /* 0 or -XEN_EXX. */
@@ -47,6 +57,7 @@ struct payload {
     struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
     livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
     livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
+    struct livepatch_hooks hooks;        /* Pre and post hooks for apply and revert */
     unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
     unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
     char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
@@ -76,6 +87,22 @@ struct payload {
      livepatch_unloadcall_t *__weak \
         const livepatch_unload_data_##_fn __section(".livepatch.hooks.unload") = _fn;
 
+#define LIVEPATCH_PREAPPLY_HOOK(_fn) \
+    livepatch_precall_t *__attribute__((weak, used)) \
+        const livepatch_preapply_data_##_fn __section(".livepatch.hooks.preapply") = _fn;
+
+#define LIVEPATCH_POSTAPPLY_HOOK(_fn) \
+    livepatch_postcall_t *__attribute__((weak, used)) \
+        const livepatch_postapply_data_##_fn __section(".livepatch.hooks.postapply") = _fn;
+
+#define LIVEPATCH_PREREVERT_HOOK(_fn) \
+    livepatch_precall_t *__attribute__((weak, used)) \
+        const livepatch_prerevert_data_##_fn __section(".livepatch.hooks.prerevert") = _fn;
+
+#define LIVEPATCH_POSTREVERT_HOOK(_fn) \
+    livepatch_postcall_t *__attribute__((weak, used)) \
+        const livepatch_postrevert_data_##_fn __section(".livepatch.hooks.postrevert") = _fn;
+
 #endif /* __XEN_LIVEPATCH_PAYLOAD_H__ */
 
 /*
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (4 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 05/14] livepatch: Implement pre-|post- apply|revert hooks Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` Pawel Wieczorkiewicz
  2019-08-21 18:31   ` Konrad Rzeszutek Wilk
  2019-08-21  8:19 ` [Xen-devel] [PATCH 07/14] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence Pawel Wieczorkiewicz
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

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 <wipawel@amazon.de>
Reviewed-by: Petre Eftime <epetre@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.com>
Reviewed-by: Norbert Manthey <nmanthey@amazon.com>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Bjoern Doebel <doebel@amazon.com>
---
 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;
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 07/14] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (5 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 08/14] livepatch: always print XENLOG_ERR information Pawel Wieczorkiewicz
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

With default implementation the ELF_LIVEPATCH_FUNC section containing
all functions to be replaced or added must be part of the hotpatch
payload, otherwise the payload is rejected (with -EINVAL).

However, with the extended hooks implementation, a hotpatch may be
constructed of only hooks to perform certain actions without any code
to be added or replaced.
Therefore, do not always expect the functions section and allow it to
be missing, provided there is at least one section containing hooks
present. The functions section, when present in a payload, must be a
single, non-empty section.

Check also all extended hooks sections if they are a single, non-empty
sections each.

At least one of the functions or hooks section must be present in a
valid payload.

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>
---
 xen/common/livepatch.c      | 145 +++++++++++++++++++++++++++++++-------------
 xen/include/xen/livepatch.h |   8 +++
 2 files changed, 112 insertions(+), 41 deletions(-)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 38fab8b240..c4a107d91c 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -467,8 +467,7 @@ static int check_xen_build_id(const struct payload *payload)
 static int check_special_sections(const struct livepatch_elf *elf)
 {
     unsigned int i;
-    static const char *const names[] = { ELF_LIVEPATCH_FUNC,
-                                         ELF_LIVEPATCH_DEPENDS,
+    static const char *const names[] = { ELF_LIVEPATCH_DEPENDS,
                                          ELF_LIVEPATCH_XEN_DEPENDS,
                                          ELF_BUILD_ID_NOTE};
     DECLARE_BITMAP(found, ARRAY_SIZE(names)) = { 0 };
@@ -503,6 +502,64 @@ static int check_special_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+static int check_patching_sections(const struct livepatch_elf *elf)
+{
+    unsigned int i;
+    static const char *const names[] = { ELF_LIVEPATCH_FUNC,
+                                         ELF_LIVEPATCH_LOAD_HOOKS,
+                                         ELF_LIVEPATCH_UNLOAD_HOOKS,
+                                         ELF_LIVEPATCH_PREAPPLY_HOOK,
+                                         ELF_LIVEPATCH_APPLY_HOOK,
+                                         ELF_LIVEPATCH_POSTAPPLY_HOOK,
+                                         ELF_LIVEPATCH_PREREVERT_HOOK,
+                                         ELF_LIVEPATCH_REVERT_HOOK,
+                                         ELF_LIVEPATCH_POSTREVERT_HOOK};
+    DECLARE_BITMAP(found, ARRAY_SIZE(names)) = { 0 };
+
+    /*
+     * The patching sections are optional, but at least one
+     * must be present. Otherwise, there is nothing to do.
+     * All the existing sections must not be empty and must
+     * be present at most once.
+     */
+    for ( i = 0; i < ARRAY_SIZE(names); i++ )
+    {
+        const struct livepatch_elf_sec *sec;
+
+        sec = livepatch_elf_sec_by_name(elf, names[i]);
+        if ( !sec )
+        {
+            dprintk(XENLOG_INFO, LIVEPATCH "%s: %s is missing!\n",
+                    elf->name, names[i]);
+            continue; /* This section is optional */
+        }
+
+        if ( !sec->sec->sh_size )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s is empty!\n",
+                    elf->name, names[i]);
+            return -EINVAL;
+        }
+
+        if ( test_and_set_bit(i, found) )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s was seen more than once!\n",
+                    elf->name, names[i]);
+            return -EINVAL;
+        }
+    }
+
+    /* Checking if at least one section is present. */
+    if ( bitmap_empty(found, ARRAY_SIZE(names)) )
+    {
+        printk(XENLOG_ERR LIVEPATCH "%s: Nothing to patch. Aborting...\n",
+               elf->name);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 /*
  * Lookup specified section and when exists assign its address to a specified hook.
  * Perform section pointer and size validation: single hook sections must contain a
@@ -542,57 +599,59 @@ static int prepare_payload(struct payload *payload,
     const Elf_Note *n;
 
     sec = livepatch_elf_sec_by_name(elf, ELF_LIVEPATCH_FUNC);
-    ASSERT(sec);
-    if ( !section_ok(elf, sec, sizeof(*payload->funcs)) )
-        return -EINVAL;
-
-    payload->funcs = sec->load_addr;
-    payload->nfuncs = sec->sec->sh_size / sizeof(*payload->funcs);
-
-    for ( i = 0; i < payload->nfuncs; i++ )
+    if ( sec )
     {
-        int rc;
+        if ( !section_ok(elf, sec, sizeof(*payload->funcs)) )
+            return -EINVAL;
 
-        f = &(payload->funcs[i]);
+        payload->funcs = sec->load_addr;
+        payload->nfuncs = sec->sec->sh_size / sizeof(*payload->funcs);
 
-        if ( f->version != LIVEPATCH_PAYLOAD_VERSION )
+        for ( i = 0; i < payload->nfuncs; i++ )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong version (%u). Expected %d!\n",
-                    elf->name, f->version, LIVEPATCH_PAYLOAD_VERSION);
-            return -EOPNOTSUPP;
-        }
+            int rc;
 
-        /* 'old_addr', 'new_addr', 'new_size' can all be zero. */
-        if ( !f->old_size )
-        {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: Address or size fields are zero!\n",
-                    elf->name);
-            return -EINVAL;
-        }
+            f = &(payload->funcs[i]);
 
-        rc = arch_livepatch_verify_func(f);
-        if ( rc )
-            return rc;
+            if ( f->version != LIVEPATCH_PAYLOAD_VERSION )
+            {
+                dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong version (%u). Expected %d!\n",
+                        elf->name, f->version, LIVEPATCH_PAYLOAD_VERSION);
+                return -EOPNOTSUPP;
+            }
 
-        rc = resolve_old_address(f, elf);
-        if ( rc )
-            return rc;
+            /* 'old_addr', 'new_addr', 'new_size' can all be zero. */
+            if ( !f->old_size )
+            {
+                dprintk(XENLOG_ERR, LIVEPATCH "%s: Address or size fields are zero!\n",
+                        elf->name);
+                return -EINVAL;
+            }
 
-        rc = livepatch_verify_distance(f);
-        if ( rc )
-            return rc;
+            rc = arch_livepatch_verify_func(f);
+            if ( rc )
+                return rc;
+
+            rc = resolve_old_address(f, elf);
+            if ( rc )
+                return rc;
+
+            rc = livepatch_verify_distance(f);
+            if ( rc )
+                return rc;
+        }
     }
 
-    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->load_funcs, payload->n_load_funcs, ".livepatch.hooks.load");
-    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ".livepatch.hooks.unload");
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->load_funcs, payload->n_load_funcs, ELF_LIVEPATCH_LOAD_HOOKS);
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ELF_LIVEPATCH_UNLOAD_HOOKS);
 
-    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.apply.pre, ELF_LIVEPATCH_PREAPPLY_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.action, ELF_LIVEPATCH_APPLY_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.post, ELF_LIVEPATCH_POSTAPPLY_HOOK);
 
-    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");
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.pre, ELF_LIVEPATCH_PREREVERT_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.action, ELF_LIVEPATCH_REVERT_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.post, ELF_LIVEPATCH_POSTREVERT_HOOK);
 
     sec = livepatch_elf_sec_by_name(elf, ELF_BUILD_ID_NOTE);
     if ( sec )
@@ -904,6 +963,10 @@ static int load_payload_data(struct payload *payload, void *raw, size_t len)
     if ( rc )
         goto out;
 
+    rc = check_patching_sections(&elf);
+    if ( rc )
+        goto out;
+
     rc = prepare_payload(payload, &elf);
     if ( rc )
         goto out;
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index ed997aa4cc..2aec532ee2 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -33,6 +33,14 @@ struct xen_sysctl_livepatch_op;
 #define ELF_LIVEPATCH_DEPENDS     ".livepatch.depends"
 #define ELF_LIVEPATCH_XEN_DEPENDS ".livepatch.xen_depends"
 #define ELF_BUILD_ID_NOTE         ".note.gnu.build-id"
+#define ELF_LIVEPATCH_LOAD_HOOKS      ".livepatch.hooks.load"
+#define ELF_LIVEPATCH_UNLOAD_HOOKS    ".livepatch.hooks.unload"
+#define ELF_LIVEPATCH_PREAPPLY_HOOK   ".livepatch.hooks.preapply"
+#define ELF_LIVEPATCH_APPLY_HOOK      ".livepatch.hooks.apply"
+#define ELF_LIVEPATCH_POSTAPPLY_HOOK  ".livepatch.hooks.postapply"
+#define ELF_LIVEPATCH_PREREVERT_HOOK  ".livepatch.hooks.prerevert"
+#define ELF_LIVEPATCH_REVERT_HOOK     ".livepatch.hooks.revert"
+#define ELF_LIVEPATCH_POSTREVERT_HOOK ".livepatch.hooks.postrevert"
 /* Arbitrary limit for payload size and .bss section size. */
 #define LIVEPATCH_MAX_SIZE     MB(2)
 
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 08/14] livepatch: always print XENLOG_ERR information
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (6 preceding siblings ...)
  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 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker Pawel Wieczorkiewicz
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Wei Liu, Ross Lagerwall, Andrew Cooper,
	Konrad Rzeszutek Wilk, mpohlack, Pawel Wieczorkiewicz,
	Jan Beulich, Roger Pau Monné

A lot of legitimate error messages were hidden behind debug printk
only. Most of these messages can be triggered by loading a malformed
hotpatch payload and are priceless for understanding issues with such
payloads.
Thus, always display all relevant XENLOG_ERR messages.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Amit Shah <aams@amazon.de>
Reviewed-by: Martin Mazein <amazein@amazon.de>
Reviewed-by: Bjoern Doebel <doebel@amazon.de>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 xen/arch/x86/livepatch.c | 16 ++++++++--------
 xen/common/livepatch.c   | 38 +++++++++++++++++++-------------------
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index 406eb910cc..436ee40fe1 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -126,7 +126,7 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
          hdr->e_ident[EI_CLASS] != ELFCLASS64 ||
          hdr->e_ident[EI_DATA] != ELFDATA2LSB )
     {
-        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
+        printk(XENLOG_ERR LIVEPATCH "%s: Unsupported ELF Machine type!\n",
                 elf->name);
         return -EOPNOTSUPP;
     }
@@ -152,7 +152,7 @@ int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
 {
-    dprintk(XENLOG_ERR, LIVEPATCH "%s: SHT_REL relocation unsupported\n",
+    printk(XENLOG_ERR LIVEPATCH "%s: SHT_REL relocation unsupported\n",
             elf->name);
     return -EOPNOTSUPP;
 }
@@ -172,19 +172,19 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf,
 
         if ( symndx == STN_UNDEF )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: Encountered STN_UNDEF\n",
                     elf->name);
             return -EOPNOTSUPP;
         }
         else if ( symndx >= elf->nsym )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n",
                     elf->name, symndx);
             return -EINVAL;
         }
         else if ( !elf->sym[symndx].sym )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: No symbol@%u\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: No symbol@%u\n",
                     elf->name, symndx);
             return -EINVAL;
         }
@@ -222,14 +222,14 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf,
             *(int32_t *)dest = val;
             if ( (int64_t)val != *(int32_t *)dest )
             {
-                dprintk(XENLOG_ERR, LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
+                printk(XENLOG_ERR LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
                         elf->name, i, rela->name, base->name);
                 return -EOVERFLOW;
             }
             break;
 
         default:
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: Unhandled relocation %lu\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: Unhandled relocation %lu\n",
                     elf->name, ELF64_R_TYPE(r->r_info));
             return -EOPNOTSUPP;
         }
@@ -238,7 +238,7 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf,
     return 0;
 
  bad_offset:
-    dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation offset is past %s section!\n",
+    printk(XENLOG_ERR LIVEPATCH "%s: Relative relocation offset is past %s section!\n",
             elf->name, base->name);
     return -EINVAL;
 }
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index c4a107d91c..585ec9819a 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -217,7 +217,7 @@ static int resolve_old_address(struct livepatch_func *f,
         f->old_addr = (void *)livepatch_symbols_lookup_by_name(f->name);
         if ( !f->old_addr )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: Could not resolve old address of %s\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: Could not resolve old address of %s\n",
                     elf->name, f->name);
             return -ENOENT;
         }
@@ -336,7 +336,7 @@ static int move_payload(struct payload *payload, struct livepatch_elf *elf)
     text_buf = vmalloc_xen(size * PAGE_SIZE);
     if ( !text_buf )
     {
-        dprintk(XENLOG_ERR, LIVEPATCH "%s: Could not allocate memory for payload!\n",
+        printk(XENLOG_ERR LIVEPATCH "%s: Could not allocate memory for payload!\n",
                 elf->name);
         rc = -ENOMEM;
         goto out;
@@ -434,7 +434,7 @@ static bool section_ok(const struct livepatch_elf *elf,
 
     if ( sec->sec->sh_size % sz )
     {
-        dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong size %"PRIuElfWord" of %s (must be multiple of %zu)\n",
+        printk(XENLOG_ERR LIVEPATCH "%s: Wrong size %"PRIuElfWord" of %s (must be multiple of %zu)\n",
                 elf->name, sec->sec->sh_size, sec->name, sz);
         return false;
     }
@@ -456,7 +456,7 @@ static int check_xen_build_id(const struct payload *payload)
         return rc;
 
     if ( payload->xen_dep.len != len || memcmp(id, payload->xen_dep.p, len) ) {
-        dprintk(XENLOG_ERR, "%s%s: check against hypervisor build-id failed!\n",
+        printk(XENLOG_ERR LIVEPATCH "%s%s: check against hypervisor build-id failed!\n",
                 LIVEPATCH, payload->name);
         return -EINVAL;
     }
@@ -479,21 +479,21 @@ static int check_special_sections(const struct livepatch_elf *elf)
         sec = livepatch_elf_sec_by_name(elf, names[i]);
         if ( !sec )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s is missing!\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: %s is missing!\n",
                     elf->name, names[i]);
             return -EINVAL;
         }
 
         if ( !sec->sec->sh_size )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s is empty!\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: %s is empty!\n",
                     elf->name, names[i]);
             return -EINVAL;
         }
 
         if ( test_and_set_bit(i, found) )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s was seen more than once!\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: %s was seen more than once!\n",
                     elf->name, names[i]);
             return -EINVAL;
         }
@@ -529,21 +529,21 @@ static int check_patching_sections(const struct livepatch_elf *elf)
         sec = livepatch_elf_sec_by_name(elf, names[i]);
         if ( !sec )
         {
-            dprintk(XENLOG_INFO, LIVEPATCH "%s: %s is missing!\n",
+            dprintk(XENLOG_DEBUG, LIVEPATCH "%s: %s is missing!\n",
                     elf->name, names[i]);
             continue; /* This section is optional */
         }
 
         if ( !sec->sec->sh_size )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s is empty!\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: %s is empty!\n",
                     elf->name, names[i]);
             return -EINVAL;
         }
 
         if ( test_and_set_bit(i, found) )
         {
-            dprintk(XENLOG_ERR, LIVEPATCH "%s: %s was seen more than once!\n",
+            printk(XENLOG_ERR LIVEPATCH "%s: %s was seen more than once!\n",
                     elf->name, names[i]);
             return -EINVAL;
         }
@@ -615,7 +615,7 @@ static int prepare_payload(struct payload *payload,
 
             if ( f->version != LIVEPATCH_PAYLOAD_VERSION )
             {
-                dprintk(XENLOG_ERR, LIVEPATCH "%s: Wrong version (%u). Expected %d!\n",
+                printk(XENLOG_ERR LIVEPATCH "%s: Wrong version (%u). Expected %d!\n",
                         elf->name, f->version, LIVEPATCH_PAYLOAD_VERSION);
                 return -EOPNOTSUPP;
             }
@@ -623,7 +623,7 @@ static int prepare_payload(struct payload *payload,
             /* 'old_addr', 'new_addr', 'new_size' can all be zero. */
             if ( !f->old_size )
             {
-                dprintk(XENLOG_ERR, LIVEPATCH "%s: Address or size fields are zero!\n",
+                printk(XENLOG_ERR LIVEPATCH "%s: Address or size fields are zero!\n",
                         elf->name);
                 return -EINVAL;
             }
@@ -762,14 +762,14 @@ static int prepare_payload(struct payload *payload,
             if ( (instr < region->start && instr >= region->end) ||
                  (replacement < region->start && replacement >= region->end) )
             {
-                dprintk(XENLOG_ERR, LIVEPATCH "%s Alt patching outside payload: %p!\n",
+                printk(XENLOG_ERR LIVEPATCH "%s Alt patching outside payload: %p!\n",
                         elf->name, instr);
                 return -EINVAL;
             }
         }
         apply_alternatives(start, end);
 #else
-        dprintk(XENLOG_ERR, LIVEPATCH "%s: We don't support alternative patching!\n",
+        printk(XENLOG_ERR LIVEPATCH "%s: We don't support alternative patching!\n",
                 elf->name);
         return -EOPNOTSUPP;
 #endif
@@ -792,7 +792,7 @@ static int prepare_payload(struct payload *payload,
         region->ex = s;
         region->ex_end = e;
 #else
-        dprintk(XENLOG_ERR, LIVEPATCH "%s: We don't support .ex_table!\n",
+        printk(XENLOG_ERR LIVEPATCH "%s: We don't support .ex_table!\n",
                 elf->name);
         return -EOPNOTSUPP;
 #endif
@@ -901,7 +901,7 @@ static int build_symbol_table(struct payload *payload,
             if ( symbols_lookup_by_name(symtab[i].name) ||
                  livepatch_symbols_lookup_by_name(symtab[i].name) )
             {
-                dprintk(XENLOG_ERR, LIVEPATCH "%s: duplicate new symbol: %s\n",
+                printk(XENLOG_ERR LIVEPATCH "%s: duplicate new symbol: %s\n",
                         elf->name, symtab[i].name);
                 xfree(symtab);
                 xfree(strtab);
@@ -1652,7 +1652,7 @@ static int build_id_dep(struct payload *payload, bool_t internal)
     if ( payload->dep.len != len ||
          memcmp(id, payload->dep.p, len) )
     {
-        dprintk(XENLOG_ERR, "%s%s: check against %s build-id failed!\n",
+        printk(XENLOG_ERR LIVEPATCH "%s%s: check against %s build-id failed!\n",
                 LIVEPATCH, payload->name, name);
         return -EINVAL;
     }
@@ -1712,7 +1712,7 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
             /* We should be the last applied one. */
             if ( p != data )
             {
-                dprintk(XENLOG_ERR, "%s%s: can't unload. Top is %s!\n",
+                printk(XENLOG_ERR LIVEPATCH "%s%s: can't unload. Top is %s!\n",
                         LIVEPATCH, data->name, p->name);
                 rc = -EBUSY;
                 break;
@@ -1748,7 +1748,7 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
              */
             if ( data->reverted && !data->safe_to_reapply )
             {
-                dprintk(XENLOG_ERR, "%s%s: can't revert as payload has .data. Please unload!\n",
+                printk(XENLOG_ERR LIVEPATCH "%s%s: can't revert as payload has .data. Please unload!\n",
                         LIVEPATCH, data->name);
                 data->rc = -EINVAL;
                 break;
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (7 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 08/14] livepatch: always print XENLOG_ERR information Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` Pawel Wieczorkiewicz
  2019-08-21 18:28   ` Konrad Rzeszutek Wilk
                     ` (2 more replies)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations Pawel Wieczorkiewicz
                   ` (5 subsequent siblings)
  14 siblings, 3 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Konrad Rzeszutek Wilk, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich, Roger Pau Monné

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@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Bjoern Doebel <doebel@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
---
 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 1b2b165a6d..b55ad6d050 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@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (8 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` Pawel Wieczorkiewicz
  2019-08-21 18:30   ` Konrad Rzeszutek Wilk
  2019-08-22 10:31   ` Julien Grall
  2019-08-21  8:19 ` [Xen-devel] [PATCH 11/14] livepatch: Add support for modules .modinfo section metadata Pawel Wieczorkiewicz
                   ` (4 subsequent siblings)
  14 siblings, 2 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Konrad Rzeszutek Wilk, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

This is the initial implementation of the expectations enhancement
to improve inline asm hotpatching.

Expectations are designed as optional feature, since the main use of
them is planned for inline asm hotpatching. The flag enabled allows
to control the expectation state.
Each expectation has data and len fields that describe the data
that is expected to be found at a given patching (old_addr) location.
The len must not exceed the data array size. The data array size
follows the size of the opaque array, since the opaque array holds
the original data and therefore must match what is specified in the
expectation (if enabled).

The payload structure is modified as each expectation structure is
part of the livepatch_func structure and hence extends the payload.
The payload version is bumped to 3 with this change to highlight the
ABI modification and enforce proper support.

Each expectation is checked prior to the apply action (i.e. as late
as possible to check against the most current state of the code).

For the replace action a new payload's expectations are checked AFTER
all applied payloads are successfully reverted, but BEFORE new payload
is applied. That breaks the replace action's atomicity and in case of
an expectation check failure would leave a system with all payloads
reverted. That is obviously insecure. Use it with caution and act
upon replace errors!

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 xen/common/livepatch.c      | 71 +++++++++++++++++++++++++++++++++++++++++++++
 xen/include/public/sysctl.h | 17 +++++++++--
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 090a48977b..8aef2fd12e 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -560,6 +560,58 @@ static int check_patching_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+static inline int livepatch_verify_expectation_fn(const struct livepatch_func *func)
+{
+    const livepatch_expectation_t *exp = &func->expect;
+
+    /* Ignore disabled expectations. */
+    if ( !exp->enabled )
+        return 0;
+
+    /* There is nothing to expect */
+    if ( !func->old_addr )
+        return -EFAULT;
+
+    if ( exp->len > sizeof(exp->data))
+        return -EOVERFLOW;
+
+    /* Incorrect expectation */
+    if ( func->old_size < exp->len )
+        return -ERANGE;
+
+    if ( memcmp(func->old_addr, exp->data, exp->len) )
+    {
+        printk(XENLOG_ERR LIVEPATCH "%s: expectation failed: expected:%*phN, actual:%*phN\n",
+               func->name, exp->len, exp->data, exp->len, func->old_addr);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static inline int livepatch_check_expectations(const struct payload *payload)
+{
+    int i, rc;
+
+    printk(XENLOG_INFO LIVEPATCH "%s: Verifying enabled expectations for all functions\n",
+           payload->name);
+
+    for ( i = 0; i < payload->nfuncs; i++ )
+    {
+        const struct livepatch_func *func = &(payload->funcs[i]);
+
+        rc = livepatch_verify_expectation_fn(func);
+        if ( rc )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: expectations of %s failed (rc=%d), aborting!\n",
+                   payload->name, func->name ?: "unknown", rc);
+            return rc;
+        }
+    }
+
+    return 0;
+}
+
 /*
  * Lookup specified section and when exists assign its address to a specified hook.
  * Perform section pointer and size validation: single hook sections must contain a
@@ -1347,6 +1399,20 @@ static void livepatch_do_action(void)
 
         if ( rc == 0 )
         {
+            /*
+             * Make sure all expectation requirements are met.
+             * Beware all the payloads are reverted at this point.
+             * If expectations are not met the system is left in a
+             * completely UNPATCHED state!
+             */
+            rc = livepatch_check_expectations(data);
+            if ( rc )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: SYSTEM MIGHT BE INSECURE: "
+                       "Replace action has been aborted after reverting ALL payloads!\n", data->name);
+                break;
+            }
+
             if ( is_hook_enabled(data->hooks.apply.action) )
             {
                 printk(XENLOG_INFO LIVEPATCH "%s: Calling apply action hook function\n", data->name);
@@ -1800,6 +1866,11 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                     break;
             }
 
+            /* Make sure all expectation requirements are met. */
+            rc = livepatch_check_expectations(data);
+            if ( rc )
+                break;
+
             if ( is_hook_enabled(data->hooks.apply.pre) )
             {
                 printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-apply hook function\n", data->name);
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index b55ad6d050..e18322350d 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 2
+#define LIVEPATCH_PAYLOAD_VERSION 3
 /*
  * .livepatch.funcs structure layout defined in the `Payload format`
  * section in the Live Patch design document.
@@ -826,6 +826,18 @@ struct xen_sysctl_cpu_featureset {
  * We guard this with __XEN__ as toolstacks SHOULD not use it.
  */
 #ifdef __XEN__
+#define LIVEPATCH_OPAQUE_SIZE 31
+
+struct livepatch_expectation {
+    uint8_t enabled : 1;
+    uint8_t len : 5;        /* Length of data up to LIVEPATCH_OPAQUE_SIZE
+                               (5 bits is enough for now) */
+    uint8_t data[LIVEPATCH_OPAQUE_SIZE]; /* Same size as opaque[] buffer of
+                                            struct livepatch_func. This is the
+                                            max number of bytes to be patched */
+};
+typedef struct livepatch_expectation livepatch_expectation_t;
+
 typedef enum livepatch_func_state {
     LIVEPATCH_FUNC_NOT_APPLIED = 0,
     LIVEPATCH_FUNC_APPLIED = 1
@@ -838,11 +850,12 @@ struct livepatch_func {
     uint32_t new_size;
     uint32_t old_size;
     uint8_t version;        /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
-    uint8_t opaque[31];
+    uint8_t opaque[LIVEPATCH_OPAQUE_SIZE];
 #if defined CONFIG_X86
     uint8_t applied;
     uint8_t _pad[7];
 #endif
+    livepatch_expectation_t expect;
 };
 typedef struct livepatch_func livepatch_func_t;
 #endif
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 11/14] livepatch: Add support for modules .modinfo section metadata
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (9 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 12/14] livepatch: Handle arbitrary size names with the list operation Pawel Wieczorkiewicz
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

Having detailed hotpatch metadata helps to properly identify module's
origin and version. It also allows to keep track of the history of
hotpatch loads in the system (at least within dmesg buffer size
limits).

The hotpatch metadata are embedded in a form of .modinfo section.
Each such section contains data of the following format:
key=value\0key=value\0...key=value\0

The .modinfo section may be generated and appended to the resulting
hotpatch ELF file optionally as an extra step of a higher level
hotpatch build system.

The metadata section pointer and the section length is stored in the
hotpatch payload structure and is used to display the content upon
hotpatch apply operation.

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: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 xen/common/livepatch.c              | 34 ++++++++++++++++++++++++++++++++++
 xen/include/xen/livepatch_payload.h |  6 ++++++
 2 files changed, 40 insertions(+)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 8aef2fd12e..f88cf3bc73 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -850,6 +850,23 @@ static int prepare_payload(struct payload *payload,
 #endif
     }
 
+    sec = livepatch_elf_sec_by_name(elf, ".modinfo");
+    if ( sec )
+    {
+        if ( !section_ok(elf, sec, sizeof(*payload->metadata.data)) )
+            return -EINVAL;
+
+        payload->metadata.data = sec->load_addr;
+        payload->metadata.len = sec->sec->sh_size;
+
+        /* The metadata is required to consists of null terminated strings. */
+        if ( payload->metadata.data[payload->metadata.len - 1] != '\0' )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: Incorrect metadata format detected\n", payload->name);
+            return -EINVAL;
+        }
+    }
+
     return 0;
 }
 
@@ -1200,6 +1217,19 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
  * for XEN_SYSCTL_LIVEPATCH_ACTION operation (see livepatch_action).
  */
 
+static inline void livepatch_display_metadata(const struct livepatch_metadata *metadata)
+{
+    const char *str;
+
+    if ( metadata && metadata->data && metadata->len > 0 )
+    {
+        printk(XENLOG_INFO LIVEPATCH "module metadata:\n");
+        for ( str = metadata->data; str < (metadata->data + metadata->len); str += (strlen(str) + 1) )
+            printk(XENLOG_INFO LIVEPATCH "  %s\n", str);
+    }
+
+}
+
 static int apply_payload(struct payload *data)
 {
     unsigned int i;
@@ -1232,6 +1262,8 @@ static int apply_payload(struct payload *data)
 
     arch_livepatch_revive();
 
+    livepatch_display_metadata(&data->metadata);
+
     return 0;
 }
 
@@ -2008,6 +2040,8 @@ static void livepatch_printall(unsigned char key)
                data->name, state2str(data->state), data->state, data->text_addr,
                data->rw_addr, data->ro_addr, data->pages);
 
+        livepatch_display_metadata(&data->metadata);
+
         for ( i = 0; i < data->nfuncs; i++ )
         {
             struct livepatch_func *f = &(data->funcs[i]);
diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h
index ff16af0dd6..9f5f064205 100644
--- a/xen/include/xen/livepatch_payload.h
+++ b/xen/include/xen/livepatch_payload.h
@@ -33,6 +33,11 @@ struct livepatch_hooks {
     } apply, revert;
 };
 
+struct livepatch_metadata {
+    const char *data; /* Ptr to .modinfo section with ASCII data. */
+    uint32_t len;     /* Length of the metadata section. */
+};
+
 struct payload {
     uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
     int32_t rc;                          /* 0 or -XEN_EXX. */
@@ -63,6 +68,7 @@ struct payload {
     unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
     unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
     char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
+    struct livepatch_metadata metadata;  /* Module meta data record */
 };
 
 /*
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 12/14] livepatch: Handle arbitrary size names with the list operation
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (10 preceding siblings ...)
  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 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 13/14] livepatch: Add metadata runtime retrieval mechanism Pawel Wieczorkiewicz
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

The payloads' name strings can be of arbitrary size (typically small
with an upper bound of XEN_LIVEPATCH_NAME_SIZE).
Current implementation of the list operation interface allows to copy
names in the XEN_LIVEPATCH_NAME_SIZE chunks regardless of its actual
size and enforces space allocation requirements on userland tools.

To unify and simplify the interface, handle the name strings of
arbitrary size by copying them in adhering chunks to the userland.
In order to let the userland allocate enough space for the incoming
data add an auxiliary interface xc_livepatch_list_get_sizes() that
provides the current number of payload entries and the total size of
all name strings. This is achieved by extending the sysctl list
interface with an extra fields: name_total_size.

The xc_livepatch_list_get_sizes() issues the livepatch sysctl list
operation with the nr field set to 0. In this mode the operation
returns the number of payload entries and calculates the total sizes
for all payloads' names.
When the sysctl operation is issued with a non-zero nr field (for
instance with a value obtained earlier with the prior call to the
xc_livepatch_list_get_sizes()) the new field name_total_size provides
the total size of actually copied data.

Extend the libxc to handle the name back-to-back data transfers.

The xen-livepatch tool is modified to start the list operation with a
call to the xc_livepatch_list_get_sizes() to obtain the actual number
of payloads as well as the necessary space for names.
The tool now always requests the actual number of entries and leaves
the preemption handling to the libxc routine. The libxc still returns
'done' and 'left' parameters with the same semantic allowing the tool
to detect anomalies and react to them. At the moment it is expected
that the tool receives the exact number of entires as requested.
The xen-livepatch tool has been also modified to handle the name
back-to-back transfers correctly.

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>
---
 tools/libxc/include/xenctrl.h |  49 ++++++++++++------
 tools/libxc/xc_misc.c         | 100 ++++++++++++++++++++++++++++---------
 tools/misc/xen-livepatch.c    | 112 ++++++++++++++++++++++--------------------
 xen/common/livepatch.c        |  31 +++++++++---
 xen/include/public/sysctl.h   |  15 +++---
 5 files changed, 204 insertions(+), 103 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 725697c132..e0ebb586b6 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2560,7 +2560,25 @@ int xc_livepatch_get(xc_interface *xch,
                      xen_livepatch_status_t *status);
 
 /*
- * The heart of this function is to get an array of xen_livepatch_status_t.
+ * Get a number of available payloads and get actual total size of
+ * the payloads' name array.
+ *
+ * This functions is typically executed first before the xc_livepatch_list()
+ * to obtain the sizes and correctly allocate all necessary data resources.
+ *
+ * The return value is zero if the hypercall completed successfully.
+ *
+ * If there was an error performing the sysctl operation, the return value
+ * will contain the hypercall error code value.
+ */
+int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
+                                uint64_t *name_total_size);
+
+/*
+ * The heart of this function is to get an array of the following objects:
+ *   - xen_livepatch_status_t: states and return codes of payloads
+ *   - name: names of payloads
+ *   - len: lengths of corresponding payloads' names
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -2571,21 +2589,20 @@ int xc_livepatch_get(xc_interface *xch,
  * 'left' are also updated with the number of entries filled out
  * and respectively the number of entries left to get from hypervisor.
  *
- * It is expected that the caller of this function will take the
- * 'left' and use the value for 'start'. This way we have an
- * cursor in the array. Note that the 'info','name', and 'len' will
- * be updated at the subsequent calls.
+ * It is expected that the caller of this function will first issue the
+ * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
+ * as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size'
+ * parameter.
  *
- * The 'max' is to be provided by the caller with the maximum
- * number of entries that 'info', 'name', and 'len' arrays can
- * be filled up with.
- *
- * Each entry in the 'name' array is expected to be of XEN_LIVEPATCH_NAME_SIZE
- * length.
+ * The 'max' is to be provided by the caller with the maximum number of
+ * entries that 'info', 'name', 'len' arrays can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
  *
+ * Each entry in the 'name' array may have an arbitrary size.
+ *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
  * The return value is zero if the hypercall completed successfully.
@@ -2597,10 +2614,12 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the number of entries that had been succesfully
  * retrieved (if any).
  */
-int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
-                      xen_livepatch_status_t *info, char *name,
-                      uint32_t *len, unsigned int *done,
-                      unsigned int *left);
+int xc_livepatch_list(xc_interface *xch, const unsigned int max,
+                      const unsigned int start,
+                      struct xen_livepatch_status *info,
+                      char *name, uint32_t *len,
+                      const uint64_t name_total_size,
+                      unsigned int *done, unsigned int *left);
 
 /*
  * The operations are asynchronous and the hypervisor may take a while
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index a8e9e7d1e2..d787f3f29f 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -662,7 +662,48 @@ int xc_livepatch_get(xc_interface *xch,
 }
 
 /*
- * The heart of this function is to get an array of xen_livepatch_status_t.
+ * Get a number of available payloads and get actual total size of
+ * the payloads' name array.
+ *
+ * This functions is typically executed first before the xc_livepatch_list()
+ * to obtain the sizes and correctly allocate all necessary data resources.
+ *
+ * The return value is zero if the hypercall completed successfully.
+ *
+ * If there was an error performing the sysctl operation, the return value
+ * will contain the hypercall error code value.
+ */
+int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
+                                uint64_t *name_total_size)
+{
+    DECLARE_SYSCTL;
+    int rc;
+
+    if ( !nr || !name_total_size )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    memset(&sysctl, 0, sizeof(sysctl));
+    sysctl.cmd = XEN_SYSCTL_livepatch_op;
+    sysctl.u.livepatch.cmd = XEN_SYSCTL_LIVEPATCH_LIST;
+
+    rc = do_sysctl(xch, &sysctl);
+    if ( rc )
+        return rc;
+
+    *nr = sysctl.u.livepatch.u.list.nr;
+    *name_total_size = sysctl.u.livepatch.u.list.name_total_size;
+
+    return 0;
+}
+
+/*
+ * The heart of this function is to get an array of the following objects:
+ *   - xen_livepatch_status_t: states and return codes of payloads
+ *   - name: names of payloads
+ *   - len: lengths of corresponding payloads' names
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -673,21 +714,20 @@ int xc_livepatch_get(xc_interface *xch,
  * 'left' are also updated with the number of entries filled out
  * and respectively the number of entries left to get from hypervisor.
  *
- * It is expected that the caller of this function will take the
- * 'left' and use the value for 'start'. This way we have an
- * cursor in the array. Note that the 'info','name', and 'len' will
- * be updated at the subsequent calls.
+ * It is expected that the caller of this function will first issue the
+ * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
+ * as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size'
+ * parameter.
  *
- * The 'max' is to be provided by the caller with the maximum
- * number of entries that 'info', 'name', and 'len' arrays can
- * be filled up with.
- *
- * Each entry in the 'name' array is expected to be of XEN_LIVEPATCH_NAME_SIZE
- * length.
+ * The 'max' is to be provided by the caller with the maximum number of
+ * entries that 'info', 'name', 'len' arrays can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
  *
+ * Each entry in the 'name' array may have an arbitrary size.
+ *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
  * The return value is zero if the hypercall completed successfully.
@@ -699,11 +739,12 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the number of entries that had been succesfully
  * retrieved (if any).
  */
-int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
+int xc_livepatch_list(xc_interface *xch, const unsigned int max,
+                      const unsigned int start,
                       struct xen_livepatch_status *info,
                       char *name, uint32_t *len,
-                      unsigned int *done,
-                      unsigned int *left)
+                      const uint64_t name_total_size,
+                      unsigned int *done, unsigned int *left)
 {
     int rc;
     DECLARE_SYSCTL;
@@ -714,27 +755,33 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
     uint32_t max_batch_sz, nr;
     uint32_t version = 0, retries = 0;
     uint32_t adjust = 0;
-    ssize_t sz;
+    off_t name_off = 0;
+    uint64_t name_sz;
 
-    if ( !max || !info || !name || !len )
+    if ( !max || !info || !name || !len || !done || !left )
     {
         errno = EINVAL;
         return -1;
     }
 
+    if ( name_total_size == 0 )
+    {
+        errno = ENOENT;
+        return -1;
+    }
+
+    memset(&sysctl, 0, sizeof(sysctl));
     sysctl.cmd = XEN_SYSCTL_livepatch_op;
     sysctl.u.livepatch.cmd = XEN_SYSCTL_LIVEPATCH_LIST;
-    sysctl.u.livepatch.pad = 0;
-    sysctl.u.livepatch.u.list.version = 0;
     sysctl.u.livepatch.u.list.idx = start;
-    sysctl.u.livepatch.u.list.pad = 0;
 
     max_batch_sz = max;
-    /* Convience value. */
-    sz = sizeof(*name) * XEN_LIVEPATCH_NAME_SIZE;
+    name_sz = name_total_size;
     *done = 0;
     *left = 0;
     do {
+        uint64_t _name_sz;
+
         /*
          * The first time we go in this loop our 'max' may be bigger
          * than what the hypervisor is comfortable with - hence the first
@@ -754,11 +801,11 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
         sysctl.u.livepatch.u.list.nr = nr;
         /* Fix the size (may vary between hypercalls). */
         HYPERCALL_BOUNCE_SET_SIZE(info, nr * sizeof(*info));
-        HYPERCALL_BOUNCE_SET_SIZE(name, nr * nr);
+        HYPERCALL_BOUNCE_SET_SIZE(name, name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, nr * sizeof(*len));
         /* Move the pointer to proper offset into 'info'. */
         (HYPERCALL_BUFFER(info))->ubuf = info + *done;
-        (HYPERCALL_BUFFER(name))->ubuf = name + (sz * *done);
+        (HYPERCALL_BUFFER(name))->ubuf = name + name_off;
         (HYPERCALL_BUFFER(len))->ubuf = len + *done;
         /* Allocate memory. */
         rc = xc_hypercall_bounce_pre(xch, info);
@@ -827,14 +874,19 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
             break;
         }
         *left = sysctl.u.livepatch.u.list.nr; /* Total remaining count. */
+        _name_sz = sysctl.u.livepatch.u.list.name_total_size; /* Total received name size. */
         /* Copy only up 'rc' of data' - we could add 'min(rc,nr) if desired. */
         HYPERCALL_BOUNCE_SET_SIZE(info, (rc * sizeof(*info)));
-        HYPERCALL_BOUNCE_SET_SIZE(name, (rc * sz));
+        HYPERCALL_BOUNCE_SET_SIZE(name, _name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, (rc * sizeof(*len)));
         /* Bounce the data and free the bounce buffer. */
         xc_hypercall_bounce_post(xch, info);
         xc_hypercall_bounce_post(xch, name);
         xc_hypercall_bounce_post(xch, len);
+
+        name_sz -= _name_sz;
+        name_off += _name_sz;
+
         /* And update how many elements of info we have copied into. */
         *done += rc;
         /* Update idx. */
diff --git a/tools/misc/xen-livepatch.c b/tools/misc/xen-livepatch.c
index a37b2457ff..8ac3d567fc 100644
--- a/tools/misc/xen-livepatch.c
+++ b/tools/misc/xen-livepatch.c
@@ -64,14 +64,14 @@ static const char *state2str(unsigned int state)
     return names[state];
 }
 
-/* This value was choosen adhoc. It could be 42 too. */
-#define MAX_LEN 11
 static int list_func(int argc, char *argv[])
 {
-    unsigned int idx, done, left, i;
+    unsigned int nr, done, left, i;
     xen_livepatch_status_t *info = NULL;
     char *name = NULL;
     uint32_t *len = NULL;
+    uint64_t name_total_size;
+    off_t name_off;
     int rc = ENOMEM;
 
     if ( argc )
@@ -79,65 +79,73 @@ static int list_func(int argc, char *argv[])
         show_help();
         return -1;
     }
-    idx = left = 0;
-    info = malloc(sizeof(*info) * MAX_LEN);
-    if ( !info )
-        return rc;
-    name = malloc(sizeof(*name) * XEN_LIVEPATCH_NAME_SIZE * MAX_LEN);
-    if ( !name )
+    done = left = 0;
+
+    rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size);
+    if ( rc )
     {
-        free(info);
+        rc = errno;
+        fprintf(stderr, "Failed to get list sizes.\n"
+                "Error %d: %s\n",
+                rc, strerror(rc));
         return rc;
     }
-    len = malloc(sizeof(*len) * MAX_LEN);
-    if ( !len ) {
-        free(name);
-        free(info);
+
+    if ( nr == 0 )
+    {
+        fprintf(stdout, "Nothing to list\n");
+        return 0;
+    }
+
+    info = malloc(nr * sizeof(*info));
+    if ( !info )
         return rc;
+
+    name = malloc(name_total_size * sizeof(*name));
+    if ( !name )
+        goto error_name;
+
+    len = malloc(nr * sizeof(*len));
+    if ( !len )
+        goto error_len;
+
+    memset(info, 'A', nr * sizeof(*info));
+    memset(name, 'B', name_total_size * sizeof(*name));
+    memset(len, 'C', nr * sizeof(*len));
+    name_off = 0;
+
+    rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size, &done, &left);
+    if ( rc || done != nr || left > 0)
+    {
+        rc = errno;
+        fprintf(stderr, "Failed to list %d/%d.\n"
+                "Error %d: %s\n",
+                left, nr, rc, strerror(rc));
+        goto error;
     }
 
-    do {
-        done = 0;
-        /* The memset is done to catch errors. */
-        memset(info, 'A', sizeof(*info) * MAX_LEN);
-        memset(name, 'B', sizeof(*name) * MAX_LEN * XEN_LIVEPATCH_NAME_SIZE);
-        memset(len, 'C', sizeof(*len) * MAX_LEN);
-        rc = xc_livepatch_list(xch, MAX_LEN, idx, info, name, len, &done, &left);
-        if ( rc )
-        {
-            rc = errno;
-            fprintf(stderr, "Failed to list %d/%d.\n"
-                            "Error %d: %s\n",
-                    idx, left, rc, strerror(rc));
-            break;
-        }
-        if ( !idx )
-            fprintf(stdout," ID                                     | status\n"
-                           "----------------------------------------+------------\n");
+    fprintf(stdout," ID                                     | status\n"
+                   "----------------------------------------+------------\n");
 
-        for ( i = 0; i < done; i++ )
-        {
-            unsigned int j;
-            uint32_t sz;
-            char *str;
-
-            sz = len[i];
-            str = name + (i * XEN_LIVEPATCH_NAME_SIZE);
-            for ( j = sz; j < XEN_LIVEPATCH_NAME_SIZE; j++ )
-                str[j] = '\0';
-
-            printf("%-40s| %s", str, state2str(info[i].state));
-            if ( info[i].rc )
-                printf(" (%d, %s)\n", -info[i].rc, strerror(-info[i].rc));
-            else
-                puts("");
-        }
-        idx += done;
-    } while ( left );
+    for ( i = 0; i < done; i++ )
+    {
+        char *name_str = name + name_off;
+
+        printf("%-40.*s| %s", len[i], name_str, state2str(info[i].state));
+        if ( info[i].rc )
+            printf(" (%d, %s)\n", -info[i].rc, strerror(-info[i].rc));
+        else
+            puts("");
+
+        name_off += len[i];
+    }
 
+error:
+    free(len);
+error_len:
     free(name);
+error_name:
     free(info);
-    free(len);
     return rc;
 }
 #undef MAX_LEN
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index f88cf3bc73..f486cb3021 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1163,7 +1163,6 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
 
     if ( list->nr &&
          (!guest_handle_okay(list->status, list->nr) ||
-          !guest_handle_okay(list->name, XEN_LIVEPATCH_NAME_SIZE * list->nr) ||
           !guest_handle_okay(list->len, list->nr)) )
         return -EINVAL;
 
@@ -1174,23 +1173,35 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
         return -EINVAL;
     }
 
+    list->name_total_size = 0;
     if ( list->nr )
     {
+        uint64_t name_offset = 0;
+
         list_for_each_entry( data, &payload_list, list )
         {
-            uint32_t len;
+            uint32_t name_len;
 
             if ( list->idx > i++ )
                 continue;
 
             status.state = data->state;
             status.rc = data->rc;
-            len = strlen(data->name) + 1;
+
+            name_len = strlen(data->name) + 1;
+            list->name_total_size += name_len;
+
+            if ( !guest_handle_subrange_okay(list->name, name_offset,
+                                             name_offset + name_len - 1) )
+            {
+                rc = -EINVAL;
+                break;
+            }
 
             /* N.B. 'idx' != 'i'. */
-            if ( __copy_to_guest_offset(list->name, idx * XEN_LIVEPATCH_NAME_SIZE,
-                                        data->name, len) ||
-                __copy_to_guest_offset(list->len, idx, &len, 1) ||
+            if ( __copy_to_guest_offset(list->name, name_offset,
+                                        data->name, name_len) ||
+                __copy_to_guest_offset(list->len, idx, &name_len, 1) ||
                 __copy_to_guest_offset(list->status, idx, &status, 1) )
             {
                 rc = -EFAULT;
@@ -1198,11 +1209,19 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
             }
 
             idx++;
+            name_offset += name_len;
 
             if ( (idx >= list->nr) || hypercall_preempt_check() )
                 break;
         }
     }
+    else
+    {
+        list_for_each_entry( data, &payload_list, list )
+        {
+            list->name_total_size += strlen(data->name) + 1;
+        }
+    }
     list->nr = payload_cnt - i; /* Remaining amount. */
     list->version = payload_version;
     spin_unlock(&payload_lock);
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index e18322350d..19aa01fbc7 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -926,10 +926,11 @@ struct xen_sysctl_livepatch_get {
  *
  * If the hypercall returns an positive number, it is the number (up to `nr`)
  * of the payloads returned, along with `nr` updated with the number of remaining
- * payloads, `version` updated (it may be the same across hypercalls. If it
- * varies the data is stale and further calls could fail). The `status`,
- * `name`, and `len`' are updated at their designed index value (`idx`) with
- * the returned value of data.
+ * payloads, `version` updated (it may be the same across hypercalls. If it varies
+ * the data is stale and further calls could fail) and the name_total_size
+ * containing total size of transfered data for the array.
+ * The `status`, `name`, `len` are updated at their designed index value (`idx`)
+ * with the returned value of data.
  *
  * If the hypercall returns E2BIG the `nr` is too big and should be
  * lowered. The upper limit of `nr` is left to the implemention.
@@ -952,11 +953,13 @@ struct xen_sysctl_livepatch_list {
                                                amount of payloads and version.
                                                OUT: How many payloads left. */
     uint32_t pad;                           /* IN: Must be zero. */
+    uint64_t name_total_size;               /* OUT: Total size of all transfer names */
     XEN_GUEST_HANDLE_64(xen_livepatch_status_t) status;  /* OUT. Must have enough
                                                space allocate for nr of them. */
     XEN_GUEST_HANDLE_64(char) name;         /* OUT: Array of names. Each member
-                                               MUST XEN_LIVEPATCH_NAME_SIZE in size.
-                                               Must have nr of them. */
+                                               may have an arbitrary length up to
+                                               XEN_LIVEPATCH_NAME_SIZE bytes. Must have
+                                               nr of them. */
     XEN_GUEST_HANDLE_64(uint32) len;        /* OUT: Array of lengths of name's.
                                                Must have nr of them. */
 };
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 13/14] livepatch: Add metadata runtime retrieval mechanism
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (11 preceding siblings ...)
  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 ` Pawel Wieczorkiewicz
  2019-08-21  8:19 ` [Xen-devel] [PATCH 14/14] livepatch: Add python bindings for livepatch operations Pawel Wieczorkiewicz
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

Extend the livepatch list operation to fetch also payloads' metadata.
This is achieved by extending the sysctl list interface with 2 extra
guest handles:
* metadata     - an array of arbitrary size strings
* metadata_len - an array of metadata strings' lengths (uin32_t each)

Payloads' metadata is a string of arbitrary size and does not have an
upper bound limit. It may also vary in size between payloads.

In order to let the userland allocate enough space for the incoming
data add a metadata total size field to the list sysctl operation and
fill it with total size of all payloads' metadata.

Extend the libxc to handle the metadata back-to-back data transfers
as well as metadata length array data transfers.

The xen-livepatch userland tool is extended to always display the
metadata for each received module. The metadata is received with the
following format: key=value\0key=value\0...key=value\0. The format is
modified to the following one: key=value;key=value;...key=value.
The new format allows to easily parse the metadata for a given module
by a machine.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 tools/libxc/include/xenctrl.h | 22 +++++++++++----
 tools/libxc/xc_misc.c         | 66 +++++++++++++++++++++++++++++++++++--------
 tools/misc/xen-livepatch.c    | 43 ++++++++++++++++++++++------
 xen/common/livepatch.c        | 22 +++++++++++----
 xen/include/public/sysctl.h   | 19 +++++++++----
 5 files changed, 134 insertions(+), 38 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index e0ebb586b6..7a3762f44e 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2561,7 +2561,7 @@ int xc_livepatch_get(xc_interface *xch,
 
 /*
  * Get a number of available payloads and get actual total size of
- * the payloads' name array.
+ * the payloads' name and metadata arrays.
  *
  * This functions is typically executed first before the xc_livepatch_list()
  * to obtain the sizes and correctly allocate all necessary data resources.
@@ -2572,13 +2572,16 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the hypercall error code value.
  */
 int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
-                                uint64_t *name_total_size);
+                                uint64_t *name_total_size,
+                                uint64_t *metadata_total_size);
 
 /*
  * The heart of this function is to get an array of the following objects:
  *   - xen_livepatch_status_t: states and return codes of payloads
  *   - name: names of payloads
  *   - len: lengths of corresponding payloads' names
+ *   - metadata: payloads' metadata
+ *   - metadata_len: lengths of corresponding payloads' metadata
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -2591,12 +2594,13 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * It is expected that the caller of this function will first issue the
  * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
- * as well as the current number of payload entries.
- * The total sizes are required and supplied via the 'name_total_size'
- * parameter.
+ * and all metadata as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size' and
+ * 'metadata_total_size' parameters.
  *
  * The 'max' is to be provided by the caller with the maximum number of
- * entries that 'info', 'name', 'len' arrays can be filled up with.
+ * entries that 'info', 'name', 'len', 'metadata' and 'metadata_len' arrays
+ * can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
@@ -2605,6 +2609,10 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
+ * Each entry in the 'metadata' array may have an arbitrary size.
+ *
+ * Each entry in the 'metadata_len' array is expected to be of uint32_t size.
+ *
  * The return value is zero if the hypercall completed successfully.
  * Note that the return value is _not_ the amount of entries filled
  * out - that is saved in 'done'.
@@ -2619,6 +2627,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
                       struct xen_livepatch_status *info,
                       char *name, uint32_t *len,
                       const uint64_t name_total_size,
+                      char *metadata, uint32_t *metadata_len,
+                      const uint64_t metadata_total_size,
                       unsigned int *done, unsigned int *left);
 
 /*
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index d787f3f29f..618113011d 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -663,7 +663,7 @@ int xc_livepatch_get(xc_interface *xch,
 
 /*
  * Get a number of available payloads and get actual total size of
- * the payloads' name array.
+ * the payloads' name and metadata arrays.
  *
  * This functions is typically executed first before the xc_livepatch_list()
  * to obtain the sizes and correctly allocate all necessary data resources.
@@ -674,12 +674,13 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the hypercall error code value.
  */
 int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
-                                uint64_t *name_total_size)
+                                uint64_t *name_total_size,
+                                uint64_t *metadata_total_size)
 {
     DECLARE_SYSCTL;
     int rc;
 
-    if ( !nr || !name_total_size )
+    if ( !nr || !name_total_size || !metadata_total_size )
     {
         errno = EINVAL;
         return -1;
@@ -695,6 +696,7 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
 
     *nr = sysctl.u.livepatch.u.list.nr;
     *name_total_size = sysctl.u.livepatch.u.list.name_total_size;
+    *metadata_total_size = sysctl.u.livepatch.u.list.metadata_total_size;
 
     return 0;
 }
@@ -704,6 +706,8 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *   - xen_livepatch_status_t: states and return codes of payloads
  *   - name: names of payloads
  *   - len: lengths of corresponding payloads' names
+ *   - metadata: payloads' metadata
+ *   - metadata_len: lengths of corresponding payloads' metadata
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -716,12 +720,13 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * It is expected that the caller of this function will first issue the
  * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
- * as well as the current number of payload entries.
- * The total sizes are required and supplied via the 'name_total_size'
- * parameter.
+ * and all metadata as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size' and
+ * 'metadata_total_size' parameters.
  *
  * The 'max' is to be provided by the caller with the maximum number of
- * entries that 'info', 'name', 'len' arrays can be filled up with.
+ * entries that 'info', 'name', 'len', 'metadata' and 'metadata_len' arrays
+ * can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
@@ -730,6 +735,10 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
+ * Each entry in the 'metadata' array may have an arbitrary size.
+ *
+ * Each entry in the 'metadata_len' array is expected to be of uint32_t size.
+ *
  * The return value is zero if the hypercall completed successfully.
  * Note that the return value is _not_ the amount of entries filled
  * out - that is saved in 'done'.
@@ -744,6 +753,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
                       struct xen_livepatch_status *info,
                       char *name, uint32_t *len,
                       const uint64_t name_total_size,
+                      char *metadata, uint32_t *metadata_len,
+                      const uint64_t metadata_total_size,
                       unsigned int *done, unsigned int *left)
 {
     int rc;
@@ -752,19 +763,22 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
     DECLARE_HYPERCALL_BOUNCE(info, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     DECLARE_HYPERCALL_BOUNCE(name, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     DECLARE_HYPERCALL_BOUNCE(len, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_HYPERCALL_BOUNCE(metadata, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_HYPERCALL_BOUNCE(metadata_len, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     uint32_t max_batch_sz, nr;
     uint32_t version = 0, retries = 0;
     uint32_t adjust = 0;
-    off_t name_off = 0;
-    uint64_t name_sz;
+    off_t name_off = 0, metadata_off = 0;
+    uint64_t name_sz, metadata_sz;
 
-    if ( !max || !info || !name || !len || !done || !left )
+    if ( !max || !info || !name || !len ||
+         !metadata || !metadata_len || !done || !left )
     {
         errno = EINVAL;
         return -1;
     }
 
-    if ( name_total_size == 0 )
+    if ( name_total_size == 0 || metadata_total_size == 0 )
     {
         errno = ENOENT;
         return -1;
@@ -777,10 +791,11 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
 
     max_batch_sz = max;
     name_sz = name_total_size;
+    metadata_sz = metadata_total_size;
     *done = 0;
     *left = 0;
     do {
-        uint64_t _name_sz;
+        uint64_t _name_sz, _metadata_sz;
 
         /*
          * The first time we go in this loop our 'max' may be bigger
@@ -803,10 +818,14 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         HYPERCALL_BOUNCE_SET_SIZE(info, nr * sizeof(*info));
         HYPERCALL_BOUNCE_SET_SIZE(name, name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, nr * sizeof(*len));
+        HYPERCALL_BOUNCE_SET_SIZE(metadata, metadata_sz);
+        HYPERCALL_BOUNCE_SET_SIZE(metadata_len, nr * sizeof(*metadata_len));
         /* Move the pointer to proper offset into 'info'. */
         (HYPERCALL_BUFFER(info))->ubuf = info + *done;
         (HYPERCALL_BUFFER(name))->ubuf = name + name_off;
         (HYPERCALL_BUFFER(len))->ubuf = len + *done;
+        (HYPERCALL_BUFFER(metadata))->ubuf = metadata + metadata_off;
+        (HYPERCALL_BUFFER(metadata_len))->ubuf = metadata_len + *done;
         /* Allocate memory. */
         rc = xc_hypercall_bounce_pre(xch, info);
         if ( rc )
@@ -820,9 +839,19 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         if ( rc )
             break;
 
+        rc = xc_hypercall_bounce_pre(xch, metadata);
+        if ( rc )
+            break;
+
+        rc = xc_hypercall_bounce_pre(xch, metadata_len);
+        if ( rc )
+            break;
+
         set_xen_guest_handle(sysctl.u.livepatch.u.list.status, info);
         set_xen_guest_handle(sysctl.u.livepatch.u.list.name, name);
         set_xen_guest_handle(sysctl.u.livepatch.u.list.len, len);
+        set_xen_guest_handle(sysctl.u.livepatch.u.list.metadata, metadata);
+        set_xen_guest_handle(sysctl.u.livepatch.u.list.metadata_len, metadata_len);
 
         rc = do_sysctl(xch, &sysctl);
         /*
@@ -839,6 +868,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
             xc_hypercall_bounce_post(xch, info);
             xc_hypercall_bounce_post(xch, name);
             xc_hypercall_bounce_post(xch, len);
+            xc_hypercall_bounce_post(xch, metadata);
+            xc_hypercall_bounce_post(xch, metadata_len);
             continue;
         }
         else if ( rc < 0 ) /* For all other errors we bail out. */
@@ -863,6 +894,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
             xc_hypercall_bounce_post(xch, info);
             xc_hypercall_bounce_post(xch, name);
             xc_hypercall_bounce_post(xch, len);
+            xc_hypercall_bounce_post(xch, metadata);
+            xc_hypercall_bounce_post(xch, metadata_len);
             continue;
         }
 
@@ -875,17 +908,24 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         }
         *left = sysctl.u.livepatch.u.list.nr; /* Total remaining count. */
         _name_sz = sysctl.u.livepatch.u.list.name_total_size; /* Total received name size. */
+        _metadata_sz = sysctl.u.livepatch.u.list.metadata_total_size; /* Total received metadata size. */
         /* Copy only up 'rc' of data' - we could add 'min(rc,nr) if desired. */
         HYPERCALL_BOUNCE_SET_SIZE(info, (rc * sizeof(*info)));
         HYPERCALL_BOUNCE_SET_SIZE(name, _name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, (rc * sizeof(*len)));
+        HYPERCALL_BOUNCE_SET_SIZE(metadata, _metadata_sz);
+        HYPERCALL_BOUNCE_SET_SIZE(metadata_len, (rc * sizeof(*metadata_len)));
         /* Bounce the data and free the bounce buffer. */
         xc_hypercall_bounce_post(xch, info);
         xc_hypercall_bounce_post(xch, name);
         xc_hypercall_bounce_post(xch, len);
+        xc_hypercall_bounce_post(xch, metadata);
+        xc_hypercall_bounce_post(xch, metadata_len);
 
         name_sz -= _name_sz;
         name_off += _name_sz;
+        metadata_sz -= _metadata_sz;
+        metadata_off += _metadata_sz;
 
         /* And update how many elements of info we have copied into. */
         *done += rc;
@@ -898,6 +938,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         xc_hypercall_bounce_post(xch, len);
         xc_hypercall_bounce_post(xch, name);
         xc_hypercall_bounce_post(xch, info);
+        xc_hypercall_bounce_post(xch, metadata);
+        xc_hypercall_bounce_post(xch, metadata_len);
     }
 
     return rc > 0 ? 0 : rc;
diff --git a/tools/misc/xen-livepatch.c b/tools/misc/xen-livepatch.c
index 8ac3d567fc..61d4950001 100644
--- a/tools/misc/xen-livepatch.c
+++ b/tools/misc/xen-livepatch.c
@@ -69,9 +69,11 @@ static int list_func(int argc, char *argv[])
     unsigned int nr, done, left, i;
     xen_livepatch_status_t *info = NULL;
     char *name = NULL;
+    char *metadata = NULL;
     uint32_t *len = NULL;
-    uint64_t name_total_size;
-    off_t name_off;
+    uint32_t *metadata_len = NULL;
+    uint64_t name_total_size, metadata_total_size;
+    off_t name_off, metadata_off;
     int rc = ENOMEM;
 
     if ( argc )
@@ -81,7 +83,7 @@ static int list_func(int argc, char *argv[])
     }
     done = left = 0;
 
-    rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size);
+    rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size, &metadata_total_size);
     if ( rc )
     {
         rc = errno;
@@ -109,12 +111,23 @@ static int list_func(int argc, char *argv[])
     if ( !len )
         goto error_len;
 
+    metadata = malloc(metadata_total_size * sizeof(*metadata));
+    if ( !metadata )
+        goto error_metadata;
+
+    metadata_len = malloc(nr * sizeof(*metadata_len));
+    if ( !metadata_len )
+        goto error_metadata_len;
+
     memset(info, 'A', nr * sizeof(*info));
     memset(name, 'B', name_total_size * sizeof(*name));
     memset(len, 'C', nr * sizeof(*len));
-    name_off = 0;
+    memset(metadata, 'D', metadata_total_size * sizeof(*metadata));
+    memset(metadata_len, 'E', nr * sizeof(*metadata_len));
+    name_off = metadata_off = 0;
 
-    rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size, &done, &left);
+    rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size,
+                           metadata, metadata_len, metadata_total_size, &done, &left);
     if ( rc || done != nr || left > 0)
     {
         rc = errno;
@@ -124,23 +137,35 @@ static int list_func(int argc, char *argv[])
         goto error;
     }
 
-    fprintf(stdout," ID                                     | status\n"
-                   "----------------------------------------+------------\n");
+    fprintf(stdout," ID                                     | status     | metadata\n"
+                   "----------------------------------------+------------+---------------\n");
 
     for ( i = 0; i < done; i++ )
     {
+        unsigned int j;
         char *name_str = name + name_off;
+        char *metadata_str = metadata + metadata_off;
 
         printf("%-40.*s| %s", len[i], name_str, state2str(info[i].state));
         if ( info[i].rc )
-            printf(" (%d, %s)\n", -info[i].rc, strerror(-info[i].rc));
+            printf(" (%d, %s)    | ", -info[i].rc, strerror(-info[i].rc));
         else
-            puts("");
+            printf("    | ");
+
+        /* Replace all '\0' with semi-colons. */
+        for ( j = 0; j < metadata_len[i] - 1; j++ )
+            metadata_str[j] = (metadata_str[j] ?: ';');
+        printf("%.*s\n", metadata_len[i], metadata_str);
 
         name_off += len[i];
+        metadata_off += metadata_len[i];
     }
 
 error:
+    free(metadata_len);
+error_metadata_len:
+    free(metadata);
+error_metadata:
     free(len);
 error_len:
     free(name);
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index f486cb3021..49a76f1029 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1163,7 +1163,8 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
 
     if ( list->nr &&
          (!guest_handle_okay(list->status, list->nr) ||
-          !guest_handle_okay(list->len, list->nr)) )
+          !guest_handle_okay(list->len, list->nr) ||
+          !guest_handle_okay(list->metadata_len, list->nr)) )
         return -EINVAL;
 
     spin_lock(&payload_lock);
@@ -1174,13 +1175,14 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
     }
 
     list->name_total_size = 0;
+    list->metadata_total_size = 0;
     if ( list->nr )
     {
-        uint64_t name_offset = 0;
+        uint64_t name_offset = 0, metadata_offset = 0;
 
         list_for_each_entry( data, &payload_list, list )
         {
-            uint32_t name_len;
+            uint32_t name_len, metadata_len;
 
             if ( list->idx > i++ )
                 continue;
@@ -1191,8 +1193,13 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
             name_len = strlen(data->name) + 1;
             list->name_total_size += name_len;
 
+            metadata_len = data->metadata.len;
+            list->metadata_total_size += metadata_len;
+
             if ( !guest_handle_subrange_okay(list->name, name_offset,
-                                             name_offset + name_len - 1) )
+                                             name_offset + name_len - 1) ||
+                 !guest_handle_subrange_okay(list->metadata, metadata_offset,
+                                             metadata_offset + metadata_len - 1) )
             {
                 rc = -EINVAL;
                 break;
@@ -1202,7 +1209,10 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
             if ( __copy_to_guest_offset(list->name, name_offset,
                                         data->name, name_len) ||
                 __copy_to_guest_offset(list->len, idx, &name_len, 1) ||
-                __copy_to_guest_offset(list->status, idx, &status, 1) )
+                __copy_to_guest_offset(list->status, idx, &status, 1) ||
+                __copy_to_guest_offset(list->metadata, metadata_offset,
+                                       data->metadata.data, metadata_len) ||
+                __copy_to_guest_offset(list->metadata_len, idx, &metadata_len, 1) )
             {
                 rc = -EFAULT;
                 break;
@@ -1210,6 +1220,7 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
 
             idx++;
             name_offset += name_len;
+            metadata_offset += metadata_len;
 
             if ( (idx >= list->nr) || hypercall_preempt_check() )
                 break;
@@ -1220,6 +1231,7 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
         list_for_each_entry( data, &payload_list, list )
         {
             list->name_total_size += strlen(data->name) + 1;
+            list->metadata_total_size += data->metadata.len;
         }
     }
     list->nr = payload_cnt - i; /* Remaining amount. */
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 19aa01fbc7..3cf8216d6e 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -921,16 +921,17 @@ struct xen_sysctl_livepatch_get {
 };
 
 /*
- * Retrieve an array of abbreviated status and names of payloads that are
- * loaded in the hypervisor.
+ * Retrieve an array of abbreviated status, names and metadata of payloads that
+ * are loaded in the hypervisor.
  *
  * If the hypercall returns an positive number, it is the number (up to `nr`)
  * of the payloads returned, along with `nr` updated with the number of remaining
  * payloads, `version` updated (it may be the same across hypercalls. If it varies
- * the data is stale and further calls could fail) and the name_total_size
- * containing total size of transfered data for the array.
- * The `status`, `name`, `len` are updated at their designed index value (`idx`)
- * with the returned value of data.
+ * the data is stale and further calls could fail), `name_total_size` and
+ * `metadata_total_size` containing total sizes of transfered data for both the
+ * arrays.
+ * The `status`, `name`, `len`, `metadata` and `metadata_len` are updated at their
+ * designed index value (`idx`) with the returned value of data.
  *
  * If the hypercall returns E2BIG the `nr` is too big and should be
  * lowered. The upper limit of `nr` is left to the implemention.
@@ -954,6 +955,7 @@ struct xen_sysctl_livepatch_list {
                                                OUT: How many payloads left. */
     uint32_t pad;                           /* IN: Must be zero. */
     uint64_t name_total_size;               /* OUT: Total size of all transfer names */
+    uint64_t metadata_total_size;           /* OUT: Total size of all transfer metadata */
     XEN_GUEST_HANDLE_64(xen_livepatch_status_t) status;  /* OUT. Must have enough
                                                space allocate for nr of them. */
     XEN_GUEST_HANDLE_64(char) name;         /* OUT: Array of names. Each member
@@ -962,6 +964,11 @@ struct xen_sysctl_livepatch_list {
                                                nr of them. */
     XEN_GUEST_HANDLE_64(uint32) len;        /* OUT: Array of lengths of name's.
                                                Must have nr of them. */
+    XEN_GUEST_HANDLE_64(char) metadata;     /* OUT: Array of metadata strings. Each
+                                               member may have an arbitrary length.
+                                               Must have nr of them. */
+    XEN_GUEST_HANDLE_64(uint32) metadata_len;  /* OUT: Array of lengths of metadata's.
+                                                  Must have nr of them. */
 };
 
 /*
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH 14/14] livepatch: Add python bindings for livepatch operations
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (12 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 13/14] livepatch: Add metadata runtime retrieval mechanism Pawel Wieczorkiewicz
@ 2019-08-21  8:19 ` 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
  14 siblings, 1 reply; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-21  8:19 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Wei Liu, Ian Jackson, mpohlack,
	Marek Marczykowski-Górecki, Pawel Wieczorkiewicz

Extend the XC python bindings library to support also all common
livepatch operations and actions.

Add the python bindings for the following operations:
- status (pyxc_livepatch_status):
  Requires a payload name as an input.
  Returns a status dict containing a state string and a return code
  integer.
- action (pyxc_livepatch_action):
  Requires a payload name and an action id as an input. Timeout and
  flags are optional parameters.
  Returns a return code integer.
- upload (pyxc_livepatch_upload):
  Requires a payload name and a module's filename as an input.
  Returns a return code integer.
- list (pyxc_livepatch_list):
  Takes no parameters.
  Returns a list of dicts containing each payload's:
  * name as a string
  * state as a string
  * return code as an integer
  * list of metadata key=value strings

Each functions throws an exception error based on the errno value
received from its corresponding libxc function call.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Martin Mazein <amazein@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 tools/python/xen/lowlevel/xc/xc.c | 273 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 273 insertions(+)

diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 7f0358ba9c..368739b996 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -2011,6 +2011,230 @@ static PyObject *pyflask_access(PyObject *self, PyObject *args,
     return Py_BuildValue("i",ret);
 }
 
+static PyObject *pyxc_livepatch_status(XcObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    xen_livepatch_status_t status;
+    PyObject *info_dict = NULL;
+    char *name;
+    int rc;
+
+    static char *kwd_list[] = { "name", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &name) )
+        goto error;
+
+    rc = xc_livepatch_get(self->xc_handle, name, &status);
+    if ( rc )
+        goto error;
+
+    info_dict = Py_BuildValue(
+            "{s:i,s:i}",
+            "state",    status.state,
+            "rc",       status.rc);
+
+error:
+    return info_dict ?: pyxc_error_to_exception(self->xc_handle);
+}
+
+static PyObject *pyxc_livepatch_action(XcObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    int (*action_func)(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+    char *name;
+    unsigned int action;
+    uint32_t timeout;
+    uint64_t flags;
+    int rc;
+
+    static char *kwd_list[] = { "name", "action", "timeout", "flags", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "sI|Ik", kwd_list,
+                                      &name, &action, &timeout, &flags) )
+        goto error;
+
+    switch (action)
+    {
+    case LIVEPATCH_ACTION_UNLOAD:
+        action_func = xc_livepatch_unload;
+        break;
+    case LIVEPATCH_ACTION_REVERT:
+        action_func = xc_livepatch_revert;
+        break;
+    case LIVEPATCH_ACTION_APPLY:
+        action_func = xc_livepatch_apply;
+        break;
+    case LIVEPATCH_ACTION_REPLACE:
+        action_func = xc_livepatch_replace;
+        break;
+    default:
+        goto error;
+    }
+
+    rc = action_func(self->xc_handle, name, timeout, flags);
+    if ( rc )
+        goto error;
+
+    return Py_BuildValue("i", rc);
+error:
+    return pyxc_error_to_exception(self->xc_handle);
+}
+
+static PyObject *pyxc_livepatch_upload(XcObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    unsigned char *fbuf = MAP_FAILED;
+    char *name, *filename;
+    struct stat buf;
+    int fd = 0, rc;
+    ssize_t len;
+
+    static char *kwd_list[] = { "name", "filename", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwd_list,
+                                      &name, &filename))
+        goto error;
+
+    fd = open(filename, O_RDONLY);
+    if ( fd < 0 )
+        goto error;
+
+    if ( stat(filename, &buf) != 0 )
+        goto error;
+
+    len = buf.st_size;
+    fbuf = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+    if ( fbuf == MAP_FAILED )
+        goto error;
+
+    rc = xc_livepatch_upload(self->xc_handle, name, fbuf, len);
+    if ( rc )
+        goto error;
+
+    if ( munmap(fbuf, len) )
+    {
+        fbuf = MAP_FAILED;
+        goto error;
+    }
+    close(fd);
+
+    return Py_BuildValue("i", rc);;
+error:
+    if ( fbuf != MAP_FAILED )
+        munmap(fbuf, len);
+    if ( fd >= 0 )
+        close(fd);
+    return pyxc_error_to_exception(self->xc_handle);
+}
+
+static PyObject *pyxc_livepatch_list(XcObject *self)
+{
+    PyObject *list;
+    unsigned int nr, done, left, i;
+    xen_livepatch_status_t *info = NULL;
+    char *name = NULL;
+    char *metadata = NULL;
+    uint32_t *len = NULL;
+    uint32_t *metadata_len = NULL;
+    uint64_t name_total_size, metadata_total_size;
+    off_t name_off, metadata_off;
+    int rc;
+
+    rc = xc_livepatch_list_get_sizes(self->xc_handle, &nr,
+                                     &name_total_size, &metadata_total_size);
+    if ( rc )
+        goto error;
+
+    if ( nr == 0 )
+        return PyList_New(0);
+
+    rc = ENOMEM;
+    info = malloc(nr * sizeof(*info));
+    if ( !info )
+        goto error;
+
+    name = malloc(name_total_size * sizeof(*name));
+    if ( !name )
+        goto error;
+
+    len = malloc(nr * sizeof(*len));
+    if ( !len )
+        goto error;
+
+    metadata = malloc(metadata_total_size * sizeof(*metadata));
+    if ( !metadata )
+        goto error;
+
+    metadata_len = malloc(nr * sizeof(*metadata_len));
+    if ( !metadata_len )
+        goto error;
+
+    rc = xc_livepatch_list(self->xc_handle, nr, 0, info,
+                           name, len, name_total_size,
+                           metadata, metadata_len, metadata_total_size,
+                           &done, &left);
+    if ( rc )
+        goto error;
+
+    list = PyList_New(0);
+    name_off = metadata_off = 0;
+    for ( i = 0; i < done; i++ )
+    {
+        PyObject *info_dict, *metadata_list;
+        char *name_str, *metadata_str;
+
+        name_str = name + name_off;
+        metadata_str = metadata + metadata_off;
+
+        metadata_list = PyList_New(0);
+        for ( char *s = metadata_str; s < metadata_str + metadata_len[i]; s += strlen(s) + 1 )
+        {
+            PyObject *field = Py_BuildValue("s", s);
+            if ( field == NULL )
+            {
+                Py_DECREF(list);
+                Py_DECREF(metadata_list);
+                rc = EFAULT;
+                goto error;
+            }
+
+            PyList_Append(metadata_list, field);
+            Py_DECREF(field);
+        }
+
+        info_dict = Py_BuildValue(
+            "{s:s,s:i,s:i,s:N}",
+            "name",     name_str,
+            "state",    info[i].state,
+            "rc",       info[i].rc,
+            "metadata", metadata_list);
+
+        if ( info_dict == NULL )
+        {
+            Py_DECREF(list);
+            Py_DECREF(metadata_list);
+            rc = EFAULT;
+            goto error;
+        }
+        PyList_Append(list, info_dict);
+        Py_DECREF(info_dict);
+
+        name_off += len[i];
+        metadata_off += metadata_len[i];
+    }
+
+error:
+    free(info);
+    free(name);
+    free(len);
+    free(metadata);
+    free(metadata_len);
+    return rc ? pyxc_error_to_exception(self->xc_handle) : list;
+}
+
 static PyMethodDef pyxc_methods[] = {
     { "domain_create", 
       (PyCFunction)pyxc_domain_create, 
@@ -2587,6 +2811,44 @@ static PyMethodDef pyxc_methods[] = {
       "Returns: [int]: 0 on all permission granted; -1 if any permissions are \
        denied\n" }, 
 
+    { "livepatch_status",
+      (PyCFunction)pyxc_livepatch_status,
+      METH_KEYWORDS, "\n"
+      "Gets current state and return code for a specified module.\n"
+      " name     [str]: Module name to be used\n"
+      "Returns: [dict] on success; throwing an exception on error\n"
+      " state    [int]: Module current state: CHECKED or APPLIED\n"
+      " rc       [int]: Return code of last module's operation\n" },
+
+    { "livepatch_upload",
+      (PyCFunction)pyxc_livepatch_upload,
+      METH_KEYWORDS, "\n"
+      "Uploads a module with specified name from filename.\n"
+      " name     [str]: Module name to be used\n"
+      " filename [str]: Filename of a module to be uploaded\n"
+      "Returns: [int] 0 on success; throwing an exception on error\n" },
+
+    { "livepatch_action",
+      (PyCFunction)pyxc_livepatch_action,
+      METH_KEYWORDS, "\n"
+      "Performs an action (unload, revert, apply or replace) on a specified \
+       module.\n"
+      " name      [str]: Module name to be used\n"
+      " action   [uint]: Action enum id\n"
+      " timeout  [uint]: Action scheduled execution timeout\n"
+      " flags   [ulong]: Flags specifying action's extra parameters\n"
+      "Returns: [int] 0 on success; throwing an exception on error\n" },
+
+    { "livepatch_list",
+      (PyCFunction)pyxc_livepatch_list,
+      METH_NOARGS, "\n"
+      "List all uploaded livepatch modules with their current state and metadata.\n"
+      "Returns: [list of dicts] on success; throwing an exception on error\n"
+      " name     [str]: Module name\n"
+      " state    [int]: Module current state: CHECKED or APPLIED\n"
+      " rc       [int]: Return code of last module's operation\n"
+      " metadata [list]: List of module's metadata 'key=value' strings\n" },
+
     { NULL, NULL, 0, NULL }
 };
 
@@ -2698,6 +2960,17 @@ PyMODINIT_FUNC initxc(void)
     PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
     PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT2", XEN_SCHEDULER_CREDIT2);
 
+    /* Expose livepatch constants to Python */
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_UNLOAD", LIVEPATCH_ACTION_UNLOAD);
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_REVERT", LIVEPATCH_ACTION_REVERT);
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_APPLY", LIVEPATCH_ACTION_APPLY);
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_REPLACE", LIVEPATCH_ACTION_REPLACE);
+
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_APPLY_NODEPS", LIVEPATCH_ACTION_APPLY_NODEPS);
+
+    PyModule_AddIntConstant(m, "LIVEPATCH_STATE_APPLIED", LIVEPATCH_STATE_APPLIED);
+    PyModule_AddIntConstant(m, "LIVEPATCH_STATE_CHECKED", LIVEPATCH_STATE_CHECKED);
+
 #if PY_MAJOR_VERSION >= 3
     return m;
 #endif
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 01/14] livepatch: Always check hypervisor build ID upon hotpatch upload
  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
  0 siblings, 0 replies; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-21 18:16 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan, Ross Lagerwall,
	Julien Grall, Jan Beulich

On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
> This change is part of a independant stacked hotpatch modules
> feature. This feature allows to bypass dependencies between modules
> upon loading, but still verifies Xen build ID matching.
> 
> In order to prevent (up)loading any hotpatches built for different
> hypervisor version as indicated by the Xen Build ID, add checking for
> the payload's vs Xen's build id match.
> 
> To achieve that embed into every hotpatch another section with a
> dedicated hypervisor build id in it. After the payload is loaded and
> the .livepatch.xen_depends section becomes available, perform the
> check and reject the payload if there is no match.
> 
> 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: Eslam Elnikety <elnikety@amazon.de>
> Reviewed-by: Martin Pohlack <mpohlack@amazon.de>

> +# This one always fails upon upload, because it deliberetely

I think that is spelled a bit different :-)

But besides that looks perfect. Ross, you Ok with this one too?

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  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 10:29   ` Julien Grall
  2 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-21 18:28 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan, Ross Lagerwall,
	Julien Grall, Jan Beulich, Roger Pau Monné

On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
>   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

Replying here as well. Could you use part of the 'opaque[31]' space 
instead for this field?

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations
  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
  1 sibling, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-21 18:30 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan, Ross Lagerwall,
	Julien Grall, Jan Beulich

On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
>   typedef enum livepatch_func_state {
>       LIVEPATCH_FUNC_NOT_APPLIED = 0,
>       LIVEPATCH_FUNC_APPLIED = 1
> @@ -838,11 +850,12 @@ struct livepatch_func {
>       uint32_t new_size;
>       uint32_t old_size;
>       uint8_t version;        /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
> -    uint8_t opaque[31];
> +    uint8_t opaque[LIVEPATCH_OPAQUE_SIZE];
>   #if defined CONFIG_X86
>       uint8_t applied;
>       uint8_t _pad[7];
>   #endif
> +    livepatch_expectation_t expect;
>   };

Aaah, now I understand why you decide to create a new field _pad and 
applied field!

Any particular reason why the version can't be 2 since this can be part 
of this changeset? Also you would need to have a Documentation change.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks
  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
  0 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-21 18:31 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: Ross Lagerwall, wipawel, mpohlack

On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
> 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.
> 

This logic looks legit, but I was wondering if you would be up for a 
writing a small test-case(s) livepatch that would exercise these parts 
just to make sure nothing in the future would screw it up?


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-21 18:28   ` Konrad Rzeszutek Wilk
@ 2019-08-21 19:00     ` Wieczorkiewicz, Pawel
  0 siblings, 0 replies; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-21 19:00 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Wieczorkiewicz, Pawel, Julien Grall, Jan Beulich,
	xen-devel, Roger Pau Monné


> On 21. Aug 2019, at 20:28, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> wrote:
> 
> On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
>>  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
> 
> Replying here as well. Could you use part of the 'opaque[31]' space instead for this field?


No, as explained earlier, I must not do that. The opaque[] is not a padding.

Best Regards,
Pawel Wieczorkiewicz



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

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations
  2019-08-21 18:30   ` Konrad Rzeszutek Wilk
@ 2019-08-21 19:02     ` Wieczorkiewicz, Pawel
  0 siblings, 0 replies; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-21 19:02 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Wieczorkiewicz, Pawel, Julien Grall, Jan Beulich,
	xen-devel


> On 21. Aug 2019, at 20:30, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> wrote:
> 
> On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
>>  typedef enum livepatch_func_state {
>>      LIVEPATCH_FUNC_NOT_APPLIED = 0,
>>      LIVEPATCH_FUNC_APPLIED = 1
>> @@ -838,11 +850,12 @@ struct livepatch_func {
>>      uint32_t new_size;
>>      uint32_t old_size;
>>      uint8_t version;        /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
>> -    uint8_t opaque[31];
>> +    uint8_t opaque[LIVEPATCH_OPAQUE_SIZE];
>>  #if defined CONFIG_X86
>>      uint8_t applied;
>>      uint8_t _pad[7];
>>  #endif
>> +    livepatch_expectation_t expect;
>>  };
> 
> Aaah, now I understand why you decide to create a new field _pad and applied field!
> 

Yup, that was premeditated! :-)

> Any particular reason why the version can't be 2 since this can be part of this changeset? Also you would need to have a Documentation change.

It surely can be 2. I wasn’t sure before if the changes could go together. Will change to 2 for both

And, I will also update the doc. 

Best Regards,
Pawel Wieczorkiewicz



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

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks
  2019-08-21 18:31   ` Konrad Rzeszutek Wilk
@ 2019-08-21 19:06     ` Wieczorkiewicz, Pawel
  2019-08-26 14:30       ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-21 19:06 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Pohlack, Martin, Wieczorkiewicz, Pawel, Ross Lagerwall,
	xen-devel, xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 2083 bytes --]


On 21. Aug 2019, at 20:31, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com<mailto:konrad.wilk@oracle.com>> wrote:

On 8/21/19 4:19 AM, Pawel Wieczorkiewicz wrote:
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.

This logic looks legit, but I was wondering if you would be up for a writing a small test-case(s) livepatch that would exercise these parts just to make sure nothing in the future would screw it up?

Yes, I could do that. But, I would like to discuss (get guidelines about) the expected test coverage.
With this sort of changes, there is an unlimited set of test-cases to be created. So, I would like to focus on a few most important.
I am missing knowledge how these test cases are supposed to be used… hence the ask.

Best Regards,
Pawel Wieczorkiewicz



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



[-- Attachment #1.2: Type: text/html, Size: 5034 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  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 21:34   ` Julien Grall
  2019-08-22  7:44     ` Wieczorkiewicz, Pawel
  2019-08-22 10:29   ` Julien Grall
  2 siblings, 1 reply; 66+ messages in thread
From: Julien Grall @ 2019-08-21 21:34 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan,
	Ross Lagerwall, Jan Beulich, Roger Pau Monné

Hi Pawel,

On 8/21/19 9:19 AM, Pawel Wieczorkiewicz wrote:
> 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.

Is this going to break livepatch on Arm? If so, do you have any plan to 
fix it?

[...]

> 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);

I doubt livepatch on Arm will compile after this change.

>   void arch_livepatch_post_action(void);
>   
>   void arch_livepatch_mask(void);

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-21 21:34   ` Julien Grall
@ 2019-08-22  7:44     ` Wieczorkiewicz, Pawel
  2019-08-22 10:07       ` Julien Grall
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-22  7:44 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Jan Beulich,
	xen-devel, Roger Pau Monné


[-- Attachment #1.1: Type: text/plain, Size: 2264 bytes --]


On 21. Aug 2019, at 23:34, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com>> wrote:

Hi Pawel,

Hi Julien,


On 8/21/19 9:19 AM, Pawel Wieczorkiewicz wrote:
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.

Is this going to break livepatch on Arm? If so, do you have any plan to fix it?


No, I do not think it is. But, I am unable to test on Arm (No access to HW and SW),
so I took the conservative approach here.

[...]

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);

I doubt livepatch on Arm will compile after this change.


What would be you suggestion then?
Shall I limit the change to X86 everywhere
 Or maybe drop the compilation flag completely?

 void arch_livepatch_post_action(void);
   void arch_livepatch_mask(void);

Cheers,

--
Julien Grall

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 4570 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22  7:44     ` Wieczorkiewicz, Pawel
@ 2019-08-22 10:07       ` Julien Grall
  2019-08-22 10:20         ` Wieczorkiewicz, Pawel
  0 siblings, 1 reply; 66+ messages in thread
From: Julien Grall @ 2019-08-22 10:07 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Ross Lagerwall, Jan Beulich, xen-devel,
	Roger Pau Monné

Hi,

On 22/08/2019 08:44, Wieczorkiewicz, Pawel wrote:
> 
>> On 21. Aug 2019, at 23:34, Julien Grall <julien.grall@arm.com 
>> <mailto:julien.grall@arm.com>> wrote:
>> On 8/21/19 9:19 AM, Pawel Wieczorkiewicz wrote:
>>> 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.
>>
>> Is this going to break livepatch on Arm? If so, do you have any plan to fix it?
>>
> 
> No, I do not think it is. But, I am unable to test on Arm (No access to HW and SW),
> so I took the conservative approach here.
Arm provides decent free model (see FoundationModel) that you can use for basic 
testing. Alternatively, you QEMU also support virtualization extension.

Let me have a look at the code (I will answer separately) to see if I can spot 
anything.

> 
>> [...]
>>
>>> 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);
>>
>> I doubt livepatch on Arm will compile after this change.
>>
> 
> What would be you suggestion then?

Cross-compiler are nowadays widely available. So build testing your changes in 
common code would be the minimum.

In this case, as you dropped the const from the prototype, you will need to do 
the same in the declaration.

> Shall I limit the change to X86 everywhere
>   Or maybe drop the compilation flag completely?

I am a bit confused. Which compilation flag do you refer to?

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 10:07       ` Julien Grall
@ 2019-08-22 10:20         ` Wieczorkiewicz, Pawel
  2019-08-22 10:43           ` Julien Grall
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-22 10:20 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Jan Beulich,
	xen-devel, Roger Pau Monné


[-- Attachment #1.1: Type: text/plain, Size: 2212 bytes --]


On 22. Aug 2019, at 12:07, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com>> wrote:

Hi,

On 22/08/2019 08:44, Wieczorkiewicz, Pawel wrote:


…snip...


Is this going to break livepatch on Arm? If so, do you have any plan to fix it?

No, I do not think it is. But, I am unable to test on Arm (No access to HW and SW),
so I took the conservative approach here.
Arm provides decent free model (see FoundationModel) that you can use for basic testing. Alternatively, you QEMU also support virtualization extension.

Let me have a look at the code (I will answer separately) to see if I can spot anything.

[...]

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);

I doubt livepatch on Arm will compile after this change.

What would be you suggestion then?

Cross-compiler are nowadays widely available. So build testing your changes in common code would be the minimum.


I wish it was that simple. Nevertheless, I will try to prepare an environment to perform such builds.

In this case, as you dropped the const from the prototype, you will need to do the same in the declaration.


Yes, but I see 2 options here:
- Enable the feature also for Arm (I prefer that, but will not be able to test that in nearest future)
- Keep Arm excluded and sprinkle code with #ifdef CONFIG_X86

Shall I limit the change to X86 everywhere
 Or maybe drop the compilation flag completely?

I am a bit confused. Which compilation flag do you refer to?


CONFIG_X86

Cheers,

--
Julien Grall

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 4943 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  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 21:34   ` Julien Grall
@ 2019-08-22 10:29   ` Julien Grall
  2019-08-22 11:02     ` Wieczorkiewicz, Pawel
  2 siblings, 1 reply; 66+ messages in thread
From: Julien Grall @ 2019-08-22 10:29 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan,
	Ross Lagerwall, Jan Beulich, Roger Pau Monné

Hi Pawel,

On 21/08/2019 09:19, Pawel Wieczorkiewicz wrote:
> 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@amazon.de>
> Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
> Reviewed-by: Bjoern Doebel <doebel@amazon.de>
> Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
> ---
>   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;
> +    }

Does this need to in arch specific code?

> +
>       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 )

Per the definition of livepath_func, the field "applied" only exists for x86. So 
this will not compiled on Arm.

> +        {
> +            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) )

Regardless the compilation issue above, none of the common code will set the 
state. So for Arm, this would likely mean the function return false.

> +            panic("livepatch: partially applied payload '%s'!\n", data->name);

I can see at least a case where the panic can be reached here. Per the changes 
in arch_livepatch_apply(), f->applied will only be set to LIVEPATCH_FUNC_APPLIED 
if livepatch_insn_len() is not 0.

I don't know whether livepatch_insn_len() can ever return 0 as my livepatch 
knowledge is limited. But the code live little doubt this is a theoritical 
possibility that after this patch will turn into crashing Xen.

More generally, I am not very comfortable to see panic() in the middle of the 
code. Could you explain why panic is the best solution over reverting the work?

My question applies for all the other panic() below.

> +
>           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 1b2b165a6d..b55ad6d050 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

AFAIK, enum will always start counting from 0, so is it really necessary to 
specify the exact values?

> +} 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

Above, you increase the version of the payload here even for Arm when there are 
no modification in Arm. This raises the question on whether we would need to 
increase the version when Arm is going to be supported?

>   };
>   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);
> 

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations
  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-22 10:31   ` Julien Grall
  2019-08-22 11:03     ` Wieczorkiewicz, Pawel
  1 sibling, 1 reply; 66+ messages in thread
From: Julien Grall @ 2019-08-22 10:31 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan,
	Ross Lagerwall, Jan Beulich

Hi Pawel,

On 21/08/2019 09:19, Pawel Wieczorkiewicz wrote:
> diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
> index b55ad6d050..e18322350d 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 2
> +#define LIVEPATCH_PAYLOAD_VERSION 3

We usually only bump the version once per release. So this is unnecessary as you 
already did it in the previous patch.

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 10:20         ` Wieczorkiewicz, Pawel
@ 2019-08-22 10:43           ` Julien Grall
  2019-08-22 11:15             ` Wieczorkiewicz, Pawel
  0 siblings, 1 reply; 66+ messages in thread
From: Julien Grall @ 2019-08-22 10:43 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Ross Lagerwall, Jan Beulich, xen-devel,
	Roger Pau Monné

Hi,

On 22/08/2019 11:20, Wieczorkiewicz, Pawel wrote:
>> On 22. Aug 2019, at 12:07, Julien Grall <julien.grall@arm.com 
>> <mailto:julien.grall@arm.com>> wrote:
>> On 22/08/2019 08:44, Wieczorkiewicz, Pawel wrote:
>>>>> 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);
>>>>
>>>> I doubt livepatch on Arm will compile after this change.
>>>>
>>> What would be you suggestion then?
>>
>> Cross-compiler are nowadays widely available. So build testing your changes in 
>> common code would be the minimum.
>>
> 
> I wish it was that simple. Nevertheless, I will try to prepare an environment to 
> perform such builds.

Cross-compiling the hypervisor is really easy ;).

1) Download the cross-compiler tarball (here one [1]) and uncompress it. You can 
also install the one provided by your distro.

2) Build Xen hypervisor. Here an example for arm64:

42sh> cd xen.git/xen
42sh> make XEN_TARGET_ARCH=arm64 CROSS_COMPILER=<triplet>-

In my case, I am using the Arm toolchain AArch64 GNU/Linux target 
(aarch64-linux-gnu). So the <triplet> would be aarch64-linux-gnu.

This is assuming you have the compilers binary in your PATH. If not, you can use 
give the full path:

CROSS_COMPILER=/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-

> 
>> In this case, as you dropped the const from the prototype, you will need to do 
>> the same in the declaration.
>>
> 
> Yes, but I see 2 options here:
> - Enable the feature also for Arm (I prefer that, but will not be able to test 
> that in nearest future)

I think some of the code can be made common. So we could possibly rely on x86 
for that. Additionally, IIRC, Konrad has a setup on the cubietruck for testing 
livepatch.

> - Keep Arm excluded and sprinkle code with #ifdef CONFIG_X86

Please no #ifdef CONFIG_X86 in the common code. If you don't plan to support 
Arm, then we should introduce a new Kconfig that will gate all those changes.

Cheers,

[1] 
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 10:29   ` Julien Grall
@ 2019-08-22 11:02     ` Wieczorkiewicz, Pawel
  2019-08-22 15:30       ` Julien Grall
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-22 11:02 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Jan Beulich,
	xen-devel, Roger Pau Monné


[-- Attachment #1.1: Type: text/plain, Size: 10764 bytes --]



On 22. Aug 2019, at 12:29, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com>> wrote:

Hi Pawel,

Hi Julien,

Thank for looking at this!


On 21/08/2019 09:19, Pawel Wieczorkiewicz wrote:
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@amazon.de<mailto:wipawel@amazon.de>>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com<mailto:andraprs@amazon.com>>
Reviewed-by: Bjoern Doebel <doebel@amazon.de<mailto:doebel@amazon.de>>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de<mailto:mpohlack@amazon.de>>
---
 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;
+    }

Does this need to in arch specific code?

As a matter of fact it does not.
Let me enable this feature for Arm as well and make this code a common inline.


+
     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 )

Per the definition of livepath_func, the field "applied" only exists for x86. So this will not compiled on Arm.

I will enable Arm too.


+        {
+            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) )

Regardless the compilation issue above, none of the common code will set the state. So for Arm, this would likely mean the function return false.

True, I should have disabled this code for Arm too.
But now, let me just make it common for all archs.


+            panic("livepatch: partially applied payload '%s'!\n", data->name);

I can see at least a case where the panic can be reached here. Per the changes in arch_livepatch_apply(), f->applied will only be set to LIVEPATCH_FUNC_APPLIED if livepatch_insn_len() is not 0.

I don't know whether livepatch_insn_len() can ever return 0 as my livepatch knowledge is limited. But the code live little doubt this is a theoritical possibility that after this patch will turn into crashing Xen.


I suppose the livepatch_insn_len() returning 0 (i.e. func->new_size being 0, which is valid AFAICS) is the to-be-implemented feature of noping out code:
From the livepatch doc:
"""
## TODO Goals

 * NOP out the code sequence if `new_size` is zero.
"""
So, in theory it can be 0 (it has to be introduced to the livepatch.funcs). Thus, you’re right.

I will fix that, but marking such function (new_size==0) as applied.

Thanks!

More generally, I am not very comfortable to see panic() in the middle of the code. Could you explain why panic is the best solution over reverting the work?


Yes. Production-ready hotpatches must not contain inconsistent hooks or functions-to-be-applied/reverted.
The goal here is to detect such hotpatches and fail hard immediately highlighting the fact that such hotpatch
is broken.

The inconsistent application of a hotpatch (some function applied, some reverted while other left behined) leaves
the system in a very bad state. I think the best what we could do here is panic() to enable post-mortem analysis
of what went wrong and avoid leaking such system into production.

Mis-detecting such conditions and leaving such inconsistent system running is a very bad idea.

My question applies for all the other panic() below.

+
         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 1b2b165a6d..b55ad6d050 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

AFAIK, enum will always start counting from 0, so is it really necessary to specify the exact values?

It’s probably my (or some earlier reviewer's) OCD. I am happy to remove these.


+} 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

Above, you increase the version of the payload here even for Arm when there are no modification in Arm. This raises the question on whether we would need to increase the version when Arm is going to be supported?

I think the best way forward is to add Arm support.
This feature is simple enough and it does not make much sense to complicate it by adding support spaghetti.


 };
 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);

Cheers,

--
Julien Grall

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 20833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 10/14] livepatch: Add support for inline asm hotpatching expectations
  2019-08-22 10:31   ` Julien Grall
@ 2019-08-22 11:03     ` Wieczorkiewicz, Pawel
  0 siblings, 0 replies; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-22 11:03 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Jan Beulich,
	xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1050 bytes --]



On 22. Aug 2019, at 12:31, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com>> wrote:

Hi Pawel,

On 21/08/2019 09:19, Pawel Wieczorkiewicz wrote:
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index b55ad6d050..e18322350d 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 2
+#define LIVEPATCH_PAYLOAD_VERSION 3

We usually only bump the version once per release. So this is unnecessary as you already did it in the previous patch.


Yes, I will keep all these changes under a single bump as promised to Konrad yesterday.

Cheers,

--
Julien Grall

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 2656 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 10:43           ` Julien Grall
@ 2019-08-22 11:15             ` Wieczorkiewicz, Pawel
  2019-08-22 15:02               ` Julien Grall
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-22 11:15 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Jan Beulich,
	xen-devel, Roger Pau Monné


[-- Attachment #1.1: Type: text/plain, Size: 2455 bytes --]



On 22. Aug 2019, at 12:43, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com>> wrote:

Hi,

On 22/08/2019 11:20, Wieczorkiewicz, Pawel wrote:


..snip..

Cross-compiler are nowadays widely available. So build testing your changes in common code would be the minimum.

I wish it was that simple. Nevertheless, I will try to prepare an environment to perform such builds.

Cross-compiling the hypervisor is really easy ;).

1) Download the cross-compiler tarball (here one [1]) and uncompress it. You can also install the one provided by your distro.

2) Build Xen hypervisor. Here an example for arm64:

42sh> cd xen.git/xen
42sh> make XEN_TARGET_ARCH=arm64 CROSS_COMPILER=<triplet>-

In my case, I am using the Arm toolchain AArch64 GNU/Linux target (aarch64-linux-gnu). So the <triplet> would be aarch64-linux-gnu.

This is assuming you have the compilers binary in your PATH. If not, you can use give the full path:

CROSS_COMPILER=/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-

Awesome! That really works (especially thanks for the [1] link… finally some toolstack that works on my system).

One change was needed: s/CROSS_COMPILER/CROSS_COMPILE/g

Thanks!

Having this in a wiki would really help. Or have I missed it?


In this case, as you dropped the const from the prototype, you will need to do the same in the declaration.

Yes, but I see 2 options here:
- Enable the feature also for Arm (I prefer that, but will not be able to test that in nearest future)

I think some of the code can be made common. So we could possibly rely on x86 for that. Additionally, IIRC, Konrad has a setup on the cubietruck for testing livepatch.


Yes, I will do that.

- Keep Arm excluded and sprinkle code with #ifdef CONFIG_X86

Please no #ifdef CONFIG_X86 in the common code. If you don't plan to support Arm, then we should introduce a new Kconfig that will gate all those changes.

Ugh, you’re right. Removing all that from common code.


Cheers,

[1] https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

--
Julien Grall

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 5285 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 11:15             ` Wieczorkiewicz, Pawel
@ 2019-08-22 15:02               ` Julien Grall
  0 siblings, 0 replies; 66+ messages in thread
From: Julien Grall @ 2019-08-22 15:02 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Ross Lagerwall, Jan Beulich, xen-devel,
	Roger Pau Monné

Hi,

On 22/08/2019 12:15, Wieczorkiewicz, Pawel wrote:
>> On 22. Aug 2019, at 12:43, Julien Grall <julien.grall@arm.com 
>> <mailto:julien.grall@arm.com>> wrote:
>> On 22/08/2019 11:20, Wieczorkiewicz, Pawel wrote:
>>>> Cross-compiler are nowadays widely available. So build testing your changes 
>>>> in common code would be the minimum.
>>>>
>>> I wish it was that simple. Nevertheless, I will try to prepare an environment 
>>> to perform such builds.
>>
>> Cross-compiling the hypervisor is really easy ;).
>>
>> 1) Download the cross-compiler tarball (here one [1]) and uncompress it. You 
>> can also install the one provided by your distro.
>>
>> 2) Build Xen hypervisor. Here an example for arm64:
>>
>> 42sh> cd xen.git/xen
>> 42sh> make XEN_TARGET_ARCH=arm64 CROSS_COMPILER=<triplet>-
>>
>> In my case, I am using the Arm toolchain AArch64 GNU/Linux target 
>> (aarch64-linux-gnu). So the <triplet> would be aarch64-linux-gnu.
>>
>> This is assuming you have the compilers binary in your PATH. If not, you can 
>> use give the full path:
>>
>> CROSS_COMPILER=/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-
> 
> Awesome! That really works (especially thanks for the [1] link… finally some 
> toolstack that works on my system).
> 
> One change was needed: s/CROSS_COMPILER/CROSS_COMPILE/g

Oh yes, sorry for that. I didn't copy/paste for once.

> 
> Thanks!
> 
> Having this in a wiki would really help. Or have I missed it?

This is explained on the Xen on Arm wiki page [2]. But I have to admit the page 
is difficult to go through. I need to find some time to rework it.

Cheers,

>> [1] 
>> https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

[2] 
https://wiki.xenproject.org/wiki/Xen_ARM_with_Virtualization_Extensions#Cross_Compiling


-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 11:02     ` Wieczorkiewicz, Pawel
@ 2019-08-22 15:30       ` Julien Grall
  2019-08-22 15:42         ` Wieczorkiewicz, Pawel
  0 siblings, 1 reply; 66+ messages in thread
From: Julien Grall @ 2019-08-22 15:30 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Ross Lagerwall, Jan Beulich, xen-devel,
	Roger Pau Monné

Hi Pawel,

On 22/08/2019 12:02, Wieczorkiewicz, Pawel wrote:
>> On 22. Aug 2019, at 12:29, Julien Grall <julien.grall@arm.com 
>> <mailto:julien.grall@arm.com>> wrote:
>> On 21/08/2019 09:19, Pawel Wieczorkiewicz wrote:
>> More generally, I am not very comfortable to see panic() in the middle of the 
>> code. Could you explain why panic is the best solution over reverting the work?
>>
> 
> Yes. Production-ready hotpatches must not contain inconsistent hooks or 
> functions-to-be-applied/reverted.
> The goal here is to detect such hotpatches and fail hard immediately 
> highlighting the fact that such hotpatch
> is broken.

Aside the len = 0 that you are going to fix. How would this condition happen? 
Are you going to add code that will potentially trigger the panic?

> 
> The inconsistent application of a hotpatch (some function applied, some reverted 
> while other left behined) leaves
> the system in a very bad state. I think the best what we could do here is 
> panic() to enable post-mortem analysis
> of what went wrong and avoid leaking such system into production.

Thank you for the explanation here (and on IRC). May I ask some documentation 
regarding the panic in at least commit message? Ideally, this would explain why 
the panic the most sensible solution.

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 09/14] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-22 15:30       ` Julien Grall
@ 2019-08-22 15:42         ` Wieczorkiewicz, Pawel
  0 siblings, 0 replies; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-22 15:42 UTC (permalink / raw)
  To: Julien Grall
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Jan Beulich,
	xen-devel, Roger Pau Monné


[-- Attachment #1.1: Type: text/plain, Size: 2771 bytes --]


On 22. Aug 2019, at 17:30, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com>> wrote:

Hi Pawel,

On 22/08/2019 12:02, Wieczorkiewicz, Pawel wrote:
On 22. Aug 2019, at 12:29, Julien Grall <julien.grall@arm.com<mailto:julien.grall@arm.com> <mailto:julien.grall@arm.com>> wrote:
On 21/08/2019 09:19, Pawel Wieczorkiewicz wrote:
More generally, I am not very comfortable to see panic() in the middle of the code. Could you explain why panic is the best solution over reverting the work?

Yes. Production-ready hotpatches must not contain inconsistent hooks or functions-to-be-applied/reverted.
The goal here is to detect such hotpatches and fail hard immediately highlighting the fact that such hotpatch
is broken.

Aside the len = 0 that you are going to fix. How would this condition happen? Are you going to add code that will potentially trigger the panic?


The default livepatch code path is very conservative (to the extent it does not even need this check and panic).
But, with the changes of this series, one can potentially construct a hotpatch that upon load would trigger the panic
(or without the panic, would silently leave the Xen code in memory in an inconsistent state). This obviously must not
happen in production, so the new livepatch feature should be used with care.The changes make livepatch more
flexible and universal, yet when using new features, more care is needed.

However, when someone is developing a hotpatch or is using the new feature for debugging or for whatever
non-production-related reason, it is very helpful to detect immediately any sort of undefined state.
I have been there myself when I was working on the changes presented here, and thought that would be a good idea
to add this checks permanently.
Also, when something changes in the future in the livepatch implementation, those checks could potentially highlight
any inconsistencies.

The inconsistent application of a hotpatch (some function applied, some reverted while other left behined) leaves
the system in a very bad state. I think the best what we could do here is panic() to enable post-mortem analysis
of what went wrong and avoid leaking such system into production.

Thank you for the explanation here (and on IRC). May I ask some documentation regarding the panic in at least commit message? Ideally, this would explain why the panic the most sensible solution.


Yes, certainly. I will add that.

Cheers,

--
Julien Grall

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 4828 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 14/14] livepatch: Add python bindings for livepatch operations
  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
  0 siblings, 0 replies; 66+ messages in thread
From: Marek Marczykowski-Górecki @ 2019-08-22 21:55 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: wipawel, Wei Liu, Ian Jackson, mpohlack, xen-devel, xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 5309 bytes --]

On Wed, Aug 21, 2019 at 08:19:31AM +0000, Pawel Wieczorkiewicz wrote:
> Extend the XC python bindings library to support also all common
> livepatch operations and actions.
> 
> Add the python bindings for the following operations:
> - status (pyxc_livepatch_status):
>   Requires a payload name as an input.
>   Returns a status dict containing a state string and a return code
>   integer.
> - action (pyxc_livepatch_action):
>   Requires a payload name and an action id as an input. Timeout and
>   flags are optional parameters.
>   Returns a return code integer.
> - upload (pyxc_livepatch_upload):
>   Requires a payload name and a module's filename as an input.
>   Returns a return code integer.
> - list (pyxc_livepatch_list):
>   Takes no parameters.
>   Returns a list of dicts containing each payload's:
>   * name as a string
>   * state as a string
>   * return code as an integer
>   * list of metadata key=value strings
> 
> Each functions throws an exception error based on the errno value
> received from its corresponding libxc function call.
> 
> Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
> Reviewed-by: Martin Mazein <amazein@amazon.de>
> Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
> Reviewed-by: Leonard Foerster <foersleo@amazon.de>
> Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
> ---
>  tools/python/xen/lowlevel/xc/xc.c | 273 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 273 insertions(+)
> 
> diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> index 7f0358ba9c..368739b996 100644
> --- a/tools/python/xen/lowlevel/xc/xc.c
> +++ b/tools/python/xen/lowlevel/xc/xc.c

(...)
> +static PyObject *pyxc_livepatch_list(XcObject *self)
> +{
> +    PyObject *list;
> +    unsigned int nr, done, left, i;
> +    xen_livepatch_status_t *info = NULL;
> +    char *name = NULL;
> +    char *metadata = NULL;
> +    uint32_t *len = NULL;
> +    uint32_t *metadata_len = NULL;
> +    uint64_t name_total_size, metadata_total_size;
> +    off_t name_off, metadata_off;
> +    int rc;
> +
> +    rc = xc_livepatch_list_get_sizes(self->xc_handle, &nr,
> +                                     &name_total_size, &metadata_total_size);
> +    if ( rc )
> +        goto error;
> +
> +    if ( nr == 0 )
> +        return PyList_New(0);
> +
> +    rc = ENOMEM;
> +    info = malloc(nr * sizeof(*info));
> +    if ( !info )
> +        goto error;
> +
> +    name = malloc(name_total_size * sizeof(*name));
> +    if ( !name )
> +        goto error;
> +
> +    len = malloc(nr * sizeof(*len));
> +    if ( !len )
> +        goto error;
> +
> +    metadata = malloc(metadata_total_size * sizeof(*metadata));
> +    if ( !metadata )
> +        goto error;
> +
> +    metadata_len = malloc(nr * sizeof(*metadata_len));
> +    if ( !metadata_len )
> +        goto error;
> +
> +    rc = xc_livepatch_list(self->xc_handle, nr, 0, info,
> +                           name, len, name_total_size,
> +                           metadata, metadata_len, metadata_total_size,
> +                           &done, &left);
> +    if ( rc )
> +        goto error;
> +
> +    list = PyList_New(0);

Previous remark stays:
Better use PyList_New(done) and later PyList_SetItem() instead of PyList_Append().

> +    name_off = metadata_off = 0;
> +    for ( i = 0; i < done; i++ )
> +    {
> +        PyObject *info_dict, *metadata_list;
> +        char *name_str, *metadata_str;
> +
> +        name_str = name + name_off;
> +        metadata_str = metadata + metadata_off;
> +
> +        metadata_list = PyList_New(0);
> +        for ( char *s = metadata_str; s < metadata_str + metadata_len[i]; s += strlen(s) + 1 )
> +        {
> +            PyObject *field = Py_BuildValue("s", s);
> +            if ( field == NULL )
> +            {
> +                Py_DECREF(list);
> +                Py_DECREF(metadata_list);
> +                rc = EFAULT;
> +                goto error;
> +            }
> +
> +            PyList_Append(metadata_list, field);
> +            Py_DECREF(field);
> +        }
> +
> +        info_dict = Py_BuildValue(
> +            "{s:s,s:i,s:i,s:N}",
> +            "name",     name_str,
> +            "state",    info[i].state,
> +            "rc",       info[i].rc,
> +            "metadata", metadata_list);
> +
> +        if ( info_dict == NULL )
> +        {
> +            Py_DECREF(list);
> +            Py_DECREF(metadata_list);
> +            rc = EFAULT;
> +            goto error;
> +        }
> +        PyList_Append(list, info_dict);
> +        Py_DECREF(info_dict);
> +
> +        name_off += len[i];
> +        metadata_off += metadata_len[i];
> +    }
> +
> +error:
> +    free(info);
> +    free(name);
> +    free(len);
> +    free(metadata);
> +    free(metadata_len);
> +    return rc ? pyxc_error_to_exception(self->xc_handle) : list;
> +}
> +
>  static PyMethodDef pyxc_methods[] = {
>      { "domain_create", 
>        (PyCFunction)pyxc_domain_create, 

-- 
Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH 06/14] livepatch: Add support for apply|revert action replacement hooks
  2019-08-21 19:06     ` Wieczorkiewicz, Pawel
@ 2019-08-26 14:30       ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-26 14:30 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Pohlack, Martin, xen-devel, Ross Lagerwall, xen-devel

> Yes, I could do that. But, I would like to discuss (get guidelines about) the expected test coverage.
> With this sort of changes, there is an unlimited set of test-cases to be created. So, I would like to focus on a few most important.
> I am missing knowledge how these test cases are supposed to be used… hence the ask.

I had in mind two livepatches with a dependency on each other that would utilize
different callback mechanism. 

Say the first one just modifies xen_extra_function to print based on a string variable.
Applying it would change extra version to say 'FIRST_LIVEPATCH' or such.

The second one has an apply and revert callback that modifies the xen_extra_function to print say
'SECOND_LIVEPATCH' and also 'SECOND_REVERTED' when reverted?

So you would have:

xen-livepatch apply xen_first
xl version |grep extra_version
[should have FIRST_LIVEPATCH]
xen-livepatch apply xen_second
xl version |grep extra_version
[should have SECOND_LIVEPATCH]
xen-livepatch revert xen_second
xl version |grep extra_version
[should have SECOND_REVERTED]

or such?

Just want to make sure that the code that is doing the various combinations
of callbacks is behaving correctly. Naturally doing all of them would be rather
difficult, so I would rather test the most common use-case.

Hope this helps?
> 
> Best Regards,
> Pawel Wieczorkiewicz
> 
> 
> 
> 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

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes
  2019-08-21  8:19 [Xen-devel] [PATCH 00/14] livepatch: new features and fixes Pawel Wieczorkiewicz
                   ` (13 preceding siblings ...)
  2019-08-21  8:19 ` [Xen-devel] [PATCH 14/14] livepatch: Add python bindings for livepatch operations Pawel Wieczorkiewicz
@ 2019-08-27  8:46 ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 01/12] livepatch: Always check hypervisor build ID upon hotpatch upload Pawel Wieczorkiewicz
                     ` (14 more replies)
  14 siblings, 15 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Marek Marczykowski-Górecki, wipawel, Stefano Stabellini,
	Wei Liu, Konrad Rzeszutek Wilk, George Dunlap, Andrew Cooper,
	Ross Lagerwall, Ian Jackson, mpohlack, Tim Deegan,
	Pawel Wieczorkiewicz, Julien Grall, Jan Beulich,
	Volodymyr Babchuk, Roger Pau Monné

This series introduces new features to the livepatch functionality as
briefly discussed during Xen Developer Summit 2019: [a] and [b].
It also provides a few fixes and some small improvements.

Main changes in v2:
- added new features to livepatch documentation
- added livepatch tests
- enabled Arm support for [5]
- make .modinfo optional for [11]
- fixed typos

FEATURES:

1. independent modules (patches: [1], [2])

  * livepatch-build-tools repo dependency [A]

  Livepatch enforces the following buildid-based dependency chain
  between hotpatch modules:
    1) first module depends on given hypervisor buildid
    2) every consecutive module depends on previous module's buildid
  This way proper hotpatch stack order is maintained and enforced.
  While it is important for production hotpatches it limits agility and
  blocks usage of testing or debug hotpatches. These kinds of hotpatch
  modules are typically expected to be loaded at any time irrespective
  of current state of the modules stack.

  [A] livepatch-build: Embed hypervisor build id into every hotpatch

2. pre- and post- apply|revert actions hooks (patches: [3], [4])

  * livepatch-build-tools repo dependency [B]

  This is an implementation of 4 new livepatch module vetoing hooks,
  that can be optionally supplied along with modules.
  Hooks that currently exists in the livepatch mechanism aren't agile
  enough and have various limitations:
  * run only from within a quiescing zone
  * cannot conditionally prevent applying or reverting
  * do not have access to the module context
  To address these limitations the following has been implemented:
  1) pre-apply hook
  2) post-apply hook
  3) pre-revert hook
  4) post-revert hook

  [B] create-diff-object: Handle extra pre-|post- hooks

3. apply|revert actions replacement hooks (patches: [5], [6], [7])

  * livepatch-build-tools repo dependency: [C], [D], [E]

  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.

  [C] create-diff-object: Do not create empty .livepatch.funcs section
  [D] create-diff-object: Handle optional apply|revert hooks
  [E] create-diff-object: Add support for applied/reverted marker

4. inline asm hotpatching expectations (patches: [8])

  * livepatch-build-tools repo dependency: [F]

  Expectations are designed as optional feature, since the main use of
  them is planned for inline asm hotpatching.
  The payload structure is modified as each expectation structure is
  part of the livepatch_func structure and hence extends the payload.
  The payload version is bumped to 3 with this change to highlight the
  ABI modification and enforce proper support.
  The expectation is manually enabled during inline asm module
  construction. If enabled, expectation ensures that the expected
  content of memory is to be found at a given patching (old_addr)
  location.

  [F] create-diff-object: Add support for expectations

5. runtime hotpatch metadata support (patches: [9], [10], [11])

  Having detailed hotpatch metadata helps to properly identify module's
  origin and version. It also allows to keep track of the history of
  hotpatch loads in the system (at least within dmesg buffer size
  limits).
  Extend the livepatch list operation to fetch also payloads' metadata.
  This is achieved by extending the sysctl list interface with 2 extra
  guest handles:
  * metadata     - an array of arbitrary size strings
  * metadata_len - an array of metadata strings' lengths (uin32_t each)
  To unify and simplify the interface, handle the modules' name strings
  of arbitrary size by copying them in adhering chunks to the userland.

6. python bindings for livepatch operations (patches: [12])

  Extend the XC python bindings library to support all common livepatch
  operations and actions:
  - status (pyxc_livepatch_status):
  - action (pyxc_livepatch_action):
  - upload (pyxc_livepatch_upload):
  - list (pyxc_livepatch_list):

[a] https://wiki.xenproject.org/wiki/Design_Sessions_2019#LivePatch_improvements_and_features
[b] https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg00846.html

Merged in v1:
  python: Add XC binding for Xen build ID
  livepatch: always print XENLOG_ERR information

Pawel Wieczorkiewicz (12):
  [1] livepatch: Always check hypervisor build ID upon hotpatch upload
  [2] livepatch: Allow to override inter-modules buildid dependency
  [3] livepatch: Export payload structure via livepatch_payload.h
  [4] livepatch: Implement pre-|post- apply|revert hooks
  [5] livepatch: Add support for apply|revert action replacement hooks
  [6] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence
  [7] livepatch: Add per-function applied/reverted state tracking marker
  [8] livepatch: Add support for inline asm hotpatching expectations
  [9] livepatch: Add support for modules .modinfo section metadata
  [10] livepatch: Handle arbitrary size names with the list operation
  [11] livepatch: Add metadata runtime retrieval mechanism
  [12] livepatch: Add python bindings for livepatch operations

 .gitignore                                     |   6 +-
 docs/misc/livepatch.pandoc                     | 231 ++++++++-
 tools/libxc/include/xenctrl.h                  |  68 ++-
 tools/libxc/xc_misc.c                          | 162 +++++--
 tools/misc/xen-livepatch.c                     | 258 +++++++---
 tools/python/xen/lowlevel/xc/xc.c              | 273 +++++++++++
 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                         | 647 +++++++++++++++++++++----
 xen/include/public/sysctl.h                    |  61 ++-
 xen/include/xen/livepatch.h                    |  42 +-
 xen/include/xen/livepatch_payload.h            |  83 ++++
 xen/test/livepatch/Makefile                    | 113 ++++-
 xen/test/livepatch/xen_action_hooks.c          | 102 ++++
 xen/test/livepatch/xen_action_hooks_marker.c   | 112 +++++
 xen/test/livepatch/xen_action_hooks_noapply.c  | 136 ++++++
 xen/test/livepatch/xen_action_hooks_nofunc.c   |  86 ++++
 xen/test/livepatch/xen_action_hooks_norevert.c | 143 ++++++
 xen/test/livepatch/xen_expectations.c          |  41 ++
 xen/test/livepatch/xen_expectations_fail.c     |  42 ++
 xen/test/livepatch/xen_prepost_hooks.c         | 122 +++++
 xen/test/livepatch/xen_prepost_hooks_fail.c    |  75 +++
 24 files changed, 2579 insertions(+), 280 deletions(-)
 create mode 100644 xen/test/livepatch/xen_action_hooks.c
 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_nofunc.c
 create mode 100644 xen/test/livepatch/xen_action_hooks_norevert.c
 create mode 100644 xen/test/livepatch/xen_expectations.c
 create mode 100644 xen/test/livepatch/xen_expectations_fail.c
 create mode 100644 xen/test/livepatch/xen_prepost_hooks.c
 create mode 100644 xen/test/livepatch/xen_prepost_hooks_fail.c

-- 
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

^ permalink raw reply	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 01/12] livepatch: Always check hypervisor build ID upon hotpatch upload
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
@ 2019-08-27  8:46   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 02/12] livepatch: Allow to override inter-modules buildid dependency Pawel Wieczorkiewicz
                     ` (13 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

This change is part of a independant stacked hotpatch modules
feature. This feature allows to bypass dependencies between modules
upon loading, but still verifies Xen build ID matching.

In order to prevent (up)loading any hotpatches built for different
hypervisor version as indicated by the Xen Build ID, add checking for
the payload's vs Xen's build id match.

To achieve that embed into every hotpatch another section with a
dedicated hypervisor build id in it. After the payload is loaded and
the .livepatch.xen_depends section becomes available, perform the
check and reject the payload if there is no match.

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: Eslam Elnikety <elnikety@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
---
Changed since v1:
  * always print XENLOG_ERR message from check_xen_build_id()
  * fix typo in test/livepatch/Makefile

 .gitignore                  |  1 +
 docs/misc/livepatch.pandoc  | 28 +++++++++++++++++++--------
 xen/common/livepatch.c      | 47 +++++++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/livepatch.h |  7 ++++---
 xen/test/livepatch/Makefile | 31 +++++++++++++++++++++++++-----
 5 files changed, 98 insertions(+), 16 deletions(-)

diff --git a/.gitignore b/.gitignore
index 3c947ac948..6f83fc8728 100644
--- a/.gitignore
+++ b/.gitignore
@@ -312,6 +312,7 @@ xen/test/livepatch/xen_bye_world.livepatch
 xen/test/livepatch/xen_hello_world.livepatch
 xen/test/livepatch/xen_nop.livepatch
 xen/test/livepatch/xen_replace_world.livepatch
+xen/test/livepatch/xen_no_xen_buildid.livepatch
 xen/tools/kconfig/.tmp_gtkcheck
 xen/tools/kconfig/.tmp_qtcheck
 xen/tools/symbols
diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index 6d9f72f49b..fd1f5d0126 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -270,6 +270,8 @@ like what the Linux kernel module loader does.
 The payload contains at least three sections:
 
  * `.livepatch.funcs` - which is an array of livepatch_func structures.
+ * `.livepatch.xen_depends` - which is an ELF Note that describes what Xen
+    build-id the payload depends on. **MUST** have one.
  * `.livepatch.depends` - which is an ELF Note that describes what the payload
     depends on. **MUST** have one.
  *  `.note.gnu.build-id` - the build-id of this payload. **MUST** have one.
@@ -383,16 +385,16 @@ The type definition of the function are as follow:
     typedef void (*livepatch_loadcall_t)(void);
     typedef void (*livepatch_unloadcall_t)(void);
 
-### .livepatch.depends and .note.gnu.build-id
+### .livepatch.xen_depends, .livepatch.depends and .note.gnu.build-id
 
 To support dependencies checking and safe loading (to load the
 appropiate payload against the right hypervisor) there is a need
 to embbed an build-id dependency.
 
-This is done by the payload containing an section `.livepatch.depends`
-which follows the format of an ELF Note. The contents of this
-(name, and description) are specific to the linker utilized to
-build the hypevisor and payload.
+This is done by the payload containing sections `.livepatch.xen_depends`
+and `.livepatch.depends` which follow the format of an ELF Note.
+The contents of these (name, and description) are specific to the linker
+utilized to build the hypevisor and payload.
 
 If GNU linker is used then the name is `GNU` and the description
 is a NT_GNU_BUILD_ID type ID. The description can be an SHA1
@@ -400,6 +402,13 @@ checksum, MD5 checksum or any unique value.
 
 The size of these structures varies with the `--build-id` linker option.
 
+There are two kinds of build-id dependencies:
+
+ * Xen build-id dependency (.livepatch.xen_depends section)
+ * previous payload build-id dependency (.livepatch.depends section)
+
+See "Live patch interdependencies" for more information.
+
 ## Hypercalls
 
 We will employ the sub operations of the system management hypercall (sysctl).
@@ -894,13 +903,16 @@ but is more complex to implement.
 The second option which requires an build-id of the hypervisor
 is implemented in the Xen hypervisor.
 
-Specifically each payload has two build-id ELF notes:
+Specifically each payload has three build-id ELF notes:
  * The build-id of the payload itself (generated via --build-id).
+ * The build-id of the Xen hypervisor it depends on (extracted from the
+   hypervisor during build time).
  * The build-id of the payload it depends on (extracted from the
    the previous payload or hypervisor during build time).
 
-This means that the very first payload depends on the hypervisor
-build-id.
+This means that every payload depends on the hypervisor build-id and on
+the build-id of the previous payload in the stack.
+The very first payload depends on the hypervisor build-id only.
 
 # Not Yet Done
 
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 7caa30c202..ef081f112c 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -74,6 +74,7 @@ struct payload {
     unsigned int nsyms;                  /* Nr of entries in .strtab and symbols. */
     struct livepatch_build_id id;        /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */
     struct livepatch_build_id dep;       /* ELFNOTE_DESC(.livepatch.depends). */
+    struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
     livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
     livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
     unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
@@ -476,11 +477,34 @@ static bool section_ok(const struct livepatch_elf *elf,
     return true;
 }
 
+static int check_xen_build_id(const struct payload *payload)
+{
+    const void *id = NULL;
+    unsigned int len = 0;
+    int rc;
+
+    ASSERT(payload->xen_dep.len);
+    ASSERT(payload->xen_dep.p);
+
+    rc = xen_build_id(&id, &len);
+    if ( rc )
+        return rc;
+
+    if ( payload->xen_dep.len != len || memcmp(id, payload->xen_dep.p, len) ) {
+        printk(XENLOG_ERR LIVEPATCH "%s: check against hypervisor build-id failed\n",
+               payload->name);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 static int check_special_sections(const struct livepatch_elf *elf)
 {
     unsigned int i;
     static const char *const names[] = { ELF_LIVEPATCH_FUNC,
                                          ELF_LIVEPATCH_DEPENDS,
+                                         ELF_LIVEPATCH_XEN_DEPENDS,
                                          ELF_BUILD_ID_NOTE};
     DECLARE_BITMAP(found, ARRAY_SIZE(names)) = { 0 };
 
@@ -632,6 +656,22 @@ static int prepare_payload(struct payload *payload,
             return -EINVAL;
     }
 
+    sec = livepatch_elf_sec_by_name(elf, ELF_LIVEPATCH_XEN_DEPENDS);
+    if ( sec )
+    {
+        n = sec->load_addr;
+
+        if ( sec->sec->sh_size <= sizeof(*n) )
+            return -EINVAL;
+
+        if ( xen_build_id_check(n, sec->sec->sh_size,
+                                &payload->xen_dep.p, &payload->xen_dep.len) )
+            return -EINVAL;
+
+        if ( !payload->xen_dep.len || !payload->xen_dep.p )
+            return -EINVAL;
+    }
+
     /* Setup the virtual region with proper data. */
     region = &payload->region;
 
@@ -882,6 +922,10 @@ static int load_payload_data(struct payload *payload, void *raw, size_t len)
     if ( rc )
         goto out;
 
+    rc = check_xen_build_id(payload);
+    if ( rc )
+        goto out;
+
     rc = build_symbol_table(payload, &elf);
     if ( rc )
         goto out;
@@ -1655,6 +1699,9 @@ static void livepatch_printall(unsigned char key)
 
         if ( data->dep.len )
             printk("depend-on=%*phN\n", data->dep.len, data->dep.p);
+
+        if ( data->xen_dep.len )
+            printk("depend-on-xen=%*phN\n", data->xen_dep.len, data->xen_dep.p);
     }
 
     spin_unlock(&payload_lock);
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index 1b1817ca0d..ed997aa4cc 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -29,9 +29,10 @@ struct xen_sysctl_livepatch_op;
 /* Convenience define for printk. */
 #define LIVEPATCH             "livepatch: "
 /* ELF payload special section names. */
-#define ELF_LIVEPATCH_FUNC    ".livepatch.funcs"
-#define ELF_LIVEPATCH_DEPENDS ".livepatch.depends"
-#define ELF_BUILD_ID_NOTE      ".note.gnu.build-id"
+#define ELF_LIVEPATCH_FUNC        ".livepatch.funcs"
+#define ELF_LIVEPATCH_DEPENDS     ".livepatch.depends"
+#define ELF_LIVEPATCH_XEN_DEPENDS ".livepatch.xen_depends"
+#define ELF_BUILD_ID_NOTE         ".note.gnu.build-id"
 /* Arbitrary limit for payload size and .bss section size. */
 #define LIVEPATCH_MAX_SIZE     MB(2)
 
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 6831383db1..938aee17ec 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -19,11 +19,13 @@ LIVEPATCH := xen_hello_world.livepatch
 LIVEPATCH_BYE := xen_bye_world.livepatch
 LIVEPATCH_REPLACE := xen_replace_world.livepatch
 LIVEPATCH_NOP := xen_nop.livepatch
+LIVEPATCH_NO_XEN_BUILDID := xen_no_xen_buildid.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
 LIVEPATCHES += $(LIVEPATCH_REPLACE)
 LIVEPATCHES += $(LIVEPATCH_NOP)
+LIVEPATCHES += $(LIVEPATCH_NO_XEN_BUILDID)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -59,7 +61,7 @@ config.h: xen_hello_world_func.o
 xen_hello_world.o: config.h
 
 .PHONY: $(LIVEPATCH)
-$(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
+$(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH) $^
 
 #
@@ -78,6 +80,17 @@ note.o:
 		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
 	rm -f $@.bin
 
+#
+# Append .livepatch.xen_depends section
+# with Xen build-id derived from xen-syms.
+#
+.PHONY: xen_note.o
+xen_note.o:
+	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
+	$(OBJCOPY) $(OBJCOPY_MAGIC) \
+		   --rename-section=.data=.livepatch.xen_depends,alloc,load,readonly,data,contents -S $@.bin $@
+	rm -f $@.bin
+
 #
 # Extract the build-id of the xen_hello_world.livepatch
 # (which xen_bye_world will depend on).
@@ -92,20 +105,28 @@ hello_world_note.o: $(LIVEPATCH)
 xen_bye_world.o: config.h
 
 .PHONY: $(LIVEPATCH_BYE)
-$(LIVEPATCH_BYE): xen_bye_world_func.o xen_bye_world.o hello_world_note.o
+$(LIVEPATCH_BYE): xen_bye_world_func.o xen_bye_world.o hello_world_note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_BYE) $^
 
 xen_replace_world.o: config.h
 
 .PHONY: $(LIVEPATCH_REPLACE)
-$(LIVEPATCH_REPLACE): xen_replace_world_func.o xen_replace_world.o note.o
+$(LIVEPATCH_REPLACE): xen_replace_world_func.o xen_replace_world.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_REPLACE) $^
 
 xen_nop.o: config.h
 
 .PHONY: $(LIVEPATCH_NOP)
-$(LIVEPATCH_NOP): xen_nop.o note.o
+$(LIVEPATCH_NOP): xen_nop.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NOP) $^
 
+# This one always fails upon upload, because it deliberately
+# does not have a .livepatch.xen_depends (xen_note.o) section.
+xen_no_xen_buildid.o: config.h
+
+.PHONY: $(LIVEPATCH_NO_XEN_BUILDID)
+$(LIVEPATCH_NO_XEN_BUILDID): xen_nop.o note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NO_XEN_BUILDID) $^
+
 .PHONY: livepatch
-livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP)
+livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID)
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 02/12] livepatch: Allow to override inter-modules buildid dependency
  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   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 03/12] livepatch: Export payload structure via livepatch_payload.h Pawel Wieczorkiewicz
                     ` (12 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

By default Livepatch enforces the following buildid-based dependency
chain between hotpatch modules:
  1) first module depends on given hypervisor buildid
  2) every consecutive module depends on previous module's buildid
This way proper hotpatch stack order is maintained and enforced.
While it is important for production hotpatches it limits agility and
blocks usage of testing or debug hotpatches. These kinds of hotpatch
modules are typically expected to be loaded at any time irrespective
of current state of the modules stack.

To enable testing and debug hotpatches allow user dynamically ignore
the inter-modules dependency. In this case only hypervisor buildid
match is verified and enforced.

To allow userland pass additional paremeters for livepatch actions
add support for action flags.
Each of the apply, revert, unload and revert action gets additional
64-bit parameter 'flags' where extra flags can be applied in a mask
form.
Initially only one flag '--nodeps' is added for the apply action.
This flag modifies the default buildid dependency check as described
above.
The global sysctl interface input flag parameter is defined with a
single corresponding flag macro:
  LIVEPATCH_ACTION_APPLY_NODEPS (1 << 0)

The userland xen-livepatch tool is modified to support the '--nodeps'
flag for apply and load commands. A general mechanism for specifying
more flags in the future for apply and other action is however added.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Eslam Elnikety <elnikety@amazon.de>
Reviewed-by: Petre Eftime <epetre@amazon.com>
Reviewed-by: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 tools/libxc/include/xenctrl.h |   9 ++--
 tools/libxc/xc_misc.c         |  20 +++----
 tools/misc/xen-livepatch.c    | 121 +++++++++++++++++++++++++++++++++++-------
 xen/common/livepatch.c        |  14 +++--
 xen/include/public/sysctl.h   |  11 +++-
 5 files changed, 139 insertions(+), 36 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 0ff6ed9e70..725697c132 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2607,11 +2607,12 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
  * to complete them. The `timeout` offers an option to expire the
  * operation if it could not be completed within the specified time
  * (in ns). Value of 0 means let hypervisor decide the best timeout.
+ * The `flags` allows to pass extra parameters to the actions.
  */
-int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout);
-int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout);
-int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout);
-int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout);
+int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
 
 /*
  * Ensure cache coherency after memory modifications. A call to this function
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 8e60b6e9f0..a8e9e7d1e2 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -854,7 +854,8 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
 static int _xc_livepatch_action(xc_interface *xch,
                                 char *name,
                                 unsigned int action,
-                                uint32_t timeout)
+                                uint32_t timeout,
+                                uint64_t flags)
 {
     int rc;
     DECLARE_SYSCTL;
@@ -880,6 +881,7 @@ static int _xc_livepatch_action(xc_interface *xch,
     sysctl.u.livepatch.pad = 0;
     sysctl.u.livepatch.u.action.cmd = action;
     sysctl.u.livepatch.u.action.timeout = timeout;
+    sysctl.u.livepatch.u.action.flags = flags;
 
     sysctl.u.livepatch.u.action.name = def_name;
     set_xen_guest_handle(sysctl.u.livepatch.u.action.name.name, name);
@@ -891,24 +893,24 @@ static int _xc_livepatch_action(xc_interface *xch,
     return rc;
 }
 
-int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_apply(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_APPLY, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_APPLY, timeout, flags);
 }
 
-int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_revert(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REVERT, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REVERT, timeout, flags);
 }
 
-int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_unload(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_UNLOAD, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_UNLOAD, timeout, flags);
 }
 
-int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout)
+int xc_livepatch_replace(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags)
 {
-    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REPLACE, timeout);
+    return _xc_livepatch_action(xch, name, LIVEPATCH_ACTION_REPLACE, timeout, flags);
 }
 
 /*
diff --git a/tools/misc/xen-livepatch.c b/tools/misc/xen-livepatch.c
index 3233472157..a37b2457ff 100644
--- a/tools/misc/xen-livepatch.c
+++ b/tools/misc/xen-livepatch.c
@@ -23,18 +23,23 @@ void show_help(void)
 {
     fprintf(stderr,
             "xen-livepatch: live patching tool\n"
-            "Usage: xen-livepatch <command> [args]\n"
+            "Usage: xen-livepatch <command> [args] [command-flags]\n"
             " <name> An unique name of payload. Up to %d characters.\n"
             "Commands:\n"
             "  help                   display this help\n"
             "  upload <name> <file>   upload file <file> with <name> name\n"
             "  list                   list payloads uploaded.\n"
-            "  apply <name>           apply <name> patch.\n"
+            "  apply <name> [flags]   apply <name> patch.\n"
+            "    Supported flags:\n"
+            "      --nodeps           Disable inter-module buildid dependency check.\n"
+            "                         Check only against hypervisor buildid.\n"
             "  revert <name>          revert name <name> patch.\n"
             "  replace <name>         apply <name> patch and revert all others.\n"
             "  unload <name>          unload name <name> patch.\n"
-            "  load  <file>           upload and apply <file>.\n"
-            "                         name is the <file> name\n",
+            "  load <file> [flags]    upload and apply <file> with name as the <file> name\n"
+            "    Supported flags:\n"
+            "      --nodeps           Disable inter-module buildid dependency check.\n"
+            "                         Check only against hypervisor buildid.\n",
             XEN_LIVEPATCH_NAME_SIZE);
 }
 
@@ -225,12 +230,13 @@ static int upload_func(int argc, char *argv[])
     return rc;
 }
 
-/* These MUST match to the 'action_options[]' array slots. */
+/* These MUST match to the 'action_options[]' and 'flag_options[]' array slots. */
 enum {
     ACTION_APPLY = 0,
     ACTION_REVERT = 1,
     ACTION_UNLOAD = 2,
     ACTION_REPLACE = 3,
+    ACTION_NUM
 };
 
 struct {
@@ -238,7 +244,7 @@ struct {
     int expected; /* The state to be in after the function. */
     const char *name;
     const char *verb;
-    int (*function)(xc_interface *xch, char *name, uint32_t timeout);
+    int (*function)(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
 } action_options[] = {
     {   .allow = LIVEPATCH_STATE_CHECKED,
         .expected = LIVEPATCH_STATE_APPLIED,
@@ -266,6 +272,66 @@ struct {
     },
 };
 
+/*
+ * This structure defines supported flag options for actions.
+ * It defines entries for each action and supports up to 64
+ * flags per action.
+ */
+struct {
+    const char *name;
+    const uint64_t flag;
+} flag_options[ACTION_NUM][8 * sizeof(uint64_t)] = {
+    { /* ACTION_APPLY */
+        {   .name = "--nodeps",
+            .flag = LIVEPATCH_ACTION_APPLY_NODEPS,
+        },
+    },
+    { /* ACTION_REVERT */
+    },
+    { /* ACTION_UNLOAD */
+    },
+    { /* ACTION_REPLACE */
+    }
+};
+
+/*
+ * Parse user provided action flags.
+ * This function expects to only receive an array of input parameters being flags.
+ * Expected action is specified via idx paramater (index of flag_options[]).
+ */
+static int get_flags(int argc, char *argv[], unsigned int idx, uint64_t *flags)
+{
+    int i, j;
+
+    if ( !flags || idx >= ARRAY_SIZE(flag_options) )
+        return -1;
+
+    *flags = 0;
+    for ( i = 0; i < argc; i++ )
+    {
+        for ( j = 0; j < ARRAY_SIZE(flag_options[idx]); j++ )
+        {
+            if ( !flag_options[idx][j].name )
+                goto error;
+
+            if ( !strcmp(flag_options[idx][j].name, argv[i]) )
+            {
+                *flags |= flag_options[idx][j].flag;
+                break;
+            }
+        }
+
+        if ( j == ARRAY_SIZE(flag_options[idx]) )
+            goto error;
+    }
+
+    return 0;
+error:
+    fprintf(stderr, "Unsupported flag: %s.\n", argv[i]);
+    errno = EINVAL;
+    return errno;
+}
+
 /* The hypervisor timeout for the live patching operation is 30 msec,
  * but it could take some time for the operation to start, so wait twice
  * that period. */
@@ -291,8 +357,9 @@ int action_func(int argc, char *argv[], unsigned int idx)
     char name[XEN_LIVEPATCH_NAME_SIZE];
     int rc;
     xen_livepatch_status_t status;
+    uint64_t flags;
 
-    if ( argc != 1 )
+    if ( argc < 1 )
     {
         show_help();
         return -1;
@@ -301,7 +368,10 @@ int action_func(int argc, char *argv[], unsigned int idx)
     if ( idx >= ARRAY_SIZE(action_options) )
         return -1;
 
-    if ( get_name(argc, argv, name) )
+    if ( get_name(argc--, argv++, name) )
+        return EINVAL;
+
+    if ( get_flags(argc, argv, idx, &flags) )
         return EINVAL;
 
     /* Check initial status. */
@@ -332,7 +402,7 @@ int action_func(int argc, char *argv[], unsigned int idx)
     if ( action_options[idx].allow & status.state )
     {
         printf("%s %s... ", action_options[idx].verb, name);
-        rc = action_options[idx].function(xch, name, HYPERVISOR_TIMEOUT_NS);
+        rc = action_options[idx].function(xch, name, HYPERVISOR_TIMEOUT_NS, flags);
         if ( rc )
         {
             int saved_errno = errno;
@@ -394,17 +464,23 @@ int action_func(int argc, char *argv[], unsigned int idx)
 
 static int load_func(int argc, char *argv[])
 {
-    int rc;
-    char *new_argv[2];
-    char *path, *name, *lastdot;
+    int i, rc = ENOMEM;
+    char *upload_argv[2];
+    char **apply_argv, *path, *name, *lastdot;
 
-    if ( argc != 1 )
+    if ( argc < 1 )
     {
         show_help();
         return -1;
     }
+
+    /* apply action has <id> [flags] input requirement, which must be constructed */
+    apply_argv = (char **) malloc(argc * sizeof(*apply_argv));
+    if ( !apply_argv )
+        return rc;
+
     /* <file> */
-    new_argv[1] = argv[0];
+    upload_argv[1] = argv[0];
 
     /* Synthesize the <id> */
     path = strdup(argv[0]);
@@ -413,16 +489,23 @@ static int load_func(int argc, char *argv[])
     lastdot = strrchr(name, '.');
     if ( lastdot != NULL )
         *lastdot = '\0';
-    new_argv[0] = name;
+    upload_argv[0] = name;
+    apply_argv[0] = name;
 
-    rc = upload_func(2 /* <id> <file> */, new_argv);
+    /* Fill in all user provided flags */
+    for ( i = 0; i < argc - 1; i++ )
+        apply_argv[i + 1] = argv[i + 1];
+
+    rc = upload_func(2 /* <id> <file> */, upload_argv);
     if ( rc )
-        return rc;
+        goto error;
 
-    rc = action_func(1 /* only <id> */, new_argv, ACTION_APPLY);
+    rc = action_func(argc, apply_argv, ACTION_APPLY);
     if ( rc )
-        action_func(1, new_argv, ACTION_UNLOAD);
+        action_func(1 /* only <id> */, upload_argv, ACTION_UNLOAD);
 
+error:
+    free(apply_argv);
     free(path);
     return rc;
 }
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index ef081f112c..c5655a43d2 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1575,9 +1575,17 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                 break;
             }
 
-            rc = build_id_dep(data, !!list_empty(&applied_list));
-            if ( rc )
-                break;
+            /*
+             * Check if action is issued with nodeps flags to ignore module
+             * stack dependencies.
+             */
+            if ( !(action->flags & LIVEPATCH_ACTION_APPLY_NODEPS) )
+            {
+                rc = build_id_dep(data, !!list_empty(&applied_list));
+                if ( rc )
+                    break;
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 91c48dcae0..1b2b165a6d 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -35,7 +35,7 @@
 #include "domctl.h"
 #include "physdev.h"
 
-#define XEN_SYSCTL_INTERFACE_VERSION 0x00000012
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000013
 
 /*
  * Read console content from Xen buffer ring.
@@ -956,6 +956,15 @@ struct xen_sysctl_livepatch_action {
                                             /* hypervisor default. */
                                             /* Or upper bound of time (ns) */
                                             /* for operation to take. */
+
+/*
+ * Overwrite default inter-module buildid dependency chain enforcement.
+ * Check only if module is built for given hypervisor by comparing buildid.
+ */
+#define LIVEPATCH_ACTION_APPLY_NODEPS (1 << 0)
+    uint64_t flags;                         /* IN: action flags. */
+                                            /* Provide additional parameters */
+                                            /* for an action. */
 };
 
 struct xen_sysctl_livepatch_op {
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 03/12] livepatch: Export payload structure via livepatch_payload.h
  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   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 04/12] livepatch: Implement pre-|post- apply|revert hooks Pawel Wieczorkiewicz
                     ` (11 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

The payload structure will be used by the new hooks implementation and
therefore its definition has to be exported via the livepatch_payload
header.
The new hooks will make use of the payload structure fields and the
hooks' pointers will also be defined in the payload structure, so
the structure along with all field definitions needs to be available
to the code being patched in.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Eslam Elnikety <elnikety@amazon.de>
Reviewed-by: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 xen/common/livepatch.c              | 37 ----------------------------------
 xen/include/xen/livepatch_payload.h | 40 +++++++++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 37 deletions(-)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index c5655a43d2..b3a2b9fafd 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -45,43 +45,6 @@ static LIST_HEAD(applied_list);
 static unsigned int payload_cnt;
 static unsigned int payload_version = 1;
 
-/* To contain the ELF Note header. */
-struct livepatch_build_id {
-   const void *p;
-   unsigned int len;
-};
-
-struct payload {
-    uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
-    int32_t rc;                          /* 0 or -XEN_EXX. */
-    bool reverted;                       /* Whether it was reverted. */
-    bool safe_to_reapply;                /* Can apply safely after revert. */
-    struct list_head list;               /* Linked to 'payload_list'. */
-    const void *text_addr;               /* Virtual address of .text. */
-    size_t text_size;                    /* .. and its size. */
-    const void *rw_addr;                 /* Virtual address of .data. */
-    size_t rw_size;                      /* .. and its size (if any). */
-    const void *ro_addr;                 /* Virtual address of .rodata. */
-    size_t ro_size;                      /* .. and its size (if any). */
-    unsigned int pages;                  /* Total pages for [text,rw,ro]_addr */
-    struct list_head applied_list;       /* Linked to 'applied_list'. */
-    struct livepatch_func *funcs;        /* The array of functions to patch. */
-    unsigned int nfuncs;                 /* Nr of functions to patch. */
-    const struct livepatch_symbol *symtab; /* All symbols. */
-    const char *strtab;                  /* Pointer to .strtab. */
-    struct virtual_region region;        /* symbol, bug.frame patching and
-                                            exception table (x86). */
-    unsigned int nsyms;                  /* Nr of entries in .strtab and symbols. */
-    struct livepatch_build_id id;        /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */
-    struct livepatch_build_id dep;       /* ELFNOTE_DESC(.livepatch.depends). */
-    struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
-    livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
-    livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
-    unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
-    unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
-    char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
-};
-
 /* Defines an outstanding patching action. */
 struct livepatch_work
 {
diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h
index 4a1a96d054..99613af2db 100644
--- a/xen/include/xen/livepatch_payload.h
+++ b/xen/include/xen/livepatch_payload.h
@@ -4,6 +4,15 @@
 
 #ifndef __XEN_LIVEPATCH_PAYLOAD_H__
 #define __XEN_LIVEPATCH_PAYLOAD_H__
+#include <xen/virtual_region.h>
+
+/* To contain the ELF Note header. */
+struct livepatch_build_id {
+   const void *p;
+   unsigned int len;
+};
+
+typedef struct payload livepatch_payload_t;
 
 /*
  * The following definitions are to be used in patches. They are taken
@@ -12,6 +21,37 @@
 typedef void livepatch_loadcall_t(void);
 typedef void livepatch_unloadcall_t(void);
 
+struct payload {
+    uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
+    int32_t rc;                          /* 0 or -XEN_EXX. */
+    bool reverted;                       /* Whether it was reverted. */
+    bool safe_to_reapply;                /* Can apply safely after revert. */
+    struct list_head list;               /* Linked to 'payload_list'. */
+    const void *text_addr;               /* Virtual address of .text. */
+    size_t text_size;                    /* .. and its size. */
+    const void *rw_addr;                 /* Virtual address of .data. */
+    size_t rw_size;                      /* .. and its size (if any). */
+    const void *ro_addr;                 /* Virtual address of .rodata. */
+    size_t ro_size;                      /* .. and its size (if any). */
+    unsigned int pages;                  /* Total pages for [text,rw,ro]_addr */
+    struct list_head applied_list;       /* Linked to 'applied_list'. */
+    struct livepatch_func *funcs;        /* The array of functions to patch. */
+    unsigned int nfuncs;                 /* Nr of functions to patch. */
+    const struct livepatch_symbol *symtab; /* All symbols. */
+    const char *strtab;                  /* Pointer to .strtab. */
+    struct virtual_region region;        /* symbol, bug.frame patching and
+                                            exception table (x86). */
+    unsigned int nsyms;                  /* Nr of entries in .strtab and symbols. */
+    struct livepatch_build_id id;        /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */
+    struct livepatch_build_id dep;       /* ELFNOTE_DESC(.livepatch.depends). */
+    struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
+    livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
+    livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
+    unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
+    unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
+    char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
+};
+
 /*
  * LIVEPATCH_LOAD_HOOK macro
  *
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 04/12] livepatch: Implement pre-|post- apply|revert hooks
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (2 preceding siblings ...)
  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   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 05/12] livepatch: Add support for apply|revert action replacement hooks Pawel Wieczorkiewicz
                     ` (10 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

This is an implementation of 4 new livepatch module vetoing hooks,
that can be optionally supplied along with modules.
Hooks that currently exists in the livepatch mechanism aren't agile
enough and have various limitations:
* run only from within a quiescing zone
* cannot conditionally prevent applying or reverting
* do not have access to the module context
To address these limitations the following has been implemented:
1) pre-apply hook
  runs before the apply action is scheduled for execution. Its main
  purpose is to prevent from applying a hotpatch when certain
  expected conditions aren't met or when mutating actions implemented
  in the hook fail or cannot be executed.

2) post-apply hook
  runs after the apply action has been executed and quiescing zone
  exited. Its main purpose is to provide an ability to follow-up on
  actions performed by the pre- hook, when module application was
  successful or undo certain preparation steps of the pre- hook in
  case of a failure. The success/failure error code is proviVded to
  the post- hooks via the rc field of the payload structure.

3) pre-revert hook
  runs before the revert action is scheduled for execution. Its main
  purpose is to prevent from reverting a hotpatch when certain
  expected conditions aren't met or when mutating actions implemented
  in the hook fail or cannot be executed.

4) post-revert hook
  runs after the revert action has been executed and quiescing zone
  exited. Its main purpose is to perform cleanup of all previously
  executed mutating actions in order to restore the original system
  state from before the current module application.
  The success/failure error code is provided to the post- hooks via
  the rc field of the payload structure.

The replace action performs atomically the following actions:
- revert all applied modules
- apply a single replacement module.
With the vetoing hooks in place various inter-hook dependencies may
arise. Also, during the revert part of the operation certain vetoing
hooks may detect failing conditions that previously were satisfied.
That could in turn lead to situation when the revert part must be
rolled back with all the pre- and post- hooks re-applied, which again
can't be guaranteed to always succeed.
The simplest response to this complication is to disallow the replace
action completely on modules with vetoing hooks.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Petre Eftime <epetre@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
Changed since v1:
  * added corresponding documentation
  * added tests

 .gitignore                                  |   6 +-
 docs/misc/livepatch.pandoc                  |  90 +++++++++++++-
 xen/common/livepatch.c                      | 179 +++++++++++++++++++++++++---
 xen/include/xen/livepatch_payload.h         |  27 +++++
 xen/test/livepatch/Makefile                 |  19 ++-
 xen/test/livepatch/xen_prepost_hooks.c      | 122 +++++++++++++++++++
 xen/test/livepatch/xen_prepost_hooks_fail.c |  75 ++++++++++++
 7 files changed, 492 insertions(+), 26 deletions(-)
 create mode 100644 xen/test/livepatch/xen_prepost_hooks.c
 create mode 100644 xen/test/livepatch/xen_prepost_hooks_fail.c

diff --git a/.gitignore b/.gitignore
index 6f83fc8728..5b80e2bbd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -308,11 +308,7 @@ xen/include/xen/acm_policy.h
 xen/include/xen/compile.h
 xen/include/xen/lib/x86/cpuid-autogen.h
 xen/test/livepatch/config.h
-xen/test/livepatch/xen_bye_world.livepatch
-xen/test/livepatch/xen_hello_world.livepatch
-xen/test/livepatch/xen_nop.livepatch
-xen/test/livepatch/xen_replace_world.livepatch
-xen/test/livepatch/xen_no_xen_buildid.livepatch
+xen/test/livepatch/*.livepatch
 xen/tools/kconfig/.tmp_gtkcheck
 xen/tools/kconfig/.tmp_qtcheck
 xen/tools/symbols
diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index fd1f5d0126..ae8566eb30 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -23,6 +23,9 @@ The document is split in four sections:
  * payload - telemetries of the old code along with binary blob of the new
    function (if needed).
  * reloc - telemetries contained in the payload to construct proper trampoline.
+ * hook - an auxiliary function being called before, during or after payload
+          application or revert.
+ * quiescing zone - period when all CPUs are lock-step with each other.
 
 ## History
 
@@ -270,6 +273,10 @@ like what the Linux kernel module loader does.
 The payload contains at least three sections:
 
  * `.livepatch.funcs` - which is an array of livepatch_func structures.
+   and/or any of:
+ * `.livepatch.hooks.{preapply,postapply,prerevert,postrevert}'
+   - which are a pointer to a hook function pointer.
+
  * `.livepatch.xen_depends` - which is an ELF Note that describes what Xen
     build-id the payload depends on. **MUST** have one.
  * `.livepatch.depends` - which is an ELF Note that describes what the payload
@@ -330,12 +337,24 @@ When reverting a patch, the hypervisor iterates over each `livepatch_func`
 and the core code copies the data from the undo buffer (private internal copy)
 to `old_addr`.
 
-It optionally may contain the address of functions to be called right before
-being applied and after being reverted:
+It optionally may contain the address of hooks to be called right before
+being applied and after being reverted (while all CPUs are still in quiescing
+zone). These hooks do not have access to payload structure.
 
  * `.livepatch.hooks.load` - an array of function pointers.
  * `.livepatch.hooks.unload` - an array of function pointers.
 
+It optionally may also contain the address of pre- and post- vetoing hooks to
+be called before (pre) or after (post) apply and revert payload actions (while
+all CPUs are already released from quiescing zone). These hooks do have
+access to payload structure. The pre-apply hook can prevent from loading the
+payload if encoded in it condition is not met. Accordingly, the pre-revert
+hook can prevent from unloading the hotpatch if encoded in it condition is not
+met.
+
+ * `.livepatch.hooks.{preapply,postapply}`
+ * `.livepatch.hooks.{prerevert,postrevert}`
+   - which are a pointer to a single hook function pointer.
 
 ### Example of .livepatch.funcs
 
@@ -371,7 +390,9 @@ A simple example of what a payload file can be:
 
 Code must be compiled with `-fPIC`.
 
-### .livepatch.hooks.load and .livepatch.hooks.unload
+### Hooks
+
+#### .livepatch.hooks.load and .livepatch.hooks.unload
 
 This section contains an array of function pointers to be executed
 before payload is being applied (.livepatch.funcs) or after reverting
@@ -385,6 +406,69 @@ The type definition of the function are as follow:
     typedef void (*livepatch_loadcall_t)(void);
     typedef void (*livepatch_unloadcall_t)(void);
 
+#### .livepatch.hooks.preapply
+
+This section contains a pointer to a single function pointer to be executed
+before apply action is scheduled (and thereby before CPUs are put into
+quiescing zone). This is useful to prevent from applying a payload when
+certain expected conditions aren't met or when mutating actions implemented
+in the hook fail or cannot be executed.
+This type of hooks do have access to payload structure.
+
+Each entry in this array is eight bytes.
+
+The type definition of the function are as follow:
+
+    typedef int livepatch_precall_t(livepatch_payload_t *arg);
+
+#### .livepatch.hooks.postapply
+
+This section contains a pointer to a single function pointer to be executed
+after apply action has finished and after all CPUs left the quiescing zone.
+This is useful to provide an ability to follow up on actions performed by
+the preapply hook. Especially, when module application was successful or to
+be able to undo certain preparation steps of the preapply hook in case of a
+failure. The success/failure error code is provided to the postapply hooks
+via the `rc` field of the payload structure.
+This type of hooks do have access to payload structure.
+
+Each entry in this array is eight bytes.
+
+The type definition of the function are as follow:
+
+    typedef void livepatch_postcall_t(livepatch_payload_t *arg);
+
+#### .livepatch.hooks.prerevert
+
+This section contains a pointer to a single function pointer to be executed
+before revert action is scheduled (and thereby before CPUs are put into
+quiescing zone). This is useful to prevent from reverting a payload when
+certain expected conditions aren't met or when mutating actions implemented
+in the hook fail or cannot be executed.
+This type of hooks do have access to payload structure.
+
+Each entry in this array is eight bytes.
+
+The type definition of the function are as follow:
+
+    typedef int livepatch_precall_t(livepatch_payload_t *arg);
+
+#### .livepatch.hooks.postrevert
+
+This section contains a pointer to a single function pointer to be executed
+after revert action has finished and after all CPUs left the quiescing zone.
+This is useful to provide an ability to perform cleanup of all previously
+executed mutating actions in order to restore the original system state from
+before the current payload application. The success/failure error code is
+provided to the postrevert hook via the `rc` field of the payload structure.
+This type of hooks do have access to payload structure.
+
+Each entry in this array is eight bytes.
+
+The type definition of the function are as follow:
+
+    typedef void livepatch_postcall_t(livepatch_payload_t *arg);
+
 ### .livepatch.xen_depends, .livepatch.depends and .note.gnu.build-id
 
 To support dependencies checking and safe loading (to load the
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index b3a2b9fafd..c5dae8814f 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -28,6 +28,8 @@
 #include <asm/alternative.h>
 #include <asm/event.h>
 
+#define is_hook_enabled(hook) ({ (hook) && *(hook); })
+
 /*
  * Protects against payload_list operations and also allows only one
  * caller in schedule_work.
@@ -501,6 +503,35 @@ static int check_special_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+/*
+ * Lookup specified section and when exists assign its address to a specified hook.
+ * Perform section pointer and size validation: single hook sections must contain a
+ * single pointer only.
+ */
+#define LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, hook, section_name) do {                        \
+    const struct livepatch_elf_sec *__sec = livepatch_elf_sec_by_name(elf, section_name); \
+    if ( !__sec )                                                                         \
+        break;                                                                            \
+    if ( !section_ok(elf, __sec, sizeof(*hook)) || __sec->sec->sh_size != sizeof(*hook) ) \
+        return -EINVAL;                                                                   \
+    hook = __sec->load_addr;                                                              \
+} while (0)
+
+/*
+ * Lookup specified section and when exists assign its address to a specified hook.
+ * Perform section pointer and size validation: multi hook sections must contain an
+ * array whose size must be a multiple of the array's items size.
+ */
+#define LIVEPATCH_ASSIGN_MULTI_HOOK(elf, hook, nhooks, section_name) do {                 \
+    const struct livepatch_elf_sec *__sec = livepatch_elf_sec_by_name(elf, section_name); \
+    if ( !__sec )                                                                         \
+        break;                                                                            \
+    if ( !section_ok(elf, __sec, sizeof(*hook)) )                                         \
+        return -EINVAL;                                                                   \
+    hook = __sec->load_addr;                                                              \
+    nhooks = __sec->sec->sh_size / sizeof(*hook);                                         \
+} while (0)
+
 static int prepare_payload(struct payload *payload,
                            struct livepatch_elf *elf)
 {
@@ -552,25 +583,14 @@ static int prepare_payload(struct payload *payload,
             return rc;
     }
 
-    sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.load");
-    if ( sec )
-    {
-        if ( !section_ok(elf, sec, sizeof(*payload->load_funcs)) )
-            return -EINVAL;
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->load_funcs, payload->n_load_funcs, ".livepatch.hooks.load");
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ".livepatch.hooks.unload");
 
-        payload->load_funcs = sec->load_addr;
-        payload->n_load_funcs = sec->sec->sh_size / sizeof(*payload->load_funcs);
-    }
-
-    sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.unload");
-    if ( sec )
-    {
-        if ( !section_ok(elf, sec, sizeof(*payload->unload_funcs)) )
-            return -EINVAL;
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.pre, ".livepatch.hooks.preapply");
+    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.post, ".livepatch.hooks.postrevert");
 
-        payload->unload_funcs = sec->load_addr;
-        payload->n_unload_funcs = sec->sec->sh_size / sizeof(*payload->unload_funcs);
-    }
     sec = livepatch_elf_sec_by_name(elf, ELF_BUILD_ID_NOTE);
     if ( sec )
     {
@@ -1217,6 +1237,39 @@ static bool_t is_work_scheduled(const struct payload *data)
     return livepatch_work.do_work && livepatch_work.data == data;
 }
 
+/*
+ * Check if payload has any of the vetoing, non-atomic hooks assigned.
+ * A vetoing, non-atmic hook may perform an operation that changes the
+ * hypervisor state and may not be guaranteed to succeed. Result of
+ * such operation may be returned and may change the livepatch workflow.
+ * Such hooks may require additional cleanup actions performed by other
+ * hooks. Thus they are not suitable for replace action.
+ */
+static inline bool_t has_payload_any_vetoing_hooks(const struct payload *payload)
+{
+    return is_hook_enabled(payload->hooks.apply.pre) ||
+           is_hook_enabled(payload->hooks.apply.post) ||
+           is_hook_enabled(payload->hooks.revert.pre) ||
+           is_hook_enabled(payload->hooks.revert.post);
+}
+
+/*
+ * Checks if any of the already applied hotpatches has any vetoing,
+ * non-atomic hooks assigned.
+ */
+static inline bool_t livepatch_applied_have_vetoing_hooks(void)
+{
+    struct payload *p;
+
+    list_for_each_entry ( p, &applied_list, applied_list )
+    {
+        if ( has_payload_any_vetoing_hooks(p) )
+            return true;
+    }
+
+    return false;
+}
+
 static int schedule_work(struct payload *data, uint32_t cmd, uint32_t timeout)
 {
     ASSERT(spin_is_locked(&payload_lock));
@@ -1317,6 +1370,7 @@ void check_for_livepatch_work(void)
     {
         struct payload *p;
         unsigned int cpus;
+        bool_t action_done = false;
 
         p = livepatch_work.data;
         if ( !get_cpu_maps() )
@@ -1369,6 +1423,7 @@ void check_for_livepatch_work(void)
             livepatch_do_action();
             /* Serialize and flush out the CPU via CPUID instruction (on x86). */
             arch_livepatch_post_action();
+            action_done = true;
             local_irq_restore(flags);
         }
 
@@ -1381,6 +1436,43 @@ void check_for_livepatch_work(void)
         /* put_cpu_maps has an barrier(). */
         put_cpu_maps();
 
+        if ( action_done )
+        {
+            switch ( livepatch_work.cmd )
+            {
+            case LIVEPATCH_ACTION_REVERT:
+                if ( is_hook_enabled(p->hooks.revert.post) )
+                {
+                    printk(XENLOG_INFO LIVEPATCH "%s: Calling post-revert hook function with rc=%d\n",
+                           p->name, p->rc);
+
+                    (*p->hooks.revert.post)(p);
+                }
+                break;
+
+            case LIVEPATCH_ACTION_APPLY:
+                if ( is_hook_enabled(p->hooks.apply.post) )
+                {
+                    printk(XENLOG_INFO LIVEPATCH "%s: Calling post-apply hook function with rc=%d\n",
+                           p->name, p->rc);
+
+                    (*p->hooks.apply.post)(p);
+                }
+                break;
+
+            case LIVEPATCH_ACTION_REPLACE:
+                if ( has_payload_any_vetoing_hooks(p) )
+                {
+                    /* It should be impossible to get here since livepatch_action() guards against that. */
+                    panic(LIVEPATCH "%s: REPLACE action is not supported on hotpatches with vetoing hooks!\n",
+                            p->name);
+                    ASSERT_UNREACHABLE();
+                }
+            default:
+                break;
+            }
+        }
+
         printk(XENLOG_INFO LIVEPATCH "%s finished %s with rc=%d\n",
                p->name, names[livepatch_work.cmd], p->rc);
     }
@@ -1516,6 +1608,21 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                 rc = -EBUSY;
                 break;
             }
+
+            if ( is_hook_enabled(data->hooks.revert.pre) )
+            {
+                printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-revert hook function\n", data->name);
+
+                rc = (*data->hooks.revert.pre)(data);
+                if ( rc )
+                {
+                    printk(XENLOG_ERR LIVEPATCH "%s: pre-revert hook failed (rc=%d), aborting!\n",
+                           data->name, rc);
+                    data->rc = rc;
+                    break;
+                }
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
@@ -1549,6 +1656,20 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                     break;
             }
 
+            if ( is_hook_enabled(data->hooks.apply.pre) )
+            {
+                printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-apply hook function\n", data->name);
+
+                rc = (*data->hooks.apply.pre)(data);
+                if ( rc )
+                {
+                    printk(XENLOG_ERR LIVEPATCH "%s: pre-apply hook failed (rc=%d), aborting!\n",
+                           data->name, rc);
+                    data->rc = rc;
+                    break;
+                }
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
@@ -1560,6 +1681,30 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
             rc = build_id_dep(data, 1 /* against hypervisor. */);
             if ( rc )
                 break;
+
+            /*
+             * REPLACE action is not supported on hotpatches with vetoing hooks.
+             * Vetoing hooks usually perform mutating actions on the system and
+             * typically exist in pairs (pre- hook doing an action and post- hook
+             * undoing the action). Coalescing all hooks from all applied modules
+             * cannot be performed without inspecting potential dependencies between
+             * the mutating hooks and hence cannot be performed automatically by
+             * the replace action. Also, the replace action cannot safely assume a
+             * successful revert of all the module with vetoing hooks. When one
+             * of the hooks fails due to not meeting certain conditions the whole
+             * replace operation must have been reverted with all previous pre- and
+             * post- hooks re-executed (which cannot be guaranteed to succeed).
+             * The simplest response to this complication is disallow replace
+             * action on modules with vetoing hooks.
+             */
+            if ( has_payload_any_vetoing_hooks(data) || livepatch_applied_have_vetoing_hooks() )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: REPLACE action is not supported on hotpatches with vetoing hooks!\n",
+                       data->name);
+                rc = -EOPNOTSUPP;
+                break;
+            }
+
             data->rc = -EAGAIN;
             rc = schedule_work(data, action->cmd, action->timeout);
         }
diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h
index 99613af2db..cd20944cc4 100644
--- a/xen/include/xen/livepatch_payload.h
+++ b/xen/include/xen/livepatch_payload.h
@@ -21,6 +21,16 @@ typedef struct payload livepatch_payload_t;
 typedef void livepatch_loadcall_t(void);
 typedef void livepatch_unloadcall_t(void);
 
+typedef int livepatch_precall_t(livepatch_payload_t *arg);
+typedef void livepatch_postcall_t(livepatch_payload_t *arg);
+
+struct livepatch_hooks {
+    struct {
+        livepatch_precall_t *const *pre;
+        livepatch_postcall_t *const *post;
+    } apply, revert;
+};
+
 struct payload {
     uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
     int32_t rc;                          /* 0 or -XEN_EXX. */
@@ -47,6 +57,7 @@ struct payload {
     struct livepatch_build_id xen_dep;   /* ELFNOTE_DESC(.livepatch.xen_depends). */
     livepatch_loadcall_t *const *load_funcs;   /* The array of funcs to call after */
     livepatch_unloadcall_t *const *unload_funcs;/* load and unload of the payload. */
+    struct livepatch_hooks hooks;        /* Pre and post hooks for apply and revert */
     unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
     unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
     char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
@@ -76,6 +87,22 @@ struct payload {
      livepatch_unloadcall_t *__weak \
         const livepatch_unload_data_##_fn __section(".livepatch.hooks.unload") = _fn;
 
+#define LIVEPATCH_PREAPPLY_HOOK(_fn) \
+    livepatch_precall_t *__attribute__((weak, used)) \
+        const livepatch_preapply_data_##_fn __section(".livepatch.hooks.preapply") = _fn;
+
+#define LIVEPATCH_POSTAPPLY_HOOK(_fn) \
+    livepatch_postcall_t *__attribute__((weak, used)) \
+        const livepatch_postapply_data_##_fn __section(".livepatch.hooks.postapply") = _fn;
+
+#define LIVEPATCH_PREREVERT_HOOK(_fn) \
+    livepatch_precall_t *__attribute__((weak, used)) \
+        const livepatch_prerevert_data_##_fn __section(".livepatch.hooks.prerevert") = _fn;
+
+#define LIVEPATCH_POSTREVERT_HOOK(_fn) \
+    livepatch_postcall_t *__attribute__((weak, used)) \
+        const livepatch_postrevert_data_##_fn __section(".livepatch.hooks.postrevert") = _fn;
+
 #endif /* __XEN_LIVEPATCH_PAYLOAD_H__ */
 
 /*
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 938aee17ec..a94bc48536 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -20,12 +20,16 @@ LIVEPATCH_BYE := xen_bye_world.livepatch
 LIVEPATCH_REPLACE := xen_replace_world.livepatch
 LIVEPATCH_NOP := xen_nop.livepatch
 LIVEPATCH_NO_XEN_BUILDID := xen_no_xen_buildid.livepatch
+LIVEPATCH_PREPOST_HOOKS := xen_prepost_hooks.livepatch
+LIVEPATCH_PREPOST_HOOKS_FAIL := xen_prepost_hooks_fail.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
 LIVEPATCHES += $(LIVEPATCH_REPLACE)
 LIVEPATCHES += $(LIVEPATCH_NOP)
 LIVEPATCHES += $(LIVEPATCH_NO_XEN_BUILDID)
+LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS)
+LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS_FAIL)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -128,5 +132,18 @@ xen_no_xen_buildid.o: config.h
 $(LIVEPATCH_NO_XEN_BUILDID): xen_nop.o note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NO_XEN_BUILDID) $^
 
+xen_prepost_hooks.o: config.h
+
+.PHONY: $(LIVEPATCH_PREPOST_HOOKS)
+$(LIVEPATCH_PREPOST_HOOKS): xen_prepost_hooks.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_PREPOST_HOOKS) $^
+
+xen_prepost_hooks_fail.o: config.h
+
+.PHONY: $(LIVEPATCH_PREPOST_HOOKS_FAIL)
+$(LIVEPATCH_PREPOST_HOOKS_FAIL): xen_prepost_hooks_fail.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_PREPOST_HOOKS_FAIL) $^
+
 .PHONY: livepatch
-livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID)
+livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID) \
+           $(LIVEPATCH_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL)
diff --git a/xen/test/livepatch/xen_prepost_hooks.c b/xen/test/livepatch/xen_prepost_hooks.c
new file mode 100644
index 0000000000..889377d6eb
--- /dev/null
+++ b/xen/test/livepatch/xen_prepost_hooks.c
@@ -0,0 +1,122 @@
+/*
+ * 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 pre_apply_cnt;
+static unsigned int post_apply_cnt;
+static unsigned int pre_revert_cnt;
+static unsigned int post_revert_cnt;
+
+static unsigned int pre_revert_retry = 1;
+
+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];
+
+        pre_apply_cnt++;
+        printk(KERN_DEBUG "%s: applying: %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];
+
+        post_apply_cnt++;
+        printk(KERN_DEBUG "%s: 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];
+
+        pre_revert_cnt++;
+        printk(KERN_DEBUG "%s: reverting: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    /* First revert attempt always fails. Second attempt succeeds. */
+    return -(pre_revert_retry--);
+}
+
+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];
+
+        post_revert_cnt++;
+        printk(KERN_DEBUG "%s: reverted: %s\n", __func__, func->name);
+    }
+
+    BUG_ON(pre_apply_cnt != 1 || post_apply_cnt != 1);
+    BUG_ON(pre_revert_cnt != 2 || post_revert_cnt != 1);
+    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_prepost_hooks_fail.c b/xen/test/livepatch/xen_prepost_hooks_fail.c
new file mode 100644
index 0000000000..87e5f6c5e1
--- /dev/null
+++ b/xen/test/livepatch/xen_prepost_hooks_fail.c
@@ -0,0 +1,75 @@
+/*
+ * 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);
+
+/* This hook always fail and should prevent from loading the hotpatch. */
+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];
+
+        printk(KERN_DEBUG "%s: pre applying: %s\n", __func__, func->name);
+    }
+
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return -EINVAL;
+}
+
+static int unreachable_pre_hook(livepatch_payload_t *payload)
+{
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+    BUG();
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+
+    return -EINVAL;
+}
+
+static void unreachable_post_hook(livepatch_payload_t *payload)
+{
+    printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
+    BUG();
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook);
+LIVEPATCH_POSTAPPLY_HOOK(unreachable_post_hook);
+LIVEPATCH_PREREVERT_HOOK(unreachable_pre_hook);
+LIVEPATCH_POSTREVERT_HOOK(unreachable_post_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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 05/12] livepatch: Add support for apply|revert action replacement hooks
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (3 preceding siblings ...)
  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   ` Pawel Wieczorkiewicz
  2019-08-27 16:58     ` Konrad Rzeszutek Wilk
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 06/12] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence Pawel Wieczorkiewicz
                     ` (9 subsequent siblings)
  14 siblings, 1 reply; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

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 <wipawel@amazon.de>
Reviewed-by: Petre Eftime <epetre@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.com>
Reviewed-by: Norbert Manthey <nmanthey@amazon.com>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Bjoern Doebel <doebel@amazon.com>
---
Changed since v1:
  * added corresponding documentation
  * added tests

 docs/misc/livepatch.pandoc            |  23 ++++++++
 xen/common/livepatch.c                |  66 ++++++++++++++++++----
 xen/include/xen/livepatch_payload.h   |  10 ++++
 xen/test/livepatch/Makefile           |  10 +++-
 xen/test/livepatch/xen_action_hooks.c | 100 ++++++++++++++++++++++++++++++++++
 5 files changed, 198 insertions(+), 11 deletions(-)
 create mode 100644 xen/test/livepatch/xen_action_hooks.c

diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index ae8566eb30..6fafb9e4b1 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -275,6 +275,7 @@ The payload contains at least three sections:
  * `.livepatch.funcs` - which is an array of livepatch_func structures.
    and/or any of:
  * `.livepatch.hooks.{preapply,postapply,prerevert,postrevert}'
+ * `.livepatch.hooks.{apply,revert}`
    - which are a pointer to a hook function pointer.
 
  * `.livepatch.xen_depends` - which is an ELF Note that describes what Xen
@@ -356,6 +357,14 @@ met.
  * `.livepatch.hooks.{prerevert,postrevert}`
    - which are a pointer to a single hook function pointer.
 
+Finally, it optionally may also contain the address of apply or revert action
+hooks to be called instead of the default apply and revert payload actions
+(while all CPUs are kept in quiescing zone). These hooks do have access to
+payload structure.
+
+ * `.livepatch.hooks.{apply,revert}`
+   - which are a pointer to a single hook function pointer.
+
 ### Example of .livepatch.funcs
 
 A simple example of what a payload file can be:
@@ -469,6 +478,20 @@ The type definition of the function are as follow:
 
     typedef void livepatch_postcall_t(livepatch_payload_t *arg);
 
+#### .livepatch.hooks.apply and .livepatch.hooks.revert
+
+This section contains a pointer to a single function pointer to be executed
+instead of a default apply (or revert) action function. This is useful to
+replace or augment default behavior of the apply (or revert) action that
+requires all CPUs to be in the quiescing zone.
+This type of hooks do have access to payload structure.
+
+Each entry in this array is eight bytes.
+
+The type definition of the function are as follow:
+
+    typedef int livepatch_actioncall_t(livepatch_payload_t *arg);
+
 ### .livepatch.xen_depends, .livepatch.depends and .note.gnu.build-id
 
 To support dependencies checking and safe loading (to load the
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index c5dae8814f..577b926ba4 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;
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index a94bc48536..116e52e774 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -22,6 +22,7 @@ LIVEPATCH_NOP := xen_nop.livepatch
 LIVEPATCH_NO_XEN_BUILDID := xen_no_xen_buildid.livepatch
 LIVEPATCH_PREPOST_HOOKS := xen_prepost_hooks.livepatch
 LIVEPATCH_PREPOST_HOOKS_FAIL := xen_prepost_hooks_fail.livepatch
+LIVEPATCH_ACTION_HOOKS := xen_action_hooks.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
@@ -30,6 +31,7 @@ LIVEPATCHES += $(LIVEPATCH_NOP)
 LIVEPATCHES += $(LIVEPATCH_NO_XEN_BUILDID)
 LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS)
 LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS_FAIL)
+LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -144,6 +146,12 @@ xen_prepost_hooks_fail.o: config.h
 $(LIVEPATCH_PREPOST_HOOKS_FAIL): xen_prepost_hooks_fail.o xen_hello_world_func.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_PREPOST_HOOKS_FAIL) $^
 
+xen_actions_hooks.o: config.h
+
+.PHONY: $(LIVEPATCH_ACTION_HOOKS)
+$(LIVEPATCH_ACTION_HOOKS): xen_action_hooks.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS) $^
+
 .PHONY: livepatch
 livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID) \
-           $(LIVEPATCH_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL)
+           $(LIVEPATCH_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL) $(LIVEPATCH_ACTION_HOOKS)
diff --git a/xen/test/livepatch/xen_action_hooks.c b/xen/test/livepatch/xen_action_hooks.c
new file mode 100644
index 0000000000..a947afc41f
--- /dev/null
+++ b/xen/test/livepatch/xen_action_hooks.c
@@ -0,0 +1,100 @@
+/*
+ * 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 unsigned int revert_cnt;
+
+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 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 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];
+
+        printk(KERN_DEBUG "%s: reverted: %s\n", __func__, func->name);
+    }
+
+    BUG_ON(apply_cnt != 1 || revert_cnt != 1);
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+LIVEPATCH_APPLY_HOOK(apply_hook);
+LIVEPATCH_REVERT_HOOK(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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 06/12] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (4 preceding siblings ...)
  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  8:46   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 07/12] livepatch: Add per-function applied/reverted state tracking marker Pawel Wieczorkiewicz
                     ` (8 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

With default implementation the ELF_LIVEPATCH_FUNC section containing
all functions to be replaced or added must be part of the hotpatch
payload, otherwise the payload is rejected (with -EINVAL).

However, with the extended hooks implementation, a hotpatch may be
constructed of only hooks to perform certain actions without any code
to be added or replaced.
Therefore, do not always expect the functions section and allow it to
be missing, provided there is at least one section containing hooks
present. The functions section, when present in a payload, must be a
single, non-empty section.

Check also all extended hooks sections if they are a single, non-empty
sections each.

At least one of the functions or hooks section must be present in a
valid payload.

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:
  * always print XENLOG_ERR messages
  * remove ASSERT from build_symbol_table()
  * added corresponding documentation
  * added tests

 xen/common/livepatch.c                       | 147 +++++++++++++++++++--------
 xen/include/xen/livepatch.h                  |   8 ++
 xen/test/livepatch/Makefile                  |   9 +-
 xen/test/livepatch/xen_action_hooks_nofunc.c |  86 ++++++++++++++++
 4 files changed, 206 insertions(+), 44 deletions(-)
 create mode 100644 xen/test/livepatch/xen_action_hooks_nofunc.c

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 577b926ba4..705b5b8151 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -467,8 +467,7 @@ static int check_xen_build_id(const struct payload *payload)
 static int check_special_sections(const struct livepatch_elf *elf)
 {
     unsigned int i;
-    static const char *const names[] = { ELF_LIVEPATCH_FUNC,
-                                         ELF_LIVEPATCH_DEPENDS,
+    static const char *const names[] = { ELF_LIVEPATCH_DEPENDS,
                                          ELF_LIVEPATCH_XEN_DEPENDS,
                                          ELF_BUILD_ID_NOTE};
     DECLARE_BITMAP(found, ARRAY_SIZE(names)) = { 0 };
@@ -503,6 +502,64 @@ static int check_special_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+static int check_patching_sections(const struct livepatch_elf *elf)
+{
+    unsigned int i;
+    static const char *const names[] = { ELF_LIVEPATCH_FUNC,
+                                         ELF_LIVEPATCH_LOAD_HOOKS,
+                                         ELF_LIVEPATCH_UNLOAD_HOOKS,
+                                         ELF_LIVEPATCH_PREAPPLY_HOOK,
+                                         ELF_LIVEPATCH_APPLY_HOOK,
+                                         ELF_LIVEPATCH_POSTAPPLY_HOOK,
+                                         ELF_LIVEPATCH_PREREVERT_HOOK,
+                                         ELF_LIVEPATCH_REVERT_HOOK,
+                                         ELF_LIVEPATCH_POSTREVERT_HOOK};
+    DECLARE_BITMAP(found, ARRAY_SIZE(names)) = { 0 };
+
+    /*
+     * The patching sections are optional, but at least one
+     * must be present. Otherwise, there is nothing to do.
+     * All the existing sections must not be empty and must
+     * be present at most once.
+     */
+    for ( i = 0; i < ARRAY_SIZE(names); i++ )
+    {
+        const struct livepatch_elf_sec *sec;
+
+        sec = livepatch_elf_sec_by_name(elf, names[i]);
+        if ( !sec )
+        {
+            dprintk(XENLOG_DEBUG, LIVEPATCH "%s: %s is missing\n",
+                    elf->name, names[i]);
+            continue; /* This section is optional */
+        }
+
+        if ( !sec->sec->sh_size )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: %s is empty\n",
+                   elf->name, names[i]);
+            return -EINVAL;
+        }
+
+        if ( test_and_set_bit(i, found) )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: %s was seen more than once\n",
+                    elf->name, names[i]);
+            return -EINVAL;
+        }
+    }
+
+    /* Checking if at least one section is present. */
+    if ( bitmap_empty(found, ARRAY_SIZE(names)) )
+    {
+        printk(XENLOG_ERR LIVEPATCH "%s: Nothing to patch. Aborting...\n",
+               elf->name);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 /*
  * Lookup specified section and when exists assign its address to a specified hook.
  * Perform section pointer and size validation: single hook sections must contain a
@@ -542,57 +599,59 @@ static int prepare_payload(struct payload *payload,
     const Elf_Note *n;
 
     sec = livepatch_elf_sec_by_name(elf, ELF_LIVEPATCH_FUNC);
-    ASSERT(sec);
-    if ( !section_ok(elf, sec, sizeof(*payload->funcs)) )
-        return -EINVAL;
-
-    payload->funcs = sec->load_addr;
-    payload->nfuncs = sec->sec->sh_size / sizeof(*payload->funcs);
-
-    for ( i = 0; i < payload->nfuncs; i++ )
+    if ( sec )
     {
-        int rc;
+        if ( !section_ok(elf, sec, sizeof(*payload->funcs)) )
+            return -EINVAL;
 
-        f = &(payload->funcs[i]);
+        payload->funcs = sec->load_addr;
+        payload->nfuncs = sec->sec->sh_size / sizeof(*payload->funcs);
 
-        if ( f->version != LIVEPATCH_PAYLOAD_VERSION )
+        for ( i = 0; i < payload->nfuncs; i++ )
         {
-            printk(XENLOG_ERR LIVEPATCH "%s: Wrong version (%u). Expected %d\n",
-                   elf->name, f->version, LIVEPATCH_PAYLOAD_VERSION);
-            return -EOPNOTSUPP;
-        }
+            int rc;
 
-        /* 'old_addr', 'new_addr', 'new_size' can all be zero. */
-        if ( !f->old_size )
-        {
-            printk(XENLOG_ERR LIVEPATCH "%s: Address or size fields are zero\n",
-                   elf->name);
-            return -EINVAL;
-        }
+            f = &(payload->funcs[i]);
 
-        rc = arch_livepatch_verify_func(f);
-        if ( rc )
-            return rc;
+            if ( f->version != LIVEPATCH_PAYLOAD_VERSION )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: Wrong version (%u). Expected %d\n",
+                       elf->name, f->version, LIVEPATCH_PAYLOAD_VERSION);
+                return -EOPNOTSUPP;
+            }
 
-        rc = resolve_old_address(f, elf);
-        if ( rc )
-            return rc;
+            /* 'old_addr', 'new_addr', 'new_size' can all be zero. */
+            if ( !f->old_size )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: Address or size fields are zero\n",
+                       elf->name);
+                return -EINVAL;
+            }
 
-        rc = livepatch_verify_distance(f);
-        if ( rc )
-            return rc;
+            rc = arch_livepatch_verify_func(f);
+            if ( rc )
+                return rc;
+
+            rc = resolve_old_address(f, elf);
+            if ( rc )
+                return rc;
+
+            rc = livepatch_verify_distance(f);
+            if ( rc )
+                return rc;
+        }
     }
 
-    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->load_funcs, payload->n_load_funcs, ".livepatch.hooks.load");
-    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ".livepatch.hooks.unload");
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->load_funcs, payload->n_load_funcs, ELF_LIVEPATCH_LOAD_HOOKS);
+    LIVEPATCH_ASSIGN_MULTI_HOOK(elf, payload->unload_funcs, payload->n_unload_funcs, ELF_LIVEPATCH_UNLOAD_HOOKS);
 
-    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.apply.pre, ELF_LIVEPATCH_PREAPPLY_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.action, ELF_LIVEPATCH_APPLY_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.apply.post, ELF_LIVEPATCH_POSTAPPLY_HOOK);
 
-    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");
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.pre, ELF_LIVEPATCH_PREREVERT_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.action, ELF_LIVEPATCH_REVERT_HOOK);
+    LIVEPATCH_ASSIGN_SINGLE_HOOK(elf, payload->hooks.revert.post, ELF_LIVEPATCH_POSTREVERT_HOOK);
 
     sec = livepatch_elf_sec_by_name(elf, ELF_BUILD_ID_NOTE);
     if ( sec )
@@ -786,8 +845,6 @@ static int build_symbol_table(struct payload *payload,
     struct livepatch_symbol *symtab;
     char *strtab;
 
-    ASSERT(payload->nfuncs);
-
     /* Recall that section @0 is always NULL. */
     for ( i = 1; i < elf->nsym; i++ )
     {
@@ -904,6 +961,10 @@ static int load_payload_data(struct payload *payload, void *raw, size_t len)
     if ( rc )
         goto out;
 
+    rc = check_patching_sections(&elf);
+    if ( rc )
+        goto out;
+
     rc = prepare_payload(payload, &elf);
     if ( rc )
         goto out;
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index ed997aa4cc..2aec532ee2 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -33,6 +33,14 @@ struct xen_sysctl_livepatch_op;
 #define ELF_LIVEPATCH_DEPENDS     ".livepatch.depends"
 #define ELF_LIVEPATCH_XEN_DEPENDS ".livepatch.xen_depends"
 #define ELF_BUILD_ID_NOTE         ".note.gnu.build-id"
+#define ELF_LIVEPATCH_LOAD_HOOKS      ".livepatch.hooks.load"
+#define ELF_LIVEPATCH_UNLOAD_HOOKS    ".livepatch.hooks.unload"
+#define ELF_LIVEPATCH_PREAPPLY_HOOK   ".livepatch.hooks.preapply"
+#define ELF_LIVEPATCH_APPLY_HOOK      ".livepatch.hooks.apply"
+#define ELF_LIVEPATCH_POSTAPPLY_HOOK  ".livepatch.hooks.postapply"
+#define ELF_LIVEPATCH_PREREVERT_HOOK  ".livepatch.hooks.prerevert"
+#define ELF_LIVEPATCH_REVERT_HOOK     ".livepatch.hooks.revert"
+#define ELF_LIVEPATCH_POSTREVERT_HOOK ".livepatch.hooks.postrevert"
 /* Arbitrary limit for payload size and .bss section size. */
 #define LIVEPATCH_MAX_SIZE     MB(2)
 
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 116e52e774..bbc6bdaf64 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -23,6 +23,7 @@ LIVEPATCH_NO_XEN_BUILDID := xen_no_xen_buildid.livepatch
 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
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
@@ -32,6 +33,7 @@ LIVEPATCHES += $(LIVEPATCH_NO_XEN_BUILDID)
 LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS)
 LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS_FAIL)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS)
+LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -152,6 +154,11 @@ xen_actions_hooks.o: config.h
 $(LIVEPATCH_ACTION_HOOKS): xen_action_hooks.o xen_hello_world_func.o note.o xen_note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS) $^
 
+.PHONY: $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
+$(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) $^
+
 .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_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL) $(LIVEPATCH_ACTION_HOOKS) \
+           $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
diff --git a/xen/test/livepatch/xen_action_hooks_nofunc.c b/xen/test/livepatch/xen_action_hooks_nofunc.c
new file mode 100644
index 0000000000..2b4e90436f
--- /dev/null
+++ b/xen/test/livepatch/xen_action_hooks_nofunc.c
@@ -0,0 +1,86 @@
+/*
+ * 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 unsigned int apply_cnt;
+static unsigned int revert_cnt;
+
+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 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 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];
+
+        printk(KERN_DEBUG "%s: reverted: %s\n", __func__, func->name);
+    }
+
+    BUG_ON(apply_cnt > 0 || revert_cnt > 0);
+    printk(KERN_DEBUG "%s: Hook done.\n", __func__);
+}
+
+LIVEPATCH_APPLY_HOOK(apply_hook);
+LIVEPATCH_REVERT_HOOK(revert_hook);
+
+LIVEPATCH_POSTREVERT_HOOK(post_revert_hook);
+
+/*
+ * 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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 07/12] livepatch: Add per-function applied/reverted state tracking marker
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (5 preceding siblings ...)
  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
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations Pawel Wieczorkiewicz
                     ` (7 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich, Volodymyr Babchuk, Roger Pau Monné

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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (6 preceding siblings ...)
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 07/12] livepatch: Add per-function applied/reverted state tracking marker Pawel Wieczorkiewicz
@ 2019-08-27  8:46   ` Pawel Wieczorkiewicz
  2019-08-29 14:34     ` Konrad Rzeszutek Wilk
                       ` (2 more replies)
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 09/12] livepatch: Add support for modules .modinfo section metadata Pawel Wieczorkiewicz
                     ` (6 subsequent siblings)
  14 siblings, 3 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

This is the initial implementation of the expectations enhancement
to improve inline asm hotpatching.

Expectations are designed as optional feature, since the main use of
them is planned for inline asm hotpatching. The flag enabled allows
to control the expectation state.
Each expectation has data and len fields that describe the data
that is expected to be found at a given patching (old_addr) location.
The len must not exceed the data array size. The data array size
follows the size of the opaque array, since the opaque array holds
the original data and therefore must match what is specified in the
expectation (if enabled).

The payload structure is modified as each expectation structure is
part of the livepatch_func structure and hence extends the payload.

Each expectation is checked prior to the apply action (i.e. as late
as possible to check against the most current state of the code).

For the replace action a new payload's expectations are checked AFTER
all applied payloads are successfully reverted, but BEFORE new payload
is applied. That breaks the replace action's atomicity and in case of
an expectation check failure would leave a system with all payloads
reverted. That is obviously insecure. Use it with caution and act
upon replace errors!

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
Changed since v1:
  * added corresponding documentation
  * added tests

 .gitignore                                 |  1 +
 docs/misc/livepatch.pandoc                 | 28 ++++++++++++
 xen/common/livepatch.c                     | 71 ++++++++++++++++++++++++++++++
 xen/include/public/sysctl.h                | 15 ++++++-
 xen/test/livepatch/Makefile                | 27 +++++++++++-
 xen/test/livepatch/xen_expectations.c      | 41 +++++++++++++++++
 xen/test/livepatch/xen_expectations_fail.c | 42 ++++++++++++++++++
 7 files changed, 222 insertions(+), 3 deletions(-)
 create mode 100644 xen/test/livepatch/xen_expectations.c
 create mode 100644 xen/test/livepatch/xen_expectations_fail.c

diff --git a/.gitignore b/.gitignore
index 5b80e2bbd5..cb770cc8c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -308,6 +308,7 @@ xen/include/xen/acm_policy.h
 xen/include/xen/compile.h
 xen/include/xen/lib/x86/cpuid-autogen.h
 xen/test/livepatch/config.h
+xen/test/livepatch/expect_config.h
 xen/test/livepatch/*.livepatch
 xen/tools/kconfig/.tmp_gtkcheck
 xen/tools/kconfig/.tmp_qtcheck
diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index 6ab7f4c2d2..92a424e918 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -300,6 +300,7 @@ which describe the functions to be patched:
         /* Added to livepatch payload version 2: */
         uint8_t applied;
         uint8_t _pad[7];
+        livepatch_expectation_t expect;
     };
 
 The size of the structure is 64 bytes on 64-bit hypervisors. It will be
@@ -336,6 +337,26 @@ 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.
+  * `expect` is an optional structure containing expected to-be-replaced data
+    (mostly for inline asm patching). The `expect` structure format is:
+
+    struct livepatch_expectation {
+        uint8_t enabled : 1;
+        uint8_t len : 5;
+        uint8_t data[LIVEPATCH_OPAQUE_SIZE]; /* Same size as opaque[] buffer of
+                                            struct livepatch_func. This is the
+                                            max number of bytes to be patched */
+    };
+    typedef struct livepatch_expectation livepatch_expectation_t;
+
+    * `enabled` allows to enable the expectation check for given function.
+      Default state is disabled.
+    * `len` specifies the number of valid bytes in `data` array. 5 bits is
+      enough to specify values up to 32 (of bytes), which is above the array
+      size.
+    * `data` contains expected bytes of content to be replaced. Same size as
+      `opaque` buffer of `struct livepatch_func` (max number of bytes to be
+      patched).
 
 The size of the `livepatch_func` array is determined from the ELF section
 size.
@@ -391,6 +412,7 @@ A simple example of what a payload file can be:
         /* Added to livepatch payload version 2: */
         uint8_t applied;
         uint8_t _pad[7];
+        livepatch_expectation_t expect;
     };
 
     /* Our replacement function for xen_extra_version. */
@@ -408,6 +430,12 @@ A simple example of what a payload file can be:
         .old_addr = (void *)0xffff82d08013963c, /* Extracted from xen-syms. */
         .new_size = 13, /* To be be computed by scripts. */
         .old_size = 13, /* -----------""---------------  */
+        /* Added to livepatch payload version 2: */
+        .expect = { /* All fields to be filled manually */
+            .enabled = 1,
+            .len = 5,
+            .data = { 0x48, 0x8d, 0x05, 0x33, 0x1C }
+        },
     } __attribute__((__section__(".livepatch.funcs")));
 
 Code must be compiled with `-fPIC`.
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index d76619844c..cdae324724 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -560,6 +560,58 @@ static int check_patching_sections(const struct livepatch_elf *elf)
     return 0;
 }
 
+static inline int livepatch_verify_expectation_fn(const struct livepatch_func *func)
+{
+    const livepatch_expectation_t *exp = &func->expect;
+
+    /* Ignore disabled expectations. */
+    if ( !exp->enabled )
+        return 0;
+
+    /* There is nothing to expect */
+    if ( !func->old_addr )
+        return -EFAULT;
+
+    if ( exp->len > sizeof(exp->data))
+        return -EOVERFLOW;
+
+    /* Incorrect expectation */
+    if ( func->old_size < exp->len )
+        return -ERANGE;
+
+    if ( memcmp(func->old_addr, exp->data, exp->len) )
+    {
+        printk(XENLOG_ERR LIVEPATCH "%s: expectation failed: expected:%*phN, actual:%*phN\n",
+               func->name, exp->len, exp->data, exp->len, func->old_addr);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static inline int livepatch_check_expectations(const struct payload *payload)
+{
+    int i, rc;
+
+    printk(XENLOG_INFO LIVEPATCH "%s: Verifying enabled expectations for all functions\n",
+           payload->name);
+
+    for ( i = 0; i < payload->nfuncs; i++ )
+    {
+        const struct livepatch_func *func = &(payload->funcs[i]);
+
+        rc = livepatch_verify_expectation_fn(func);
+        if ( rc )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: expectations of %s failed (rc=%d), aborting!\n",
+                   payload->name, func->name ?: "unknown", rc);
+            return rc;
+        }
+    }
+
+    return 0;
+}
+
 /*
  * Lookup specified section and when exists assign its address to a specified hook.
  * Perform section pointer and size validation: single hook sections must contain a
@@ -1345,6 +1397,20 @@ static void livepatch_do_action(void)
 
         if ( rc == 0 )
         {
+            /*
+             * Make sure all expectation requirements are met.
+             * Beware all the payloads are reverted at this point.
+             * If expectations are not met the system is left in a
+             * completely UNPATCHED state!
+             */
+            rc = livepatch_check_expectations(data);
+            if ( rc )
+            {
+                printk(XENLOG_ERR LIVEPATCH "%s: SYSTEM MIGHT BE INSECURE: "
+                       "Replace action has been aborted after reverting ALL payloads!\n", data->name);
+                break;
+            }
+
             if ( is_hook_enabled(data->hooks.apply.action) )
             {
                 printk(XENLOG_INFO LIVEPATCH "%s: Calling apply action hook function\n", data->name);
@@ -1798,6 +1864,11 @@ static int livepatch_action(struct xen_sysctl_livepatch_action *action)
                     break;
             }
 
+            /* Make sure all expectation requirements are met. */
+            rc = livepatch_check_expectations(data);
+            if ( rc )
+                break;
+
             if ( is_hook_enabled(data->hooks.apply.pre) )
             {
                 printk(XENLOG_INFO LIVEPATCH "%s: Calling pre-apply hook function\n", data->name);
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 3bcb892ce1..a454b86ce6 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -826,6 +826,18 @@ struct xen_sysctl_cpu_featureset {
  * We guard this with __XEN__ as toolstacks SHOULD not use it.
  */
 #ifdef __XEN__
+#define LIVEPATCH_OPAQUE_SIZE 31
+
+struct livepatch_expectation {
+    uint8_t enabled : 1;
+    uint8_t len : 5;        /* Length of data up to LIVEPATCH_OPAQUE_SIZE
+                               (5 bits is enough for now) */
+    uint8_t data[LIVEPATCH_OPAQUE_SIZE]; /* Same size as opaque[] buffer of
+                                            struct livepatch_func. This is the
+                                            max number of bytes to be patched */
+};
+typedef struct livepatch_expectation livepatch_expectation_t;
+
 typedef enum livepatch_func_state {
     LIVEPATCH_FUNC_NOT_APPLIED,
     LIVEPATCH_FUNC_APPLIED
@@ -838,9 +850,10 @@ struct livepatch_func {
     uint32_t new_size;
     uint32_t old_size;
     uint8_t version;        /* MUST be LIVEPATCH_PAYLOAD_VERSION. */
-    uint8_t opaque[31];
+    uint8_t opaque[LIVEPATCH_OPAQUE_SIZE];
     uint8_t applied;
     uint8_t _pad[7];
+    livepatch_expectation_t expect;
 };
 typedef struct livepatch_func livepatch_func_t;
 #endif
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 23113d3418..067861903f 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -27,6 +27,8 @@ 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
+LIVEPATCH_EXPECTATIONS:= xen_expectations.livepatch
+LIVEPATCH_EXPECTATIONS_FAIL:= xen_expectations_fail.livepatch
 
 LIVEPATCHES += $(LIVEPATCH)
 LIVEPATCHES += $(LIVEPATCH_BYE)
@@ -40,6 +42,8 @@ LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_MARKER)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOAPPLY)
 LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
+LIVEPATCHES += $(LIVEPATCH_EXPECTATIONS)
+LIVEPATCHES += $(LIVEPATCH_EXPECTATIONS_FAIL)
 
 LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
 
@@ -54,7 +58,7 @@ uninstall:
 
 .PHONY: clean
 clean::
-	rm -f *.o .*.o.d *.livepatch config.h
+	rm -f *.o .*.o.d *.livepatch config.h expect_config.h
 
 #
 # To compute these values we need the binary files: xen-syms
@@ -182,8 +186,27 @@ xen_actions_hooks_norevert.o: config.h
 $(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) $^
 
+CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')
+.PHONY: expect_config.h
+expect_config.h: EXPECT_BYTES=$(call CODE_GET_EXPECT,$(BASEDIR)/xen-syms,xen_extra_version)
+expect_config.h: EXPECT_BYTES_COUNT=6
+expect_config.h: xen_expectations.o
+	(set -e; \
+	 echo "#define EXPECT_BYTES $(EXPECT_BYTES)"; \
+         echo "#define EXPECT_BYTES_COUNT $(EXPECT_BYTES_COUNT)") > $@
+
+xen_expectations.o: expect_config.h
+
+.PHONY: $(LIVEPATCH_EXPECTATIONS)
+$(LIVEPATCH_EXPECTATIONS): xen_expectations.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_EXPECTATIONS) $^
+
+.PHONY: $(LIVEPATCH_EXPECTATIONS_FAIL)
+$(LIVEPATCH_EXPECTATIONS_FAIL): xen_expectations_fail.o xen_hello_world_func.o note.o xen_note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_EXPECTATIONS_FAIL) $^
+
 .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_MARKER) $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) \
-           $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
+           $(LIVEPATCH_ACTION_HOOKS_NOREVERT) $(LIVEPATCH_EXPECTATIONS) $(LIVEPATCH_EXPECTATIONS_FAIL)
diff --git a/xen/test/livepatch/xen_expectations.c b/xen/test/livepatch/xen_expectations.c
new file mode 100644
index 0000000000..c8175a458b
--- /dev/null
+++ b/xen/test/livepatch/xen_expectations.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#include "expect_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 livepatch_exceptions_str[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = livepatch_exceptions_str,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = EXPECT_BYTES_COUNT,
+    .old_size = EXPECT_BYTES_COUNT,
+    .expect = {
+        .enabled = 1,
+        .len = EXPECT_BYTES_COUNT,
+        .data = EXPECT_BYTES
+    },
+
+};
+
+/*
+ * 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_expectations_fail.c b/xen/test/livepatch/xen_expectations_fail.c
new file mode 100644
index 0000000000..36a110286f
--- /dev/null
+++ b/xen/test/livepatch/xen_expectations_fail.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ *
+ */
+
+#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 livepatch_exceptions_str[] = "xen_extra_version";
+extern const char *xen_hello_world(void);
+
+#define EXPECT_BYTES_COUNT 6
+
+struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = livepatch_exceptions_str,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = EXPECT_BYTES_COUNT,
+    .old_size = EXPECT_BYTES_COUNT,
+    .expect = {
+        .enabled = 1,
+        .len = EXPECT_BYTES_COUNT,
+        .data = { 0xDE, 0xAD, 0xC0, 0xDE, 0xBA, 0xBE }
+    },
+
+};
+
+/*
+ * 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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 09/12] livepatch: Add support for modules .modinfo section metadata
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (7 preceding siblings ...)
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations Pawel Wieczorkiewicz
@ 2019-08-27  8:46   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 10/12] livepatch: Handle arbitrary size names with the list operation Pawel Wieczorkiewicz
                     ` (5 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: Pawel Wieczorkiewicz, wipawel, Ross Lagerwall, mpohlack,
	Konrad Rzeszutek Wilk

Having detailed hotpatch metadata helps to properly identify module's
origin and version. It also allows to keep track of the history of
hotpatch loads in the system (at least within dmesg buffer size
limits).

The hotpatch metadata are embedded in a form of .modinfo section.
Each such section contains data of the following format:
key=value\0key=value\0...key=value\0

The .modinfo section may be generated and appended to the resulting
hotpatch ELF file optionally as an extra step of a higher level
hotpatch build system.

The metadata section pointer and the section length is stored in the
hotpatch payload structure and is used to display the content upon
hotpatch apply operation.

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: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
 xen/common/livepatch.c              | 34 ++++++++++++++++++++++++++++++++++
 xen/include/xen/livepatch_payload.h |  6 ++++++
 2 files changed, 40 insertions(+)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index cdae324724..a056fcefcc 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -850,6 +850,23 @@ static int prepare_payload(struct payload *payload,
 #endif
     }
 
+    sec = livepatch_elf_sec_by_name(elf, ".modinfo");
+    if ( sec )
+    {
+        if ( !section_ok(elf, sec, sizeof(*payload->metadata.data)) )
+            return -EINVAL;
+
+        payload->metadata.data = sec->load_addr;
+        payload->metadata.len = sec->sec->sh_size;
+
+        /* The metadata is required to consists of null terminated strings. */
+        if ( payload->metadata.data[payload->metadata.len - 1] != '\0' )
+        {
+            printk(XENLOG_ERR LIVEPATCH "%s: Incorrect metadata format detected\n", payload->name);
+            return -EINVAL;
+        }
+    }
+
     return 0;
 }
 
@@ -1198,6 +1215,19 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
  * for XEN_SYSCTL_LIVEPATCH_ACTION operation (see livepatch_action).
  */
 
+static inline void livepatch_display_metadata(const struct livepatch_metadata *metadata)
+{
+    const char *str;
+
+    if ( metadata && metadata->data && metadata->len > 0 )
+    {
+        printk(XENLOG_INFO LIVEPATCH "module metadata:\n");
+        for ( str = metadata->data; str < (metadata->data + metadata->len); str += (strlen(str) + 1) )
+            printk(XENLOG_INFO LIVEPATCH "  %s\n", str);
+    }
+
+}
+
 static int apply_payload(struct payload *data)
 {
     unsigned int i;
@@ -1230,6 +1260,8 @@ static int apply_payload(struct payload *data)
 
     arch_livepatch_revive();
 
+    livepatch_display_metadata(&data->metadata);
+
     return 0;
 }
 
@@ -2006,6 +2038,8 @@ static void livepatch_printall(unsigned char key)
                data->name, state2str(data->state), data->state, data->text_addr,
                data->rw_addr, data->ro_addr, data->pages);
 
+        livepatch_display_metadata(&data->metadata);
+
         for ( i = 0; i < data->nfuncs; i++ )
         {
             struct livepatch_func *f = &(data->funcs[i]);
diff --git a/xen/include/xen/livepatch_payload.h b/xen/include/xen/livepatch_payload.h
index ff16af0dd6..9f5f064205 100644
--- a/xen/include/xen/livepatch_payload.h
+++ b/xen/include/xen/livepatch_payload.h
@@ -33,6 +33,11 @@ struct livepatch_hooks {
     } apply, revert;
 };
 
+struct livepatch_metadata {
+    const char *data; /* Ptr to .modinfo section with ASCII data. */
+    uint32_t len;     /* Length of the metadata section. */
+};
+
 struct payload {
     uint32_t state;                      /* One of the LIVEPATCH_STATE_*. */
     int32_t rc;                          /* 0 or -XEN_EXX. */
@@ -63,6 +68,7 @@ struct payload {
     unsigned int n_load_funcs;           /* Nr of the funcs to load and execute. */
     unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. */
     char name[XEN_LIVEPATCH_NAME_SIZE];  /* Name of it. */
+    struct livepatch_metadata metadata;  /* Module meta data record */
 };
 
 /*
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 10/12] livepatch: Handle arbitrary size names with the list operation
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (8 preceding siblings ...)
  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   ` Pawel Wieczorkiewicz
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 11/12] livepatch: Add metadata runtime retrieval mechanism Pawel Wieczorkiewicz
                     ` (4 subsequent siblings)
  14 siblings, 0 replies; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

The payloads' name strings can be of arbitrary size (typically small
with an upper bound of XEN_LIVEPATCH_NAME_SIZE).
Current implementation of the list operation interface allows to copy
names in the XEN_LIVEPATCH_NAME_SIZE chunks regardless of its actual
size and enforces space allocation requirements on userland tools.

To unify and simplify the interface, handle the name strings of
arbitrary size by copying them in adhering chunks to the userland.
In order to let the userland allocate enough space for the incoming
data add an auxiliary interface xc_livepatch_list_get_sizes() that
provides the current number of payload entries and the total size of
all name strings. This is achieved by extending the sysctl list
interface with an extra fields: name_total_size.

The xc_livepatch_list_get_sizes() issues the livepatch sysctl list
operation with the nr field set to 0. In this mode the operation
returns the number of payload entries and calculates the total sizes
for all payloads' names.
When the sysctl operation is issued with a non-zero nr field (for
instance with a value obtained earlier with the prior call to the
xc_livepatch_list_get_sizes()) the new field name_total_size provides
the total size of actually copied data.

Extend the libxc to handle the name back-to-back data transfers.

The xen-livepatch tool is modified to start the list operation with a
call to the xc_livepatch_list_get_sizes() to obtain the actual number
of payloads as well as the necessary space for names.
The tool now always requests the actual number of entries and leaves
the preemption handling to the libxc routine. The libxc still returns
'done' and 'left' parameters with the same semantic allowing the tool
to detect anomalies and react to them. At the moment it is expected
that the tool receives the exact number of entires as requested.
The xen-livepatch tool has been also modified to handle the name
back-to-back transfers correctly.

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:
  * added corresponding documentation

 docs/misc/livepatch.pandoc    |  24 +++++----
 tools/libxc/include/xenctrl.h |  49 ++++++++++++------
 tools/libxc/xc_misc.c         | 100 ++++++++++++++++++++++++++++---------
 tools/misc/xen-livepatch.c    | 112 ++++++++++++++++++++++--------------------
 xen/common/livepatch.c        |  31 +++++++++---
 xen/include/public/sysctl.h   |  15 +++---
 6 files changed, 219 insertions(+), 112 deletions(-)

diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index 92a424e918..a626c4f916 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -714,17 +714,20 @@ The caller provides:
  * `idx` Index iterator. The index into the hypervisor's payload count. It is
     recommended that on first invocation zero be used so that `nr` (which the
     hypervisor will update with the remaining payload count) be provided.
-    Also the hypervisor will provide `version` with the most current value.
+    Also the hypervisor will provide `version` with the most current value and
+    calculated total size for all payloads' names.
  * `nr` The max number of entries to populate. Can be zero which will result
     in the hypercall being a probing one and return the number of payloads
     (and update the `version`).
  * `pad` - *MUST* be zero.
  * `status` Virtual address of where to write `struct xen_livepatch_status`
    structures. Caller *MUST* allocate up to `nr` of them.
- * `name` - Virtual address of where to write the unique name of the payload.
-   Caller *MUST* allocate up to `nr` of them. Each *MUST* be of
-   **XEN_LIVEPATCH_NAME_SIZE** size. Note that **XEN_LIVEPATCH_NAME_SIZE** includes
-   the NUL terminator.
+ * `name` - Virtual address of where to write the unique name of the payloads.
+   Caller *MUST* allocate enough space to be able to store all received data
+   (i.e. total allocated space *MUST* match the `name_total_size` value
+   provided by the hypervisor). Individual payload name cannot be longer than
+   **XEN_LIVEPATCH_NAME_SIZE** bytes. Note that **XEN_LIVEPATCH_NAME_SIZE**
+   includes the NUL terminator.
  * `len` - Virtual address of where to write the length of each unique name
    of the payload. Caller *MUST* allocate up to `nr` of them. Each *MUST* be
    of sizeof(uint32_t) (4 bytes).
@@ -733,7 +736,8 @@ If the hypercall returns an positive number, it is the number (upto `nr`
 provided to the hypercall) of the payloads returned, along with `nr` updated
 with the number of remaining payloads, `version` updated (it may be the same
 across hypercalls - if it varies the data is stale and further calls could
-fail). The `status`, `name`, and `len` are updated at their designed index
+fail) and the `name_total_size` containing total size of transfered data for
+the array. The `status`, `name`, and `len` are updated at their designed index
 value (`idx`) with the returned value of data.
 
 If the hypercall returns -XEN_E2BIG the `nr` is too big and should be
@@ -772,11 +776,13 @@ The structure is as follow:
                                                    amount of payloads and version.
                                                    OUT: How many payloads left. */
         uint32_t pad;                           /* IN: Must be zero. */
+        uint64_t name_total_size;               /* OUT: Total size of all transfer names */
         XEN_GUEST_HANDLE_64(xen_livepatch_status_t) status;  /* OUT. Must have enough
                                                    space allocate for nr of them. */
-        XEN_GUEST_HANDLE_64(char) id;           /* OUT: Array of names. Each member
-                                                   MUST XEN_LIVEPATCH_NAME_SIZE in size.
-                                                   Must have nr of them. */
+        XEN_GUEST_HANDLE_64(char) name;         /* OUT: Array of names. Each member
+                                                   may have an arbitrary length up to
+                                                   XEN_LIVEPATCH_NAME_SIZE bytes. Must have
+                                                   nr of them. */
         XEN_GUEST_HANDLE_64(uint32) len;        /* OUT: Array of lengths of name's.
                                                    Must have nr of them. */
     };
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 725697c132..e0ebb586b6 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2560,7 +2560,25 @@ int xc_livepatch_get(xc_interface *xch,
                      xen_livepatch_status_t *status);
 
 /*
- * The heart of this function is to get an array of xen_livepatch_status_t.
+ * Get a number of available payloads and get actual total size of
+ * the payloads' name array.
+ *
+ * This functions is typically executed first before the xc_livepatch_list()
+ * to obtain the sizes and correctly allocate all necessary data resources.
+ *
+ * The return value is zero if the hypercall completed successfully.
+ *
+ * If there was an error performing the sysctl operation, the return value
+ * will contain the hypercall error code value.
+ */
+int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
+                                uint64_t *name_total_size);
+
+/*
+ * The heart of this function is to get an array of the following objects:
+ *   - xen_livepatch_status_t: states and return codes of payloads
+ *   - name: names of payloads
+ *   - len: lengths of corresponding payloads' names
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -2571,21 +2589,20 @@ int xc_livepatch_get(xc_interface *xch,
  * 'left' are also updated with the number of entries filled out
  * and respectively the number of entries left to get from hypervisor.
  *
- * It is expected that the caller of this function will take the
- * 'left' and use the value for 'start'. This way we have an
- * cursor in the array. Note that the 'info','name', and 'len' will
- * be updated at the subsequent calls.
+ * It is expected that the caller of this function will first issue the
+ * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
+ * as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size'
+ * parameter.
  *
- * The 'max' is to be provided by the caller with the maximum
- * number of entries that 'info', 'name', and 'len' arrays can
- * be filled up with.
- *
- * Each entry in the 'name' array is expected to be of XEN_LIVEPATCH_NAME_SIZE
- * length.
+ * The 'max' is to be provided by the caller with the maximum number of
+ * entries that 'info', 'name', 'len' arrays can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
  *
+ * Each entry in the 'name' array may have an arbitrary size.
+ *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
  * The return value is zero if the hypercall completed successfully.
@@ -2597,10 +2614,12 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the number of entries that had been succesfully
  * retrieved (if any).
  */
-int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
-                      xen_livepatch_status_t *info, char *name,
-                      uint32_t *len, unsigned int *done,
-                      unsigned int *left);
+int xc_livepatch_list(xc_interface *xch, const unsigned int max,
+                      const unsigned int start,
+                      struct xen_livepatch_status *info,
+                      char *name, uint32_t *len,
+                      const uint64_t name_total_size,
+                      unsigned int *done, unsigned int *left);
 
 /*
  * The operations are asynchronous and the hypervisor may take a while
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index a8e9e7d1e2..d787f3f29f 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -662,7 +662,48 @@ int xc_livepatch_get(xc_interface *xch,
 }
 
 /*
- * The heart of this function is to get an array of xen_livepatch_status_t.
+ * Get a number of available payloads and get actual total size of
+ * the payloads' name array.
+ *
+ * This functions is typically executed first before the xc_livepatch_list()
+ * to obtain the sizes and correctly allocate all necessary data resources.
+ *
+ * The return value is zero if the hypercall completed successfully.
+ *
+ * If there was an error performing the sysctl operation, the return value
+ * will contain the hypercall error code value.
+ */
+int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
+                                uint64_t *name_total_size)
+{
+    DECLARE_SYSCTL;
+    int rc;
+
+    if ( !nr || !name_total_size )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    memset(&sysctl, 0, sizeof(sysctl));
+    sysctl.cmd = XEN_SYSCTL_livepatch_op;
+    sysctl.u.livepatch.cmd = XEN_SYSCTL_LIVEPATCH_LIST;
+
+    rc = do_sysctl(xch, &sysctl);
+    if ( rc )
+        return rc;
+
+    *nr = sysctl.u.livepatch.u.list.nr;
+    *name_total_size = sysctl.u.livepatch.u.list.name_total_size;
+
+    return 0;
+}
+
+/*
+ * The heart of this function is to get an array of the following objects:
+ *   - xen_livepatch_status_t: states and return codes of payloads
+ *   - name: names of payloads
+ *   - len: lengths of corresponding payloads' names
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -673,21 +714,20 @@ int xc_livepatch_get(xc_interface *xch,
  * 'left' are also updated with the number of entries filled out
  * and respectively the number of entries left to get from hypervisor.
  *
- * It is expected that the caller of this function will take the
- * 'left' and use the value for 'start'. This way we have an
- * cursor in the array. Note that the 'info','name', and 'len' will
- * be updated at the subsequent calls.
+ * It is expected that the caller of this function will first issue the
+ * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
+ * as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size'
+ * parameter.
  *
- * The 'max' is to be provided by the caller with the maximum
- * number of entries that 'info', 'name', and 'len' arrays can
- * be filled up with.
- *
- * Each entry in the 'name' array is expected to be of XEN_LIVEPATCH_NAME_SIZE
- * length.
+ * The 'max' is to be provided by the caller with the maximum number of
+ * entries that 'info', 'name', 'len' arrays can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
  *
+ * Each entry in the 'name' array may have an arbitrary size.
+ *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
  * The return value is zero if the hypercall completed successfully.
@@ -699,11 +739,12 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the number of entries that had been succesfully
  * retrieved (if any).
  */
-int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
+int xc_livepatch_list(xc_interface *xch, const unsigned int max,
+                      const unsigned int start,
                       struct xen_livepatch_status *info,
                       char *name, uint32_t *len,
-                      unsigned int *done,
-                      unsigned int *left)
+                      const uint64_t name_total_size,
+                      unsigned int *done, unsigned int *left)
 {
     int rc;
     DECLARE_SYSCTL;
@@ -714,27 +755,33 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
     uint32_t max_batch_sz, nr;
     uint32_t version = 0, retries = 0;
     uint32_t adjust = 0;
-    ssize_t sz;
+    off_t name_off = 0;
+    uint64_t name_sz;
 
-    if ( !max || !info || !name || !len )
+    if ( !max || !info || !name || !len || !done || !left )
     {
         errno = EINVAL;
         return -1;
     }
 
+    if ( name_total_size == 0 )
+    {
+        errno = ENOENT;
+        return -1;
+    }
+
+    memset(&sysctl, 0, sizeof(sysctl));
     sysctl.cmd = XEN_SYSCTL_livepatch_op;
     sysctl.u.livepatch.cmd = XEN_SYSCTL_LIVEPATCH_LIST;
-    sysctl.u.livepatch.pad = 0;
-    sysctl.u.livepatch.u.list.version = 0;
     sysctl.u.livepatch.u.list.idx = start;
-    sysctl.u.livepatch.u.list.pad = 0;
 
     max_batch_sz = max;
-    /* Convience value. */
-    sz = sizeof(*name) * XEN_LIVEPATCH_NAME_SIZE;
+    name_sz = name_total_size;
     *done = 0;
     *left = 0;
     do {
+        uint64_t _name_sz;
+
         /*
          * The first time we go in this loop our 'max' may be bigger
          * than what the hypervisor is comfortable with - hence the first
@@ -754,11 +801,11 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
         sysctl.u.livepatch.u.list.nr = nr;
         /* Fix the size (may vary between hypercalls). */
         HYPERCALL_BOUNCE_SET_SIZE(info, nr * sizeof(*info));
-        HYPERCALL_BOUNCE_SET_SIZE(name, nr * nr);
+        HYPERCALL_BOUNCE_SET_SIZE(name, name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, nr * sizeof(*len));
         /* Move the pointer to proper offset into 'info'. */
         (HYPERCALL_BUFFER(info))->ubuf = info + *done;
-        (HYPERCALL_BUFFER(name))->ubuf = name + (sz * *done);
+        (HYPERCALL_BUFFER(name))->ubuf = name + name_off;
         (HYPERCALL_BUFFER(len))->ubuf = len + *done;
         /* Allocate memory. */
         rc = xc_hypercall_bounce_pre(xch, info);
@@ -827,14 +874,19 @@ int xc_livepatch_list(xc_interface *xch, unsigned int max, unsigned int start,
             break;
         }
         *left = sysctl.u.livepatch.u.list.nr; /* Total remaining count. */
+        _name_sz = sysctl.u.livepatch.u.list.name_total_size; /* Total received name size. */
         /* Copy only up 'rc' of data' - we could add 'min(rc,nr) if desired. */
         HYPERCALL_BOUNCE_SET_SIZE(info, (rc * sizeof(*info)));
-        HYPERCALL_BOUNCE_SET_SIZE(name, (rc * sz));
+        HYPERCALL_BOUNCE_SET_SIZE(name, _name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, (rc * sizeof(*len)));
         /* Bounce the data and free the bounce buffer. */
         xc_hypercall_bounce_post(xch, info);
         xc_hypercall_bounce_post(xch, name);
         xc_hypercall_bounce_post(xch, len);
+
+        name_sz -= _name_sz;
+        name_off += _name_sz;
+
         /* And update how many elements of info we have copied into. */
         *done += rc;
         /* Update idx. */
diff --git a/tools/misc/xen-livepatch.c b/tools/misc/xen-livepatch.c
index a37b2457ff..8ac3d567fc 100644
--- a/tools/misc/xen-livepatch.c
+++ b/tools/misc/xen-livepatch.c
@@ -64,14 +64,14 @@ static const char *state2str(unsigned int state)
     return names[state];
 }
 
-/* This value was choosen adhoc. It could be 42 too. */
-#define MAX_LEN 11
 static int list_func(int argc, char *argv[])
 {
-    unsigned int idx, done, left, i;
+    unsigned int nr, done, left, i;
     xen_livepatch_status_t *info = NULL;
     char *name = NULL;
     uint32_t *len = NULL;
+    uint64_t name_total_size;
+    off_t name_off;
     int rc = ENOMEM;
 
     if ( argc )
@@ -79,65 +79,73 @@ static int list_func(int argc, char *argv[])
         show_help();
         return -1;
     }
-    idx = left = 0;
-    info = malloc(sizeof(*info) * MAX_LEN);
-    if ( !info )
-        return rc;
-    name = malloc(sizeof(*name) * XEN_LIVEPATCH_NAME_SIZE * MAX_LEN);
-    if ( !name )
+    done = left = 0;
+
+    rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size);
+    if ( rc )
     {
-        free(info);
+        rc = errno;
+        fprintf(stderr, "Failed to get list sizes.\n"
+                "Error %d: %s\n",
+                rc, strerror(rc));
         return rc;
     }
-    len = malloc(sizeof(*len) * MAX_LEN);
-    if ( !len ) {
-        free(name);
-        free(info);
+
+    if ( nr == 0 )
+    {
+        fprintf(stdout, "Nothing to list\n");
+        return 0;
+    }
+
+    info = malloc(nr * sizeof(*info));
+    if ( !info )
         return rc;
+
+    name = malloc(name_total_size * sizeof(*name));
+    if ( !name )
+        goto error_name;
+
+    len = malloc(nr * sizeof(*len));
+    if ( !len )
+        goto error_len;
+
+    memset(info, 'A', nr * sizeof(*info));
+    memset(name, 'B', name_total_size * sizeof(*name));
+    memset(len, 'C', nr * sizeof(*len));
+    name_off = 0;
+
+    rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size, &done, &left);
+    if ( rc || done != nr || left > 0)
+    {
+        rc = errno;
+        fprintf(stderr, "Failed to list %d/%d.\n"
+                "Error %d: %s\n",
+                left, nr, rc, strerror(rc));
+        goto error;
     }
 
-    do {
-        done = 0;
-        /* The memset is done to catch errors. */
-        memset(info, 'A', sizeof(*info) * MAX_LEN);
-        memset(name, 'B', sizeof(*name) * MAX_LEN * XEN_LIVEPATCH_NAME_SIZE);
-        memset(len, 'C', sizeof(*len) * MAX_LEN);
-        rc = xc_livepatch_list(xch, MAX_LEN, idx, info, name, len, &done, &left);
-        if ( rc )
-        {
-            rc = errno;
-            fprintf(stderr, "Failed to list %d/%d.\n"
-                            "Error %d: %s\n",
-                    idx, left, rc, strerror(rc));
-            break;
-        }
-        if ( !idx )
-            fprintf(stdout," ID                                     | status\n"
-                           "----------------------------------------+------------\n");
+    fprintf(stdout," ID                                     | status\n"
+                   "----------------------------------------+------------\n");
 
-        for ( i = 0; i < done; i++ )
-        {
-            unsigned int j;
-            uint32_t sz;
-            char *str;
-
-            sz = len[i];
-            str = name + (i * XEN_LIVEPATCH_NAME_SIZE);
-            for ( j = sz; j < XEN_LIVEPATCH_NAME_SIZE; j++ )
-                str[j] = '\0';
-
-            printf("%-40s| %s", str, state2str(info[i].state));
-            if ( info[i].rc )
-                printf(" (%d, %s)\n", -info[i].rc, strerror(-info[i].rc));
-            else
-                puts("");
-        }
-        idx += done;
-    } while ( left );
+    for ( i = 0; i < done; i++ )
+    {
+        char *name_str = name + name_off;
+
+        printf("%-40.*s| %s", len[i], name_str, state2str(info[i].state));
+        if ( info[i].rc )
+            printf(" (%d, %s)\n", -info[i].rc, strerror(-info[i].rc));
+        else
+            puts("");
+
+        name_off += len[i];
+    }
 
+error:
+    free(len);
+error_len:
     free(name);
+error_name:
     free(info);
-    free(len);
     return rc;
 }
 #undef MAX_LEN
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index a056fcefcc..8a9e92660e 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1161,7 +1161,6 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
 
     if ( list->nr &&
          (!guest_handle_okay(list->status, list->nr) ||
-          !guest_handle_okay(list->name, XEN_LIVEPATCH_NAME_SIZE * list->nr) ||
           !guest_handle_okay(list->len, list->nr)) )
         return -EINVAL;
 
@@ -1172,23 +1171,35 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
         return -EINVAL;
     }
 
+    list->name_total_size = 0;
     if ( list->nr )
     {
+        uint64_t name_offset = 0;
+
         list_for_each_entry( data, &payload_list, list )
         {
-            uint32_t len;
+            uint32_t name_len;
 
             if ( list->idx > i++ )
                 continue;
 
             status.state = data->state;
             status.rc = data->rc;
-            len = strlen(data->name) + 1;
+
+            name_len = strlen(data->name) + 1;
+            list->name_total_size += name_len;
+
+            if ( !guest_handle_subrange_okay(list->name, name_offset,
+                                             name_offset + name_len - 1) )
+            {
+                rc = -EINVAL;
+                break;
+            }
 
             /* N.B. 'idx' != 'i'. */
-            if ( __copy_to_guest_offset(list->name, idx * XEN_LIVEPATCH_NAME_SIZE,
-                                        data->name, len) ||
-                __copy_to_guest_offset(list->len, idx, &len, 1) ||
+            if ( __copy_to_guest_offset(list->name, name_offset,
+                                        data->name, name_len) ||
+                __copy_to_guest_offset(list->len, idx, &name_len, 1) ||
                 __copy_to_guest_offset(list->status, idx, &status, 1) )
             {
                 rc = -EFAULT;
@@ -1196,11 +1207,19 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
             }
 
             idx++;
+            name_offset += name_len;
 
             if ( (idx >= list->nr) || hypercall_preempt_check() )
                 break;
         }
     }
+    else
+    {
+        list_for_each_entry( data, &payload_list, list )
+        {
+            list->name_total_size += strlen(data->name) + 1;
+        }
+    }
     list->nr = payload_cnt - i; /* Remaining amount. */
     list->version = payload_version;
     spin_unlock(&payload_lock);
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index a454b86ce6..d95c62f06b 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -924,10 +924,11 @@ struct xen_sysctl_livepatch_get {
  *
  * If the hypercall returns an positive number, it is the number (up to `nr`)
  * of the payloads returned, along with `nr` updated with the number of remaining
- * payloads, `version` updated (it may be the same across hypercalls. If it
- * varies the data is stale and further calls could fail). The `status`,
- * `name`, and `len`' are updated at their designed index value (`idx`) with
- * the returned value of data.
+ * payloads, `version` updated (it may be the same across hypercalls. If it varies
+ * the data is stale and further calls could fail) and the name_total_size
+ * containing total size of transfered data for the array.
+ * The `status`, `name`, `len` are updated at their designed index value (`idx`)
+ * with the returned value of data.
  *
  * If the hypercall returns E2BIG the `nr` is too big and should be
  * lowered. The upper limit of `nr` is left to the implemention.
@@ -950,11 +951,13 @@ struct xen_sysctl_livepatch_list {
                                                amount of payloads and version.
                                                OUT: How many payloads left. */
     uint32_t pad;                           /* IN: Must be zero. */
+    uint64_t name_total_size;               /* OUT: Total size of all transfer names */
     XEN_GUEST_HANDLE_64(xen_livepatch_status_t) status;  /* OUT. Must have enough
                                                space allocate for nr of them. */
     XEN_GUEST_HANDLE_64(char) name;         /* OUT: Array of names. Each member
-                                               MUST XEN_LIVEPATCH_NAME_SIZE in size.
-                                               Must have nr of them. */
+                                               may have an arbitrary length up to
+                                               XEN_LIVEPATCH_NAME_SIZE bytes. Must have
+                                               nr of them. */
     XEN_GUEST_HANDLE_64(uint32) len;        /* OUT: Array of lengths of name's.
                                                Must have nr of them. */
 };
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 11/12] livepatch: Add metadata runtime retrieval mechanism
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (9 preceding siblings ...)
  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   ` 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
                     ` (3 subsequent siblings)
  14 siblings, 1 reply; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	mpohlack, Tim Deegan, Pawel Wieczorkiewicz, Julien Grall,
	Jan Beulich

Extend the livepatch list operation to fetch also payloads' metadata.
This is achieved by extending the sysctl list interface with 2 extra
guest handles:
* metadata     - an array of arbitrary size strings
* metadata_len - an array of metadata strings' lengths (uin32_t each)

Payloads' metadata is a string of arbitrary size and does not have an
upper bound limit. It may also vary in size between payloads.

In order to let the userland allocate enough space for the incoming
data add a metadata total size field to the list sysctl operation and
fill it with total size of all payloads' metadata.

Extend the libxc to handle the metadata back-to-back data transfers
as well as metadata length array data transfers.

The xen-livepatch userland tool is extended to always display the
metadata for each received module. The metadata is received with the
following format: key=value\0key=value\0...key=value\0. The format is
modified to the following one: key=value;key=value;...key=value.
The new format allows to easily parse the metadata for a given module
by a machine.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
Changed since v1:
  * added corresponding documentation
  * make metadata optional (do not display it when given payload
    does not have it)

 docs/misc/livepatch.pandoc    | 31 ++++++++++++++++-----
 tools/libxc/include/xenctrl.h | 22 +++++++++++----
 tools/libxc/xc_misc.c         | 64 +++++++++++++++++++++++++++++++++++--------
 tools/misc/xen-livepatch.c    | 43 +++++++++++++++++++++++------
 xen/common/livepatch.c        | 22 +++++++++++----
 xen/include/public/sysctl.h   | 19 +++++++++----
 6 files changed, 157 insertions(+), 44 deletions(-)

diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
index a626c4f916..f8009033b7 100644
--- a/docs/misc/livepatch.pandoc
+++ b/docs/misc/livepatch.pandoc
@@ -704,8 +704,8 @@ The structure is as follow:
 
 ### XEN_SYSCTL_LIVEPATCH_LIST (2)
 
-Retrieve an array of abbreviated status and names of payloads that are loaded in the
-hypervisor.
+Retrieve an array of abbreviated status, names and metadata of payloads that are
+loaded in the hypervisor.
 
 The caller provides:
 
@@ -714,8 +714,9 @@ The caller provides:
  * `idx` Index iterator. The index into the hypervisor's payload count. It is
     recommended that on first invocation zero be used so that `nr` (which the
     hypervisor will update with the remaining payload count) be provided.
-    Also the hypervisor will provide `version` with the most current value and
-    calculated total size for all payloads' names.
+    Also the hypervisor will provide `version` with the most current value,
+    calculated total size of all payloads' names and calculated total size of
+    all payload's metadata.
  * `nr` The max number of entries to populate. Can be zero which will result
     in the hypercall being a probing one and return the number of payloads
     (and update the `version`).
@@ -731,14 +732,23 @@ The caller provides:
  * `len` - Virtual address of where to write the length of each unique name
    of the payload. Caller *MUST* allocate up to `nr` of them. Each *MUST* be
    of sizeof(uint32_t) (4 bytes).
+ * `metadata` - Virtual address of where to write the metadata of the payloads.
+   Caller *MUST* allocate enough space to be able to store all received data
+   (i.e. total allocated space *MUST* match the `metadata_total_size` value
+   provided by the hypervisor). Individual payload metadata string can be of
+   arbitrary length. The metadata string format is: key=value\0...key=value\0.
+ * `metadata_len` - Virtual address of where to write the length of each metadata
+   string of the payload. Caller *MUST* allocate up to `nr` of them. Each *MUST*
+   be of sizeof(uint32_t) (4 bytes).
 
 If the hypercall returns an positive number, it is the number (upto `nr`
 provided to the hypercall) of the payloads returned, along with `nr` updated
 with the number of remaining payloads, `version` updated (it may be the same
 across hypercalls - if it varies the data is stale and further calls could
-fail) and the `name_total_size` containing total size of transfered data for
-the array. The `status`, `name`, and `len` are updated at their designed index
-value (`idx`) with the returned value of data.
+fail), `name_total_size` and `metadata_total_size` containing total sizes of
+transfered data for both the arrays.
+The `status`, `name`, `len`, `metadata` and `metadata_len` are updated at their
+designed index value (`idx`) with the returned value of data.
 
 If the hypercall returns -XEN_E2BIG the `nr` is too big and should be
 lowered.
@@ -777,6 +787,7 @@ The structure is as follow:
                                                    OUT: How many payloads left. */
         uint32_t pad;                           /* IN: Must be zero. */
         uint64_t name_total_size;               /* OUT: Total size of all transfer names */
+        uint64_t metadata_total_size;           /* OUT: Total size of all transfer metadata */
         XEN_GUEST_HANDLE_64(xen_livepatch_status_t) status;  /* OUT. Must have enough
                                                    space allocate for nr of them. */
         XEN_GUEST_HANDLE_64(char) name;         /* OUT: Array of names. Each member
@@ -785,6 +796,12 @@ The structure is as follow:
                                                    nr of them. */
         XEN_GUEST_HANDLE_64(uint32) len;        /* OUT: Array of lengths of name's.
                                                    Must have nr of them. */
+        XEN_GUEST_HANDLE_64(char) metadata;     /* OUT: Array of metadata strings. Each
+                                                   member may have an arbitrary length.
+                                                   Must have nr of them. */
+        XEN_GUEST_HANDLE_64(uint32) metadata_len;  /* OUT: Array of lengths of metadata's.
+                                                      Must have nr of them. */
+
     };
 
 ### XEN_SYSCTL_LIVEPATCH_ACTION (3)
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index e0ebb586b6..7a3762f44e 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2561,7 +2561,7 @@ int xc_livepatch_get(xc_interface *xch,
 
 /*
  * Get a number of available payloads and get actual total size of
- * the payloads' name array.
+ * the payloads' name and metadata arrays.
  *
  * This functions is typically executed first before the xc_livepatch_list()
  * to obtain the sizes and correctly allocate all necessary data resources.
@@ -2572,13 +2572,16 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the hypercall error code value.
  */
 int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
-                                uint64_t *name_total_size);
+                                uint64_t *name_total_size,
+                                uint64_t *metadata_total_size);
 
 /*
  * The heart of this function is to get an array of the following objects:
  *   - xen_livepatch_status_t: states and return codes of payloads
  *   - name: names of payloads
  *   - len: lengths of corresponding payloads' names
+ *   - metadata: payloads' metadata
+ *   - metadata_len: lengths of corresponding payloads' metadata
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -2591,12 +2594,13 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * It is expected that the caller of this function will first issue the
  * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
- * as well as the current number of payload entries.
- * The total sizes are required and supplied via the 'name_total_size'
- * parameter.
+ * and all metadata as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size' and
+ * 'metadata_total_size' parameters.
  *
  * The 'max' is to be provided by the caller with the maximum number of
- * entries that 'info', 'name', 'len' arrays can be filled up with.
+ * entries that 'info', 'name', 'len', 'metadata' and 'metadata_len' arrays
+ * can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
@@ -2605,6 +2609,10 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
+ * Each entry in the 'metadata' array may have an arbitrary size.
+ *
+ * Each entry in the 'metadata_len' array is expected to be of uint32_t size.
+ *
  * The return value is zero if the hypercall completed successfully.
  * Note that the return value is _not_ the amount of entries filled
  * out - that is saved in 'done'.
@@ -2619,6 +2627,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
                       struct xen_livepatch_status *info,
                       char *name, uint32_t *len,
                       const uint64_t name_total_size,
+                      char *metadata, uint32_t *metadata_len,
+                      const uint64_t metadata_total_size,
                       unsigned int *done, unsigned int *left);
 
 /*
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index d787f3f29f..7dc9fd83ed 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -663,7 +663,7 @@ int xc_livepatch_get(xc_interface *xch,
 
 /*
  * Get a number of available payloads and get actual total size of
- * the payloads' name array.
+ * the payloads' name and metadata arrays.
  *
  * This functions is typically executed first before the xc_livepatch_list()
  * to obtain the sizes and correctly allocate all necessary data resources.
@@ -674,12 +674,13 @@ int xc_livepatch_get(xc_interface *xch,
  * will contain the hypercall error code value.
  */
 int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
-                                uint64_t *name_total_size)
+                                uint64_t *name_total_size,
+                                uint64_t *metadata_total_size)
 {
     DECLARE_SYSCTL;
     int rc;
 
-    if ( !nr || !name_total_size )
+    if ( !nr || !name_total_size || !metadata_total_size )
     {
         errno = EINVAL;
         return -1;
@@ -695,6 +696,7 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
 
     *nr = sysctl.u.livepatch.u.list.nr;
     *name_total_size = sysctl.u.livepatch.u.list.name_total_size;
+    *metadata_total_size = sysctl.u.livepatch.u.list.metadata_total_size;
 
     return 0;
 }
@@ -704,6 +706,8 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *   - xen_livepatch_status_t: states and return codes of payloads
  *   - name: names of payloads
  *   - len: lengths of corresponding payloads' names
+ *   - metadata: payloads' metadata
+ *   - metadata_len: lengths of corresponding payloads' metadata
  *
  * However it is complex because it has to deal with the hypervisor
  * returning some of the requested data or data being stale
@@ -716,12 +720,13 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * It is expected that the caller of this function will first issue the
  * xc_livepatch_list_get_sizes() in order to obtain total sizes of names
- * as well as the current number of payload entries.
- * The total sizes are required and supplied via the 'name_total_size'
- * parameter.
+ * and all metadata as well as the current number of payload entries.
+ * The total sizes are required and supplied via the 'name_total_size' and
+ * 'metadata_total_size' parameters.
  *
  * The 'max' is to be provided by the caller with the maximum number of
- * entries that 'info', 'name', 'len' arrays can be filled up with.
+ * entries that 'info', 'name', 'len', 'metadata' and 'metadata_len' arrays
+ * can be filled up with.
  *
  * Each entry in the 'info' array is expected to be of xen_livepatch_status_t
  * structure size.
@@ -730,6 +735,10 @@ int xc_livepatch_list_get_sizes(xc_interface *xch, unsigned int *nr,
  *
  * Each entry in the 'len' array is expected to be of uint32_t size.
  *
+ * Each entry in the 'metadata' array may have an arbitrary size.
+ *
+ * Each entry in the 'metadata_len' array is expected to be of uint32_t size.
+ *
  * The return value is zero if the hypercall completed successfully.
  * Note that the return value is _not_ the amount of entries filled
  * out - that is saved in 'done'.
@@ -744,6 +753,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
                       struct xen_livepatch_status *info,
                       char *name, uint32_t *len,
                       const uint64_t name_total_size,
+                      char *metadata, uint32_t *metadata_len,
+                      const uint64_t metadata_total_size,
                       unsigned int *done, unsigned int *left)
 {
     int rc;
@@ -752,13 +763,16 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
     DECLARE_HYPERCALL_BOUNCE(info, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     DECLARE_HYPERCALL_BOUNCE(name, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     DECLARE_HYPERCALL_BOUNCE(len, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_HYPERCALL_BOUNCE(metadata, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_HYPERCALL_BOUNCE(metadata_len, 0, XC_HYPERCALL_BUFFER_BOUNCE_OUT);
     uint32_t max_batch_sz, nr;
     uint32_t version = 0, retries = 0;
     uint32_t adjust = 0;
-    off_t name_off = 0;
-    uint64_t name_sz;
+    off_t name_off = 0, metadata_off = 0;
+    uint64_t name_sz, metadata_sz;
 
-    if ( !max || !info || !name || !len || !done || !left )
+    if ( !max || !info || !name || !len ||
+         !metadata || !metadata_len || !done || !left )
     {
         errno = EINVAL;
         return -1;
@@ -777,10 +791,11 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
 
     max_batch_sz = max;
     name_sz = name_total_size;
+    metadata_sz = metadata_total_size;
     *done = 0;
     *left = 0;
     do {
-        uint64_t _name_sz;
+        uint64_t _name_sz, _metadata_sz;
 
         /*
          * The first time we go in this loop our 'max' may be bigger
@@ -803,10 +818,14 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         HYPERCALL_BOUNCE_SET_SIZE(info, nr * sizeof(*info));
         HYPERCALL_BOUNCE_SET_SIZE(name, name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, nr * sizeof(*len));
+        HYPERCALL_BOUNCE_SET_SIZE(metadata, metadata_sz);
+        HYPERCALL_BOUNCE_SET_SIZE(metadata_len, nr * sizeof(*metadata_len));
         /* Move the pointer to proper offset into 'info'. */
         (HYPERCALL_BUFFER(info))->ubuf = info + *done;
         (HYPERCALL_BUFFER(name))->ubuf = name + name_off;
         (HYPERCALL_BUFFER(len))->ubuf = len + *done;
+        (HYPERCALL_BUFFER(metadata))->ubuf = metadata + metadata_off;
+        (HYPERCALL_BUFFER(metadata_len))->ubuf = metadata_len + *done;
         /* Allocate memory. */
         rc = xc_hypercall_bounce_pre(xch, info);
         if ( rc )
@@ -820,9 +839,19 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         if ( rc )
             break;
 
+        rc = xc_hypercall_bounce_pre(xch, metadata);
+        if ( rc )
+            break;
+
+        rc = xc_hypercall_bounce_pre(xch, metadata_len);
+        if ( rc )
+            break;
+
         set_xen_guest_handle(sysctl.u.livepatch.u.list.status, info);
         set_xen_guest_handle(sysctl.u.livepatch.u.list.name, name);
         set_xen_guest_handle(sysctl.u.livepatch.u.list.len, len);
+        set_xen_guest_handle(sysctl.u.livepatch.u.list.metadata, metadata);
+        set_xen_guest_handle(sysctl.u.livepatch.u.list.metadata_len, metadata_len);
 
         rc = do_sysctl(xch, &sysctl);
         /*
@@ -839,6 +868,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
             xc_hypercall_bounce_post(xch, info);
             xc_hypercall_bounce_post(xch, name);
             xc_hypercall_bounce_post(xch, len);
+            xc_hypercall_bounce_post(xch, metadata);
+            xc_hypercall_bounce_post(xch, metadata_len);
             continue;
         }
         else if ( rc < 0 ) /* For all other errors we bail out. */
@@ -863,6 +894,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
             xc_hypercall_bounce_post(xch, info);
             xc_hypercall_bounce_post(xch, name);
             xc_hypercall_bounce_post(xch, len);
+            xc_hypercall_bounce_post(xch, metadata);
+            xc_hypercall_bounce_post(xch, metadata_len);
             continue;
         }
 
@@ -875,17 +908,24 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         }
         *left = sysctl.u.livepatch.u.list.nr; /* Total remaining count. */
         _name_sz = sysctl.u.livepatch.u.list.name_total_size; /* Total received name size. */
+        _metadata_sz = sysctl.u.livepatch.u.list.metadata_total_size; /* Total received metadata size. */
         /* Copy only up 'rc' of data' - we could add 'min(rc,nr) if desired. */
         HYPERCALL_BOUNCE_SET_SIZE(info, (rc * sizeof(*info)));
         HYPERCALL_BOUNCE_SET_SIZE(name, _name_sz);
         HYPERCALL_BOUNCE_SET_SIZE(len, (rc * sizeof(*len)));
+        HYPERCALL_BOUNCE_SET_SIZE(metadata, _metadata_sz);
+        HYPERCALL_BOUNCE_SET_SIZE(metadata_len, (rc * sizeof(*metadata_len)));
         /* Bounce the data and free the bounce buffer. */
         xc_hypercall_bounce_post(xch, info);
         xc_hypercall_bounce_post(xch, name);
         xc_hypercall_bounce_post(xch, len);
+        xc_hypercall_bounce_post(xch, metadata);
+        xc_hypercall_bounce_post(xch, metadata_len);
 
         name_sz -= _name_sz;
         name_off += _name_sz;
+        metadata_sz -= _metadata_sz;
+        metadata_off += _metadata_sz;
 
         /* And update how many elements of info we have copied into. */
         *done += rc;
@@ -898,6 +938,8 @@ int xc_livepatch_list(xc_interface *xch, const unsigned int max,
         xc_hypercall_bounce_post(xch, len);
         xc_hypercall_bounce_post(xch, name);
         xc_hypercall_bounce_post(xch, info);
+        xc_hypercall_bounce_post(xch, metadata);
+        xc_hypercall_bounce_post(xch, metadata_len);
     }
 
     return rc > 0 ? 0 : rc;
diff --git a/tools/misc/xen-livepatch.c b/tools/misc/xen-livepatch.c
index 8ac3d567fc..f17340a2ee 100644
--- a/tools/misc/xen-livepatch.c
+++ b/tools/misc/xen-livepatch.c
@@ -69,9 +69,11 @@ static int list_func(int argc, char *argv[])
     unsigned int nr, done, left, i;
     xen_livepatch_status_t *info = NULL;
     char *name = NULL;
+    char *metadata = NULL;
     uint32_t *len = NULL;
-    uint64_t name_total_size;
-    off_t name_off;
+    uint32_t *metadata_len = NULL;
+    uint64_t name_total_size, metadata_total_size;
+    off_t name_off, metadata_off;
     int rc = ENOMEM;
 
     if ( argc )
@@ -81,7 +83,7 @@ static int list_func(int argc, char *argv[])
     }
     done = left = 0;
 
-    rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size);
+    rc = xc_livepatch_list_get_sizes(xch, &nr, &name_total_size, &metadata_total_size);
     if ( rc )
     {
         rc = errno;
@@ -109,12 +111,23 @@ static int list_func(int argc, char *argv[])
     if ( !len )
         goto error_len;
 
+    metadata = malloc(metadata_total_size * sizeof(*metadata) + 1);
+    if ( !metadata )
+        goto error_metadata;
+
+    metadata_len = malloc(nr * sizeof(*metadata_len));
+    if ( !metadata_len )
+        goto error_metadata_len;
+
     memset(info, 'A', nr * sizeof(*info));
     memset(name, 'B', name_total_size * sizeof(*name));
     memset(len, 'C', nr * sizeof(*len));
-    name_off = 0;
+    memset(metadata, 'D', metadata_total_size * sizeof(*metadata) + 1);
+    memset(metadata_len, 'E', nr * sizeof(*metadata_len));
+    name_off = metadata_off = 0;
 
-    rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size, &done, &left);
+    rc = xc_livepatch_list(xch, nr, 0, info, name, len, name_total_size,
+                           metadata, metadata_len, metadata_total_size, &done, &left);
     if ( rc || done != nr || left > 0)
     {
         rc = errno;
@@ -124,23 +137,35 @@ static int list_func(int argc, char *argv[])
         goto error;
     }
 
-    fprintf(stdout," ID                                     | status\n"
-                   "----------------------------------------+------------\n");
+    fprintf(stdout," ID                                     | status     | metadata\n"
+                   "----------------------------------------+------------+---------------\n");
 
     for ( i = 0; i < done; i++ )
     {
+        unsigned int j;
         char *name_str = name + name_off;
+        char *metadata_str = metadata + metadata_off;
 
         printf("%-40.*s| %s", len[i], name_str, state2str(info[i].state));
         if ( info[i].rc )
-            printf(" (%d, %s)\n", -info[i].rc, strerror(-info[i].rc));
+            printf(" (%d, %s)    | ", -info[i].rc, strerror(-info[i].rc));
         else
-            puts("");
+            printf("    | ");
+
+        /* Replace all '\0' with semi-colons. */
+        for ( j = 0; metadata_len[i] && j < metadata_len[i] - 1; j++ )
+            metadata_str[j] = (metadata_str[j] ?: ';');
+        printf("%.*s\n", metadata_len[i], metadata_str);
 
         name_off += len[i];
+        metadata_off += metadata_len[i];
     }
 
 error:
+    free(metadata_len);
+error_metadata_len:
+    free(metadata);
+error_metadata:
     free(len);
 error_len:
     free(name);
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 8a9e92660e..f638511ba5 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -1161,7 +1161,8 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
 
     if ( list->nr &&
          (!guest_handle_okay(list->status, list->nr) ||
-          !guest_handle_okay(list->len, list->nr)) )
+          !guest_handle_okay(list->len, list->nr) ||
+          !guest_handle_okay(list->metadata_len, list->nr)) )
         return -EINVAL;
 
     spin_lock(&payload_lock);
@@ -1172,13 +1173,14 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
     }
 
     list->name_total_size = 0;
+    list->metadata_total_size = 0;
     if ( list->nr )
     {
-        uint64_t name_offset = 0;
+        uint64_t name_offset = 0, metadata_offset = 0;
 
         list_for_each_entry( data, &payload_list, list )
         {
-            uint32_t name_len;
+            uint32_t name_len, metadata_len;
 
             if ( list->idx > i++ )
                 continue;
@@ -1189,8 +1191,13 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
             name_len = strlen(data->name) + 1;
             list->name_total_size += name_len;
 
+            metadata_len = data->metadata.len;
+            list->metadata_total_size += metadata_len;
+
             if ( !guest_handle_subrange_okay(list->name, name_offset,
-                                             name_offset + name_len - 1) )
+                                             name_offset + name_len - 1) ||
+                 !guest_handle_subrange_okay(list->metadata, metadata_offset,
+                                             metadata_offset + metadata_len - 1) )
             {
                 rc = -EINVAL;
                 break;
@@ -1200,7 +1207,10 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
             if ( __copy_to_guest_offset(list->name, name_offset,
                                         data->name, name_len) ||
                 __copy_to_guest_offset(list->len, idx, &name_len, 1) ||
-                __copy_to_guest_offset(list->status, idx, &status, 1) )
+                __copy_to_guest_offset(list->status, idx, &status, 1) ||
+                __copy_to_guest_offset(list->metadata, metadata_offset,
+                                       data->metadata.data, metadata_len) ||
+                __copy_to_guest_offset(list->metadata_len, idx, &metadata_len, 1) )
             {
                 rc = -EFAULT;
                 break;
@@ -1208,6 +1218,7 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
 
             idx++;
             name_offset += name_len;
+            metadata_offset += metadata_len;
 
             if ( (idx >= list->nr) || hypercall_preempt_check() )
                 break;
@@ -1218,6 +1229,7 @@ static int livepatch_list(struct xen_sysctl_livepatch_list *list)
         list_for_each_entry( data, &payload_list, list )
         {
             list->name_total_size += strlen(data->name) + 1;
+            list->metadata_total_size += data->metadata.len;
         }
     }
     list->nr = payload_cnt - i; /* Remaining amount. */
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index d95c62f06b..a7812528e2 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -919,16 +919,17 @@ struct xen_sysctl_livepatch_get {
 };
 
 /*
- * Retrieve an array of abbreviated status and names of payloads that are
- * loaded in the hypervisor.
+ * Retrieve an array of abbreviated status, names and metadata of payloads that
+ * are loaded in the hypervisor.
  *
  * If the hypercall returns an positive number, it is the number (up to `nr`)
  * of the payloads returned, along with `nr` updated with the number of remaining
  * payloads, `version` updated (it may be the same across hypercalls. If it varies
- * the data is stale and further calls could fail) and the name_total_size
- * containing total size of transfered data for the array.
- * The `status`, `name`, `len` are updated at their designed index value (`idx`)
- * with the returned value of data.
+ * the data is stale and further calls could fail), `name_total_size` and
+ * `metadata_total_size` containing total sizes of transfered data for both the
+ * arrays.
+ * The `status`, `name`, `len`, `metadata` and `metadata_len` are updated at their
+ * designed index value (`idx`) with the returned value of data.
  *
  * If the hypercall returns E2BIG the `nr` is too big and should be
  * lowered. The upper limit of `nr` is left to the implemention.
@@ -952,6 +953,7 @@ struct xen_sysctl_livepatch_list {
                                                OUT: How many payloads left. */
     uint32_t pad;                           /* IN: Must be zero. */
     uint64_t name_total_size;               /* OUT: Total size of all transfer names */
+    uint64_t metadata_total_size;           /* OUT: Total size of all transfer metadata */
     XEN_GUEST_HANDLE_64(xen_livepatch_status_t) status;  /* OUT. Must have enough
                                                space allocate for nr of them. */
     XEN_GUEST_HANDLE_64(char) name;         /* OUT: Array of names. Each member
@@ -960,6 +962,11 @@ struct xen_sysctl_livepatch_list {
                                                nr of them. */
     XEN_GUEST_HANDLE_64(uint32) len;        /* OUT: Array of lengths of name's.
                                                Must have nr of them. */
+    XEN_GUEST_HANDLE_64(char) metadata;     /* OUT: Array of metadata strings. Each
+                                               member may have an arbitrary length.
+                                               Must have nr of them. */
+    XEN_GUEST_HANDLE_64(uint32) metadata_len;  /* OUT: Array of lengths of metadata's.
+                                                  Must have nr of them. */
 };
 
 /*
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* [Xen-devel] [PATCH v2 12/12] livepatch: Add python bindings for livepatch operations
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (10 preceding siblings ...)
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 11/12] livepatch: Add metadata runtime retrieval mechanism Pawel Wieczorkiewicz
@ 2019-08-27  8:46   ` 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
                     ` (2 subsequent siblings)
  14 siblings, 1 reply; 66+ messages in thread
From: Pawel Wieczorkiewicz @ 2019-08-27  8:46 UTC (permalink / raw)
  To: xen-devel, xen-devel
  Cc: wipawel, Wei Liu, Ian Jackson, mpohlack,
	Marek Marczykowski-Górecki, Pawel Wieczorkiewicz

Extend the XC python bindings library to support also all common
livepatch operations and actions.

Add the python bindings for the following operations:
- status (pyxc_livepatch_status):
  Requires a payload name as an input.
  Returns a status dict containing a state string and a return code
  integer.
- action (pyxc_livepatch_action):
  Requires a payload name and an action id as an input. Timeout and
  flags are optional parameters.
  Returns a return code integer.
- upload (pyxc_livepatch_upload):
  Requires a payload name and a module's filename as an input.
  Returns a return code integer.
- list (pyxc_livepatch_list):
  Takes no parameters.
  Returns a list of dicts containing each payload's:
  * name as a string
  * state as a string
  * return code as an integer
  * list of metadata key=value strings

Each functions throws an exception error based on the errno value
received from its corresponding libxc function call.

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Martin Mazein <amazein@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
Reviewed-by: Leonard Foerster <foersleo@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
---
Changed since v1:
  * changed PyList_Append() with PyList_SetItem() as requested by
    Marek

 tools/python/xen/lowlevel/xc/xc.c | 273 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 273 insertions(+)

diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 7f0358ba9c..d64b9372b6 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -2011,6 +2011,230 @@ static PyObject *pyflask_access(PyObject *self, PyObject *args,
     return Py_BuildValue("i",ret);
 }
 
+static PyObject *pyxc_livepatch_status(XcObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    xen_livepatch_status_t status;
+    PyObject *info_dict = NULL;
+    char *name;
+    int rc;
+
+    static char *kwd_list[] = { "name", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &name) )
+        goto error;
+
+    rc = xc_livepatch_get(self->xc_handle, name, &status);
+    if ( rc )
+        goto error;
+
+    info_dict = Py_BuildValue(
+            "{s:i,s:i}",
+            "state",    status.state,
+            "rc",       status.rc);
+
+error:
+    return info_dict ?: pyxc_error_to_exception(self->xc_handle);
+}
+
+static PyObject *pyxc_livepatch_action(XcObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    int (*action_func)(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
+    char *name;
+    unsigned int action;
+    uint32_t timeout;
+    uint64_t flags;
+    int rc;
+
+    static char *kwd_list[] = { "name", "action", "timeout", "flags", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "sI|Ik", kwd_list,
+                                      &name, &action, &timeout, &flags) )
+        goto error;
+
+    switch (action)
+    {
+    case LIVEPATCH_ACTION_UNLOAD:
+        action_func = xc_livepatch_unload;
+        break;
+    case LIVEPATCH_ACTION_REVERT:
+        action_func = xc_livepatch_revert;
+        break;
+    case LIVEPATCH_ACTION_APPLY:
+        action_func = xc_livepatch_apply;
+        break;
+    case LIVEPATCH_ACTION_REPLACE:
+        action_func = xc_livepatch_replace;
+        break;
+    default:
+        goto error;
+    }
+
+    rc = action_func(self->xc_handle, name, timeout, flags);
+    if ( rc )
+        goto error;
+
+    return Py_BuildValue("i", rc);
+error:
+    return pyxc_error_to_exception(self->xc_handle);
+}
+
+static PyObject *pyxc_livepatch_upload(XcObject *self,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+    unsigned char *fbuf = MAP_FAILED;
+    char *name, *filename;
+    struct stat buf;
+    int fd = 0, rc;
+    ssize_t len;
+
+    static char *kwd_list[] = { "name", "filename", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwd_list,
+                                      &name, &filename))
+        goto error;
+
+    fd = open(filename, O_RDONLY);
+    if ( fd < 0 )
+        goto error;
+
+    if ( stat(filename, &buf) != 0 )
+        goto error;
+
+    len = buf.st_size;
+    fbuf = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+    if ( fbuf == MAP_FAILED )
+        goto error;
+
+    rc = xc_livepatch_upload(self->xc_handle, name, fbuf, len);
+    if ( rc )
+        goto error;
+
+    if ( munmap(fbuf, len) )
+    {
+        fbuf = MAP_FAILED;
+        goto error;
+    }
+    close(fd);
+
+    return Py_BuildValue("i", rc);;
+error:
+    if ( fbuf != MAP_FAILED )
+        munmap(fbuf, len);
+    if ( fd >= 0 )
+        close(fd);
+    return pyxc_error_to_exception(self->xc_handle);
+}
+
+static PyObject *pyxc_livepatch_list(XcObject *self)
+{
+    PyObject *list;
+    unsigned int nr, done, left, i;
+    xen_livepatch_status_t *info = NULL;
+    char *name = NULL;
+    char *metadata = NULL;
+    uint32_t *len = NULL;
+    uint32_t *metadata_len = NULL;
+    uint64_t name_total_size, metadata_total_size;
+    off_t name_off, metadata_off;
+    int rc;
+
+    rc = xc_livepatch_list_get_sizes(self->xc_handle, &nr,
+                                     &name_total_size, &metadata_total_size);
+    if ( rc )
+        goto error;
+
+    if ( nr == 0 )
+        return PyList_New(0);
+
+    rc = ENOMEM;
+    info = malloc(nr * sizeof(*info));
+    if ( !info )
+        goto error;
+
+    name = malloc(name_total_size * sizeof(*name));
+    if ( !name )
+        goto error;
+
+    len = malloc(nr * sizeof(*len));
+    if ( !len )
+        goto error;
+
+    metadata = malloc(metadata_total_size * sizeof(*metadata));
+    if ( !metadata )
+        goto error;
+
+    metadata_len = malloc(nr * sizeof(*metadata_len));
+    if ( !metadata_len )
+        goto error;
+
+    rc = xc_livepatch_list(self->xc_handle, nr, 0, info,
+                           name, len, name_total_size,
+                           metadata, metadata_len, metadata_total_size,
+                           &done, &left);
+    if ( rc )
+        goto error;
+
+    list = PyList_New(done);
+    name_off = metadata_off = 0;
+    for ( i = 0; i < done; i++ )
+    {
+        PyObject *info_dict, *metadata_list;
+        char *name_str, *metadata_str;
+
+        name_str = name + name_off;
+        metadata_str = metadata + metadata_off;
+
+        metadata_list = PyList_New(0);
+        for ( char *s = metadata_str; s < metadata_str + metadata_len[i]; s += strlen(s) + 1 )
+        {
+            PyObject *field = Py_BuildValue("s", s);
+            if ( field == NULL )
+            {
+                Py_DECREF(list);
+                Py_DECREF(metadata_list);
+                rc = EFAULT;
+                goto error;
+            }
+
+            PyList_Append(metadata_list, field);
+            Py_DECREF(field);
+        }
+
+        info_dict = Py_BuildValue(
+            "{s:s,s:i,s:i,s:N}",
+            "name",     name_str,
+            "state",    info[i].state,
+            "rc",       info[i].rc,
+            "metadata", metadata_list);
+
+        if ( info_dict == NULL )
+        {
+            Py_DECREF(list);
+            Py_DECREF(metadata_list);
+            rc = EFAULT;
+            goto error;
+        }
+        PyList_SetItem(list, i, info_dict);
+        Py_DECREF(info_dict);
+
+        name_off += len[i];
+        metadata_off += metadata_len[i];
+    }
+
+error:
+    free(info);
+    free(name);
+    free(len);
+    free(metadata);
+    free(metadata_len);
+    return rc ? pyxc_error_to_exception(self->xc_handle) : list;
+}
+
 static PyMethodDef pyxc_methods[] = {
     { "domain_create", 
       (PyCFunction)pyxc_domain_create, 
@@ -2587,6 +2811,44 @@ static PyMethodDef pyxc_methods[] = {
       "Returns: [int]: 0 on all permission granted; -1 if any permissions are \
        denied\n" }, 
 
+    { "livepatch_status",
+      (PyCFunction)pyxc_livepatch_status,
+      METH_KEYWORDS, "\n"
+      "Gets current state and return code for a specified module.\n"
+      " name     [str]: Module name to be used\n"
+      "Returns: [dict] on success; throwing an exception on error\n"
+      " state    [int]: Module current state: CHECKED or APPLIED\n"
+      " rc       [int]: Return code of last module's operation\n" },
+
+    { "livepatch_upload",
+      (PyCFunction)pyxc_livepatch_upload,
+      METH_KEYWORDS, "\n"
+      "Uploads a module with specified name from filename.\n"
+      " name     [str]: Module name to be used\n"
+      " filename [str]: Filename of a module to be uploaded\n"
+      "Returns: [int] 0 on success; throwing an exception on error\n" },
+
+    { "livepatch_action",
+      (PyCFunction)pyxc_livepatch_action,
+      METH_KEYWORDS, "\n"
+      "Performs an action (unload, revert, apply or replace) on a specified \
+       module.\n"
+      " name      [str]: Module name to be used\n"
+      " action   [uint]: Action enum id\n"
+      " timeout  [uint]: Action scheduled execution timeout\n"
+      " flags   [ulong]: Flags specifying action's extra parameters\n"
+      "Returns: [int] 0 on success; throwing an exception on error\n" },
+
+    { "livepatch_list",
+      (PyCFunction)pyxc_livepatch_list,
+      METH_NOARGS, "\n"
+      "List all uploaded livepatch modules with their current state and metadata.\n"
+      "Returns: [list of dicts] on success; throwing an exception on error\n"
+      " name     [str]: Module name\n"
+      " state    [int]: Module current state: CHECKED or APPLIED\n"
+      " rc       [int]: Return code of last module's operation\n"
+      " metadata [list]: List of module's metadata 'key=value' strings\n" },
+
     { NULL, NULL, 0, NULL }
 };
 
@@ -2698,6 +2960,17 @@ PyMODINIT_FUNC initxc(void)
     PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
     PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT2", XEN_SCHEDULER_CREDIT2);
 
+    /* Expose livepatch constants to Python */
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_UNLOAD", LIVEPATCH_ACTION_UNLOAD);
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_REVERT", LIVEPATCH_ACTION_REVERT);
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_APPLY", LIVEPATCH_ACTION_APPLY);
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_REPLACE", LIVEPATCH_ACTION_REPLACE);
+
+    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_APPLY_NODEPS", LIVEPATCH_ACTION_APPLY_NODEPS);
+
+    PyModule_AddIntConstant(m, "LIVEPATCH_STATE_APPLIED", LIVEPATCH_STATE_APPLIED);
+    PyModule_AddIntConstant(m, "LIVEPATCH_STATE_CHECKED", LIVEPATCH_STATE_CHECKED);
+
 #if PY_MAJOR_VERSION >= 3
     return m;
 #endif
-- 
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

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 05/12] livepatch: Add support for apply|revert action replacement hooks
  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
  0 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-27 16:58 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, Tim Deegan, Ross Lagerwall,
	Julien Grall, Jan Beulich

On August 27, 2019 4:46:17 AM EDT, Pawel Wieczorkiewicz <wipawel@amazon.de> wrote:
>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.

Is there sense in having the old ones anymore? We could just remove them altogether and just use the new ones instead from the start?


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 05/12] livepatch: Add support for apply|revert action replacement hooks
  2019-08-27 16:58     ` Konrad Rzeszutek Wilk
@ 2019-08-28  7:37       ` Wieczorkiewicz, Pawel
  0 siblings, 0 replies; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-28  7:37 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Wieczorkiewicz, Pawel, Julien Grall, Jan Beulich,
	xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1742 bytes --]



On 27. Aug 2019, at 18:58, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com<mailto:konrad.wilk@oracle.com>> wrote:

On August 27, 2019 4:46:17 AM EDT, Pawel Wieczorkiewicz <wipawel@amazon.de<mailto:wipawel@amazon.de>> wrote:
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.

Is there sense in having the old ones anymore? We could just remove them altogether and just use the new ones instead from the start?


Yes, I believe there is. The old ones represent well-tested, proven way of
payload application (or revert) which preserves conservative behavior of the system
via enforcing certain assumptions.
The old ones cover 99% of the production use cases, so I would insist on keeping
them in (at least for now).

Later, we could modify livepatch-build-tools to always generate the original
apply|revert functions (in a default case) as part of payloads (hooks).
But, I would not do it just now.

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 3346 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 12/12] livepatch: Add python bindings for livepatch operations
  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
  0 siblings, 0 replies; 66+ messages in thread
From: Marek Marczykowski-Górecki @ 2019-08-28 13:21 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: wipawel, Wei Liu, Ian Jackson, mpohlack, xen-devel, xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 12191 bytes --]

On Tue, Aug 27, 2019 at 08:46:24AM +0000, Pawel Wieczorkiewicz wrote:
> Extend the XC python bindings library to support also all common
> livepatch operations and actions.
> 
> Add the python bindings for the following operations:
> - status (pyxc_livepatch_status):
>   Requires a payload name as an input.
>   Returns a status dict containing a state string and a return code
>   integer.
> - action (pyxc_livepatch_action):
>   Requires a payload name and an action id as an input. Timeout and
>   flags are optional parameters.
>   Returns a return code integer.
> - upload (pyxc_livepatch_upload):
>   Requires a payload name and a module's filename as an input.
>   Returns a return code integer.
> - list (pyxc_livepatch_list):
>   Takes no parameters.
>   Returns a list of dicts containing each payload's:
>   * name as a string
>   * state as a string
>   * return code as an integer
>   * list of metadata key=value strings
> 
> Each functions throws an exception error based on the errno value
> received from its corresponding libxc function call.
> 
> Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
> Reviewed-by: Martin Mazein <amazein@amazon.de>
> Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
> Reviewed-by: Leonard Foerster <foersleo@amazon.de>
> Reviewed-by: Norbert Manthey <nmanthey@amazon.de>

Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>

> ---
> Changed since v1:
>   * changed PyList_Append() with PyList_SetItem() as requested by
>     Marek
> 
>  tools/python/xen/lowlevel/xc/xc.c | 273 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 273 insertions(+)
> 
> diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
> index 7f0358ba9c..d64b9372b6 100644
> --- a/tools/python/xen/lowlevel/xc/xc.c
> +++ b/tools/python/xen/lowlevel/xc/xc.c
> @@ -2011,6 +2011,230 @@ static PyObject *pyflask_access(PyObject *self, PyObject *args,
>      return Py_BuildValue("i",ret);
>  }
>  
> +static PyObject *pyxc_livepatch_status(XcObject *self,
> +                                       PyObject *args,
> +                                       PyObject *kwds)
> +{
> +    xen_livepatch_status_t status;
> +    PyObject *info_dict = NULL;
> +    char *name;
> +    int rc;
> +
> +    static char *kwd_list[] = { "name", NULL };
> +
> +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &name) )
> +        goto error;
> +
> +    rc = xc_livepatch_get(self->xc_handle, name, &status);
> +    if ( rc )
> +        goto error;
> +
> +    info_dict = Py_BuildValue(
> +            "{s:i,s:i}",
> +            "state",    status.state,
> +            "rc",       status.rc);
> +
> +error:
> +    return info_dict ?: pyxc_error_to_exception(self->xc_handle);
> +}
> +
> +static PyObject *pyxc_livepatch_action(XcObject *self,
> +                                       PyObject *args,
> +                                       PyObject *kwds)
> +{
> +    int (*action_func)(xc_interface *xch, char *name, uint32_t timeout, uint64_t flags);
> +    char *name;
> +    unsigned int action;
> +    uint32_t timeout;
> +    uint64_t flags;
> +    int rc;
> +
> +    static char *kwd_list[] = { "name", "action", "timeout", "flags", NULL };
> +
> +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "sI|Ik", kwd_list,
> +                                      &name, &action, &timeout, &flags) )
> +        goto error;
> +
> +    switch (action)
> +    {
> +    case LIVEPATCH_ACTION_UNLOAD:
> +        action_func = xc_livepatch_unload;
> +        break;
> +    case LIVEPATCH_ACTION_REVERT:
> +        action_func = xc_livepatch_revert;
> +        break;
> +    case LIVEPATCH_ACTION_APPLY:
> +        action_func = xc_livepatch_apply;
> +        break;
> +    case LIVEPATCH_ACTION_REPLACE:
> +        action_func = xc_livepatch_replace;
> +        break;
> +    default:
> +        goto error;
> +    }
> +
> +    rc = action_func(self->xc_handle, name, timeout, flags);
> +    if ( rc )
> +        goto error;
> +
> +    return Py_BuildValue("i", rc);
> +error:
> +    return pyxc_error_to_exception(self->xc_handle);
> +}
> +
> +static PyObject *pyxc_livepatch_upload(XcObject *self,
> +                                       PyObject *args,
> +                                       PyObject *kwds)
> +{
> +    unsigned char *fbuf = MAP_FAILED;
> +    char *name, *filename;
> +    struct stat buf;
> +    int fd = 0, rc;
> +    ssize_t len;
> +
> +    static char *kwd_list[] = { "name", "filename", NULL };
> +
> +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ss", kwd_list,
> +                                      &name, &filename))
> +        goto error;
> +
> +    fd = open(filename, O_RDONLY);
> +    if ( fd < 0 )
> +        goto error;
> +
> +    if ( stat(filename, &buf) != 0 )
> +        goto error;
> +
> +    len = buf.st_size;
> +    fbuf = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
> +    if ( fbuf == MAP_FAILED )
> +        goto error;
> +
> +    rc = xc_livepatch_upload(self->xc_handle, name, fbuf, len);
> +    if ( rc )
> +        goto error;
> +
> +    if ( munmap(fbuf, len) )
> +    {
> +        fbuf = MAP_FAILED;
> +        goto error;
> +    }
> +    close(fd);
> +
> +    return Py_BuildValue("i", rc);;
> +error:
> +    if ( fbuf != MAP_FAILED )
> +        munmap(fbuf, len);
> +    if ( fd >= 0 )
> +        close(fd);
> +    return pyxc_error_to_exception(self->xc_handle);
> +}
> +
> +static PyObject *pyxc_livepatch_list(XcObject *self)
> +{
> +    PyObject *list;
> +    unsigned int nr, done, left, i;
> +    xen_livepatch_status_t *info = NULL;
> +    char *name = NULL;
> +    char *metadata = NULL;
> +    uint32_t *len = NULL;
> +    uint32_t *metadata_len = NULL;
> +    uint64_t name_total_size, metadata_total_size;
> +    off_t name_off, metadata_off;
> +    int rc;
> +
> +    rc = xc_livepatch_list_get_sizes(self->xc_handle, &nr,
> +                                     &name_total_size, &metadata_total_size);
> +    if ( rc )
> +        goto error;
> +
> +    if ( nr == 0 )
> +        return PyList_New(0);
> +
> +    rc = ENOMEM;
> +    info = malloc(nr * sizeof(*info));
> +    if ( !info )
> +        goto error;
> +
> +    name = malloc(name_total_size * sizeof(*name));
> +    if ( !name )
> +        goto error;
> +
> +    len = malloc(nr * sizeof(*len));
> +    if ( !len )
> +        goto error;
> +
> +    metadata = malloc(metadata_total_size * sizeof(*metadata));
> +    if ( !metadata )
> +        goto error;
> +
> +    metadata_len = malloc(nr * sizeof(*metadata_len));
> +    if ( !metadata_len )
> +        goto error;
> +
> +    rc = xc_livepatch_list(self->xc_handle, nr, 0, info,
> +                           name, len, name_total_size,
> +                           metadata, metadata_len, metadata_total_size,
> +                           &done, &left);
> +    if ( rc )
> +        goto error;
> +
> +    list = PyList_New(done);
> +    name_off = metadata_off = 0;
> +    for ( i = 0; i < done; i++ )
> +    {
> +        PyObject *info_dict, *metadata_list;
> +        char *name_str, *metadata_str;
> +
> +        name_str = name + name_off;
> +        metadata_str = metadata + metadata_off;
> +
> +        metadata_list = PyList_New(0);
> +        for ( char *s = metadata_str; s < metadata_str + metadata_len[i]; s += strlen(s) + 1 )
> +        {
> +            PyObject *field = Py_BuildValue("s", s);
> +            if ( field == NULL )
> +            {
> +                Py_DECREF(list);
> +                Py_DECREF(metadata_list);
> +                rc = EFAULT;
> +                goto error;
> +            }
> +
> +            PyList_Append(metadata_list, field);
> +            Py_DECREF(field);
> +        }
> +
> +        info_dict = Py_BuildValue(
> +            "{s:s,s:i,s:i,s:N}",
> +            "name",     name_str,
> +            "state",    info[i].state,
> +            "rc",       info[i].rc,
> +            "metadata", metadata_list);
> +
> +        if ( info_dict == NULL )
> +        {
> +            Py_DECREF(list);
> +            Py_DECREF(metadata_list);
> +            rc = EFAULT;
> +            goto error;
> +        }
> +        PyList_SetItem(list, i, info_dict);
> +        Py_DECREF(info_dict);
> +
> +        name_off += len[i];
> +        metadata_off += metadata_len[i];
> +    }
> +
> +error:
> +    free(info);
> +    free(name);
> +    free(len);
> +    free(metadata);
> +    free(metadata_len);
> +    return rc ? pyxc_error_to_exception(self->xc_handle) : list;
> +}
> +
>  static PyMethodDef pyxc_methods[] = {
>      { "domain_create", 
>        (PyCFunction)pyxc_domain_create, 
> @@ -2587,6 +2811,44 @@ static PyMethodDef pyxc_methods[] = {
>        "Returns: [int]: 0 on all permission granted; -1 if any permissions are \
>         denied\n" }, 
>  
> +    { "livepatch_status",
> +      (PyCFunction)pyxc_livepatch_status,
> +      METH_KEYWORDS, "\n"
> +      "Gets current state and return code for a specified module.\n"
> +      " name     [str]: Module name to be used\n"
> +      "Returns: [dict] on success; throwing an exception on error\n"
> +      " state    [int]: Module current state: CHECKED or APPLIED\n"
> +      " rc       [int]: Return code of last module's operation\n" },
> +
> +    { "livepatch_upload",
> +      (PyCFunction)pyxc_livepatch_upload,
> +      METH_KEYWORDS, "\n"
> +      "Uploads a module with specified name from filename.\n"
> +      " name     [str]: Module name to be used\n"
> +      " filename [str]: Filename of a module to be uploaded\n"
> +      "Returns: [int] 0 on success; throwing an exception on error\n" },
> +
> +    { "livepatch_action",
> +      (PyCFunction)pyxc_livepatch_action,
> +      METH_KEYWORDS, "\n"
> +      "Performs an action (unload, revert, apply or replace) on a specified \
> +       module.\n"
> +      " name      [str]: Module name to be used\n"
> +      " action   [uint]: Action enum id\n"
> +      " timeout  [uint]: Action scheduled execution timeout\n"
> +      " flags   [ulong]: Flags specifying action's extra parameters\n"
> +      "Returns: [int] 0 on success; throwing an exception on error\n" },
> +
> +    { "livepatch_list",
> +      (PyCFunction)pyxc_livepatch_list,
> +      METH_NOARGS, "\n"
> +      "List all uploaded livepatch modules with their current state and metadata.\n"
> +      "Returns: [list of dicts] on success; throwing an exception on error\n"
> +      " name     [str]: Module name\n"
> +      " state    [int]: Module current state: CHECKED or APPLIED\n"
> +      " rc       [int]: Return code of last module's operation\n"
> +      " metadata [list]: List of module's metadata 'key=value' strings\n" },
> +
>      { NULL, NULL, 0, NULL }
>  };
>  
> @@ -2698,6 +2960,17 @@ PyMODINIT_FUNC initxc(void)
>      PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT", XEN_SCHEDULER_CREDIT);
>      PyModule_AddIntConstant(m, "XEN_SCHEDULER_CREDIT2", XEN_SCHEDULER_CREDIT2);
>  
> +    /* Expose livepatch constants to Python */
> +    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_UNLOAD", LIVEPATCH_ACTION_UNLOAD);
> +    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_REVERT", LIVEPATCH_ACTION_REVERT);
> +    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_APPLY", LIVEPATCH_ACTION_APPLY);
> +    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_REPLACE", LIVEPATCH_ACTION_REPLACE);
> +
> +    PyModule_AddIntConstant(m, "LIVEPATCH_ACTION_APPLY_NODEPS", LIVEPATCH_ACTION_APPLY_NODEPS);
> +
> +    PyModule_AddIntConstant(m, "LIVEPATCH_STATE_APPLIED", LIVEPATCH_STATE_APPLIED);
> +    PyModule_AddIntConstant(m, "LIVEPATCH_STATE_CHECKED", LIVEPATCH_STATE_CHECKED);
> +
>  #if PY_MAJOR_VERSION >= 3
>      return m;
>  #endif

-- 
Best Regards,
Marek Marczykowski-Górecki
Invisible Things Lab
A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  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-09-05 18:05     ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-29 14:34 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu,
	Konrad Rzeszutek Wilk, George Dunlap, Andrew Cooper, Ian Jackson,
	mpohlack, xen-devel, Ross Lagerwall, Julien Grall, Jan Beulich,
	xen-devel

> diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
> index 23113d3418..067861903f 100644
> --- a/xen/test/livepatch/Makefile
> +++ b/xen/test/livepatch/Makefile
> @@ -27,6 +27,8 @@ 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
> +LIVEPATCH_EXPECTATIONS:= xen_expectations.livepatch
> +LIVEPATCH_EXPECTATIONS_FAIL:= xen_expectations_fail.livepatch
>  
>  LIVEPATCHES += $(LIVEPATCH)
>  LIVEPATCHES += $(LIVEPATCH_BYE)
> @@ -40,6 +42,8 @@ LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOFUNC)
>  LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_MARKER)
>  LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOAPPLY)
>  LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
> +LIVEPATCHES += $(LIVEPATCH_EXPECTATIONS)
> +LIVEPATCHES += $(LIVEPATCH_EXPECTATIONS_FAIL)
>  
>  LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch
>  
> @@ -54,7 +58,7 @@ uninstall:
>  
>  .PHONY: clean
>  clean::
> -	rm -f *.o .*.o.d *.livepatch config.h
> +	rm -f *.o .*.o.d *.livepatch config.h expect_config.h
>  
>  #
>  # To compute these values we need the binary files: xen-syms
> @@ -182,8 +186,27 @@ xen_actions_hooks_norevert.o: config.h
>  $(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) $^
>  
> +CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')
> +.PHONY: expect_config.h
> +expect_config.h: EXPECT_BYTES=$(call CODE_GET_EXPECT,$(BASEDIR)/xen-syms,xen_extra_version)
> +expect_config.h: EXPECT_BYTES_COUNT=6
> +expect_config.h: xen_expectations.o
> +	(set -e; \
> +	 echo "#define EXPECT_BYTES $(EXPECT_BYTES)"; \
> +         echo "#define EXPECT_BYTES_COUNT $(EXPECT_BYTES_COUNT)") > $@
> +
> +xen_expectations.o: expect_config.h
> +
> +.PHONY: $(LIVEPATCH_EXPECTATIONS)
> +$(LIVEPATCH_EXPECTATIONS): xen_expectations.o xen_hello_world_func.o note.o xen_note.o
> +	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_EXPECTATIONS) $^
> +
> +.PHONY: $(LIVEPATCH_EXPECTATIONS_FAIL)
> +$(LIVEPATCH_EXPECTATIONS_FAIL): xen_expectations_fail.o xen_hello_world_func.o note.o xen_note.o
> +	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_EXPECTATIONS_FAIL) $^
> +
>  .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_MARKER) $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) \
> -           $(LIVEPATCH_ACTION_HOOKS_NOREVERT)
> +           $(LIVEPATCH_ACTION_HOOKS_NOREVERT) $(LIVEPATCH_EXPECTATIONS) $(LIVEPATCH_EXPECTATIONS_FAIL)
> diff --git a/xen/test/livepatch/xen_expectations.c b/xen/test/livepatch/xen_expectations.c
> new file mode 100644
> index 0000000000..c8175a458b
> --- /dev/null
> +++ b/xen/test/livepatch/xen_expectations.c
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
> + *
> + */
> +
> +#include "expect_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 livepatch_exceptions_str[] = "xen_extra_version";
> +extern const char *xen_hello_world(void);
> +
> +struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
> +    .version = LIVEPATCH_PAYLOAD_VERSION,
> +    .name = livepatch_exceptions_str,
> +    .new_addr = xen_hello_world,
> +    .old_addr = xen_extra_version,
> +    .new_size = EXPECT_BYTES_COUNT,
> +    .old_size = EXPECT_BYTES_COUNT,
> +    .expect = {
> +        .enabled = 1,
> +        .len = EXPECT_BYTES_COUNT,
> +        .data = EXPECT_BYTES
> +    },
> +
> +};

When I compile with 32-bit ARM 'make tests' I get:

arm-eabi-ld    -EL -EL     --build-id=sha1 -r -o xen_action_hooks_norevert.livepatch xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o
make[3]: Circular expect_config.h <- xen_expectations.o dependency dropped.
objdump: can't disassemble for architecture UNKNOWN!

(set -e; \
 echo "#define EXPECT_BYTES {"; \
         echo "#define EXPECT_BYTES_COUNT 6") > expect_config.h
arm-eabi-gcc -marm -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O1 -fno-omit-frame-pointer -nostdinc -fno-builtin -fno-common -Werror -Wredundant-decls -Wno-pointer-arith -Wvla -pipe -D__XEN__ -include /home/konrad/A20/xen.git/xen/include/xen/config.h '-D__OBJECT_FILE__="xen_expectations.o"' -Wa,--strip-local-absolute -g -MMD -MF ./.xen_expectations.o.d -msoft-float -mcpu=cortex-a15 -DCONFIG_EARLY_PRINTK -DEARLY_PRINTK_INC=\"debug-8250.inc\" -DEARLY_PRINTK_BAUD= -DEARLY_UART_BASE_ADDRESS=0x01c28000 -DEARLY_UART_REG_SHIFT=2  -I/home/konrad/A20/xen.git/xen/include -fno-stack-protector -fno-exceptions -Wnested-externs -DGCC_HAS_VISIBILITY_ATTRIBUTE -marm -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -c xen_expectations.c -o xen_expectations.o
xen_expectations.c:31:2: error: expected '}' before ';' token
 };
  ^
xen_expectations.c:18:76: note: to match this '{'
 struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
                                                                            ^
make[3]: *** [/home/konrad/A20/xen.git/xen/Rules.mk:202: xen_expectations.o] Error 1
make[3]: Leaving directory '/home/konrad/A20/xen.git/xen/test/livepatch'


And this is what expect_config.h looks like:

#define EXPECT_BYTES {
#define EXPECT_BYTES_COUNT 6

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  2019-08-29 14:34     ` Konrad Rzeszutek Wilk
@ 2019-08-29 15:29       ` Wieczorkiewicz, Pawel
  0 siblings, 0 replies; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-29 15:29 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Konrad Rzeszutek Wilk,
	George Dunlap, Andrew Cooper, Ross Lagerwall, Ian Jackson,
	xen-devel, Pohlack, Martin, Wieczorkiewicz, Pawel, Julien Grall,
	Jan Beulich, xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 4263 bytes --]



On 29. Aug 2019, at 16:34, Konrad Rzeszutek Wilk <konrad@darnok.org<mailto:konrad@darnok.org>> wrote:



…snip...

+
+struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .name = livepatch_exceptions_str,
+    .new_addr = xen_hello_world,
+    .old_addr = xen_extra_version,
+    .new_size = EXPECT_BYTES_COUNT,
+    .old_size = EXPECT_BYTES_COUNT,
+    .expect = {
+        .enabled = 1,
+        .len = EXPECT_BYTES_COUNT,
+        .data = EXPECT_BYTES
+    },
+
+};

When I compile with 32-bit ARM 'make tests' I get:

arm-eabi-ld    -EL -EL     --build-id=sha1 -r -o xen_action_hooks_norevert.livepatch xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o
make[3]: Circular expect_config.h <- xen_expectations.o dependency dropped.
objdump: can't disassemble for architecture UNKNOWN!

(set -e; \
echo "#define EXPECT_BYTES {"; \
        echo "#define EXPECT_BYTES_COUNT 6") > expect_config.h
arm-eabi-gcc -marm -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O1 -fno-omit-frame-pointer -nostdinc -fno-builtin -fno-common -Werror -Wredundant-decls -Wno-pointer-arith -Wvla -pipe -D__XEN__ -include /home/konrad/A20/xen.git/xen/include/xen/config.h '-D__OBJECT_FILE__="xen_expectations.o"' -Wa,--strip-local-absolute -g -MMD -MF ./.xen_expectations.o.d -msoft-float -mcpu=cortex-a15 -DCONFIG_EARLY_PRINTK -DEARLY_PRINTK_INC=\"debug-8250.inc\" -DEARLY_PRINTK_BAUD= -DEARLY_UART_BASE_ADDRESS=0x01c28000 -DEARLY_UART_REG_SHIFT=2  -I/home/konrad/A20/xen.git/xen/include -fno-stack-protector -fno-exceptions -Wnested-externs -DGCC_HAS_VISIBILITY_ATTRIBUTE -marm -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -c xen_expectations.c -o xen_expectations.o
xen_expectations.c:31:2: error: expected '}' before ';' token
};
 ^
xen_expectations.c:18:76: note: to match this '{'
struct livepatch_func __section(".livepatch.funcs") livepatch_exceptions = {
                                                                           ^
make[3]: *** [/home/konrad/A20/xen.git/xen/Rules.mk:202: xen_expectations.o] Error 1
make[3]: Leaving directory '/home/konrad/A20/xen.git/xen/test/livepatch'


And this is what expect_config.h looks like:

#define EXPECT_BYTES {
#define EXPECT_BYTES_COUNT 6

Hi Konrad,

I think I fixed it with the following change on top:

[DIFF START]
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 067861903f..20bdeb6c6d 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -186,10 +186,17 @@ xen_actions_hooks_norevert.o: config.h
 $(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) $^

-CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')
+ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm)
+INSN_WIDTH := 4
+INSN_PER_LINE := 2
+else
+INSN_WIDTH := 1
+INSN_PER_LINE := 8
+endif
+CODE_GET_EXPECT=$(shell $(OBJDUMP) -d --insn-width=$(INSN_WIDTH) $(1) | sed -n -e '/<'$(2)'>:$$/,/^$$/ p' | tail -n +2 | head -n $(INSN_PER_LINE) | awk '{printf "%s", $$2}' | sed 's/.\{2\}/0x&,/g' | sed 's/^/{/;s/,$$/}/g')
 .PHONY: expect_config.h
 expect_config.h: EXPECT_BYTES=$(call CODE_GET_EXPECT,$(BASEDIR)/xen-syms,xen_extra_version)
-expect_config.h: EXPECT_BYTES_COUNT=6
+expect_config.h: EXPECT_BYTES_COUNT=8
 expect_config.h: xen_expectations.o
        (set -e; \
         echo "#define EXPECT_BYTES $(EXPECT_BYTES)"; \
[DIFF END]

I will test that some more and add it to the v3 of the patchset.

Best Regards,
Pawel Wieczorkiewicz






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



[-- Attachment #1.2: Type: text/html, Size: 7939 bytes --]

[-- Attachment #2: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  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:58     ` Konrad Rzeszutek Wilk
  2019-08-29 16:16       ` Wieczorkiewicz, Pawel
  2019-09-05 18:05     ` Konrad Rzeszutek Wilk
  2 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-29 15:58 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, xen-devel, Ross Lagerwall,
	Julien Grall, Jan Beulich, xen-devel

> +CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')

Ony my Hikey 960 when I compile using an native compiler I get:

gcc  -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O1 -fno-omit-frame-pointer -nostdinc -fno-builtin -fno-common -Werror -Wredundant-decls -Wno-pointer-arith -Wvla -pipe -D__XEN__ -include /home/xen.git/xen/include/xen/config.h '-D__OBJECT_FILE__="xen_expectations.o"' -Wa,--strip-local-absolute -g -MMD -MF ./.xen_expectations.o.d -mcpu=generic -mgeneral-regs-only   -I/home/xen.git/xen/include -fno-stack-protector -fno-exceptions -Wnested-externs -DGCC_HAS_VISIBILITY_ATTRIBUTE  -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -c xen_expectations.c -o xen_expectations.o
/home/xen.git/xen/Rules.mk:202: recipe for target 'xen_expectations.o' failed
make[3]: Circular expect_config.h <- xen_expectations.o dependency dropped.
In file included from xen_expectations.c:6:0:
expect_config.h:1:23: error: large integer implicitly truncated to unsigned type
 [-Werror=overflow]
 #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
c09112e0}
                       ^
xen_expectations.c:28:17: note: in expansion of macro ‘EXPECT_BYTES’
         .data = EXPECT_BYTES
                 ^~~~~~~~~~~~
expect_config.h:1:34: error: large integer implicitly truncated to unsigned type
 [-Werror=overflow]
 #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
c09112e0}
                                  ^
xen_expectations.c:28:17: note: in expansion of macro ‘EXPECT_BYTES’
         .data = EXPECT_BYTES
                 ^~~~~~~~~~~~
expect_config.h:1:45: error: large integer implicitly truncated to unsigned type
 [-Werror=overflow]
 #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
c09112e0}
…

make[3]: Leaving directory '/home/xen.git/xen/test/livepatch'
Makefile:11: recipe for target 'build' failed
make[2]: Leaving directory '/home/xen.git/xen/test'
Makefile:85: recipe for target '_tests' failed
make[1]: Leaving directory '/home/xen.git/xen'
Makefile:45: recipe for target 'tests' failed
root@hikey960:/home/xen.git/xen# cat test/livepatch/expect_config.h 
#define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0xc09112e0}
#define EXPECT_BYTES_COUNT 6



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  2019-08-29 15:58     ` Konrad Rzeszutek Wilk
@ 2019-08-29 16:16       ` Wieczorkiewicz, Pawel
  2019-08-29 17:49         ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-29 16:16 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Wieczorkiewicz, Pawel, Julien Grall, Jan Beulich,
	xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 3043 bytes --]



On 29. Aug 2019, at 17:58, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com<mailto:konrad.wilk@oracle.com>> wrote:

+CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')

Ony my Hikey 960 when I compile using an native compiler I get:

gcc  -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O1 -fno-omit-frame-pointer -nostdinc -fno-builtin -fno-common -Werror -Wredundant-decls -Wno-pointer-arith -Wvla -pipe -D__XEN__ -include /home/xen.git/xen/include/xen/config.h '-D__OBJECT_FILE__="xen_expectations.o"' -Wa,--strip-local-absolute -g -MMD -MF ./.xen_expectations.o.d -mcpu=generic -mgeneral-regs-only   -I/home/xen.git/xen/include -fno-stack-protector -fno-exceptions -Wnested-externs -DGCC_HAS_VISIBILITY_ATTRIBUTE  -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -c xen_expectations.c -o xen_expectations.o
/home/xen.git/xen/Rules.mk:202: recipe for target 'xen_expectations.o' failed
make[3]: Circular expect_config.h <- xen_expectations.o dependency dropped.
In file included from xen_expectations.c:6:0:
expect_config.h:1:23: error: large integer implicitly truncated to unsigned type
[-Werror=overflow]
#define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
c09112e0}
                      ^
xen_expectations.c:28:17: note: in expansion of macro ‘EXPECT_BYTES’
        .data = EXPECT_BYTES
                ^~~~~~~~~~~~
expect_config.h:1:34: error: large integer implicitly truncated to unsigned type
[-Werror=overflow]
#define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
c09112e0}
                                 ^
xen_expectations.c:28:17: note: in expansion of macro ‘EXPECT_BYTES’
        .data = EXPECT_BYTES
                ^~~~~~~~~~~~
expect_config.h:1:45: error: large integer implicitly truncated to unsigned type
[-Werror=overflow]
#define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
c09112e0}
…

make[3]: Leaving directory '/home/xen.git/xen/test/livepatch'
Makefile:11: recipe for target 'build' failed
make[2]: Leaving directory '/home/xen.git/xen/test'
Makefile:85: recipe for target '_tests' failed
make[1]: Leaving directory '/home/xen.git/xen'
Makefile:45: recipe for target 'tests' failed
root@hikey960:/home/xen.git/xen# cat test/livepatch/expect_config.h
#define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0xc09112e0}
#define EXPECT_BYTES_COUNT 6



Could you please try with the patch attached?




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



[-- Attachment #1.2: Type: text/html, Size: 4807 bytes --]

[-- Attachment #2: 0001-fixup-livepatch-Add-support-for-inline-asm-hotpatchi.patch --]
[-- Type: application/octet-stream, Size: 1593 bytes --]

From 5dc24035e63aac8182ba91b98d0c9bb85c9256d9 Mon Sep 17 00:00:00 2001
From: Pawel Wieczorkiewicz <wipawel@amazon.de>
Date: Thu, 29 Aug 2019 15:43:23 +0000
Subject: [PATCH] fixup! livepatch: Add support for inline asm hotpatching
 expectations

---
 xen/test/livepatch/Makefile | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 067861903f..ae2c479e61 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -186,10 +186,15 @@ xen_actions_hooks_norevert.o: config.h
 $(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) $^
 
-CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')
+EXPECT_BYTES_COUNT := 8
+ifeq ($(findstring arm, $(XEN_TARGET_ARCH) $(ARCH)),arm)
+BYTES_PER_LINE := 4
+else
+BYTES_PER_LINE := 1
+endif
+CODE_GET_EXPECT=$(shell $(OBJDUMP) -d --insn-width=$(BYTES_PER_LINE) $(1) | sed -n -e '/<'$(2)'>:$$/,/^$$/ p' | tail -n +2 | head -n $$(($(EXPECT_BYTES_COUNT)/$(BYTES_PER_LINE))) | awk '{printf "%s", $$2}' | sed 's/.\{2\}/0x&,/g' | sed 's/^/{/;s/,$$/}/g')
 .PHONY: expect_config.h
 expect_config.h: EXPECT_BYTES=$(call CODE_GET_EXPECT,$(BASEDIR)/xen-syms,xen_extra_version)
-expect_config.h: EXPECT_BYTES_COUNT=6
 expect_config.h: xen_expectations.o
 	(set -e; \
 	 echo "#define EXPECT_BYTES $(EXPECT_BYTES)"; \
-- 
2.16.5


[-- Attachment #3: ATT00001.htm --]
[-- Type: text/html, Size: 1179 bytes --]

[-- Attachment #4: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  2019-08-29 16:16       ` Wieczorkiewicz, Pawel
@ 2019-08-29 17:49         ` Konrad Rzeszutek Wilk
  2019-08-29 19:07           ` Wieczorkiewicz, Pawel
  0 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-29 17:49 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, xen-devel, Pohlack, Martin,
	Ross Lagerwall, Julien Grall, Jan Beulich, xen-devel

[-- Attachment #1: Type: text/plain, Size: 3625 bytes --]

On Thu, Aug 29, 2019 at 04:16:13PM +0000, Wieczorkiewicz, Pawel wrote:
> 
> 
> On 29. Aug 2019, at 17:58, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com<mailto:konrad.wilk@oracle.com>> wrote:
> 
> +CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')
> 
> Ony my Hikey 960 when I compile using an native compiler I get:
> 
> gcc  -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O1 -fno-omit-frame-pointer -nostdinc -fno-builtin -fno-common -Werror -Wredundant-decls -Wno-pointer-arith -Wvla -pipe -D__XEN__ -include /home/xen.git/xen/include/xen/config.h '-D__OBJECT_FILE__="xen_expectations.o"' -Wa,--strip-local-absolute -g -MMD -MF ./.xen_expectations.o.d -mcpu=generic -mgeneral-regs-only   -I/home/xen.git/xen/include -fno-stack-protector -fno-exceptions -Wnested-externs -DGCC_HAS_VISIBILITY_ATTRIBUTE  -DBUILD_ID -fno-strict-aliasing -std=gnu99 -Wall -Wstrict-prototypes -Wdeclaration-after-statement -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -c xen_expectations.c -o xen_expectations.o
> /home/xen.git/xen/Rules.mk:202: recipe for target 'xen_expectations.o' failed
> make[3]: Circular expect_config.h <- xen_expectations.o dependency dropped.
> In file included from xen_expectations.c:6:0:
> expect_config.h:1:23: error: large integer implicitly truncated to unsigned type
> [-Werror=overflow]
> #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
> c09112e0}
>                       ^
> xen_expectations.c:28:17: note: in expansion of macro ‘EXPECT_BYTES’
>         .data = EXPECT_BYTES
>                 ^~~~~~~~~~~~
> expect_config.h:1:34: error: large integer implicitly truncated to unsigned type
> [-Werror=overflow]
> #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
> c09112e0}
>                                  ^
> xen_expectations.c:28:17: note: in expansion of macro ‘EXPECT_BYTES’
>         .data = EXPECT_BYTES
>                 ^~~~~~~~~~~~
> expect_config.h:1:45: error: large integer implicitly truncated to unsigned type
> [-Werror=overflow]
> #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0x
> c09112e0}
> …
> 
> make[3]: Leaving directory '/home/xen.git/xen/test/livepatch'
> Makefile:11: recipe for target 'build' failed
> make[2]: Leaving directory '/home/xen.git/xen/test'
> Makefile:85: recipe for target '_tests' failed
> make[1]: Leaving directory '/home/xen.git/xen'
> Makefile:45: recipe for target 'tests' failed
> root@hikey960:/home/xen.git/xen# cat test/livepatch/expect_config.h
> #define EXPECT_BYTES {0xf0000260,0x00f00002,0xe000f000,0x12e000f0,0x9112e000,0xc09112e0}
> #define EXPECT_BYTES_COUNT 6
> 
> 
> 
> Could you please try with the patch attached?

It compiled, but the test-case was not happy. See attached the full serial log

> 
> 
> 
> 
> 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
> 
> 


> 
> If it still fails, could you please send me the output for the following
> command with this build?
> 
> objdump -d xen-syms | sed -n -e '/<xen_extra_version>:$/,/^$/ p' | tail -n +2

Also included in the serial log.

> 
> Best Regards,
> Pawel Wieczorkiewicz
> 
> 
> 


[-- Attachment #2: livepatch-hikey960.txt --]
[-- Type: text/plain, Size: 112265 bytes --]

Loading driver at 0x000B87C8000 EntryPoint=0x000B8870370 
Using modules provided by bootloader in FDT
Xen 4.13-unstable (c/s Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty) EFI 
loader
 Xen 4.13-unstable
(XEN) Xen version 4.13-unstable (root@lan) (gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516) debug=y  Thu Aug 29 17:26:25 UTC 2019
(XEN) Latest ChangeSet: Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
(XEN) build-id: 416315091386424648bd584d25c7224ee5b5d998
(XEN) Processor: 410fd034: "ARM Limited", variant: 0x0, part 0xd03, rev 0x4
(XEN) 64-bit Execution:
(XEN)   Processor Features: 0000000000002222 0000000000000000
(XEN)     Exception Levels: EL3:64+32 EL2:64+32 EL1:64+32 EL0:64+32
(XEN)     Extensions: FloatingPoint AdvancedSIMD
(XEN)   Debug Features: 0000000010305106 0000000000000000
(XEN)   Auxiliary Features: 0000000000000000 0000000000000000
(XEN)   Memory Model Features: 0000000000001122 0000000000000000
(XEN)   ISA Features:  0000000000011120 0000000000000000
(XEN) 32-bit Execution:
(XEN)   Processor Features: 00000131:00011011
(XEN)     Instruction Sets: AArch32 A32 Thumb Thumb-2 Jazelle
(XEN)     Extensions: GenericTimer Security
(XEN)   Debug Features: 03010066
(XEN)   Auxiliary Features: 00000000
(XEN)   Memory Model Features: 10201105 40000000 01260000 02102211
(XEN)  ISA Features: 02101110 13112111 21232042 01112131 00011142 00011121
(XEN) Using SMC Calling Convention v1.0
(XEN) Using PSCI v1.0
(XEN) SMP: Allowing 8 CPUs
(XEN) Generic Timer IRQ: phys=30 hyp=26 virt=27 Freq: 1920 KHz
(XEN) GICv2 initialization:
(XEN)         gic_dist_addr=00000000e82b1000
(XEN)         gic_cpu_addr=00000000e82b2000
(XEN)         gic_hyp_addr=00000000e82b4000
(XEN)         gic_vcpu_addr=00000000e82b6000
(XEN)         gic_maintenance_irq=25
(XEN) Using the new VGIC implementation.
(XEN) GICv2: 384 lines, 8 cpus, secure (IID 0200143b).
(XEN) Using scheduler: SMP Credit Scheduler rev2 (credit2)
(XEN) Initializing Credit2 scheduler
(XEN)  load_precision_shift: 18
(XEN)  load_window_shift: 30
(XEN)  underload_balance_tolerance: 0
(XEN)  overload_balance_tolerance: -3
(XEN)  runqueues arrangement: socket
(XEN)  cap enforcement granularity: 10ms
(XEN) load tracking window length 1073741824 ns
(XEN) Adding cpu 0 to runqueue 0
(XEN)  First cpu on runqueue, activating
(XEN) Allocated console ring of 64 KiB.
(XEN) CPU0: Guest atomics will try 1 times before pausing the domain
(XEN) Bringing up CPU1
(XEN) Adding cpu 1 to runqueue 0
(XEN) CPU1: Guest atomics will try 1 times before pausing the domain
(XEN) CPU 1 booted.
(XEN) Bringing up CPU2
(XEN) Adding cpu 2 to runqueue 0
(XEN) CPU2: Guest atomics will try 20 times before pausing the domain
(XEN) CPU 2 booted.
(XEN) Bringing up CPU3
(XEN) Adding cpu 3 to runqueue 0
(XEN) CPU3: Guest atomics will try 20 times before pausing the domain
(XEN) CPU 3 booted.
(XEN) Bringing up CPU4
(XEN) Adding cpu 4 to runqueue 0
(XEN) CPU4: Guest atomics will try 8 times before pausing the domain
(XEN) CPU 4 booted.
(XEN) Bringing up CPU5
(XEN) Adding cpu 5 to runqueue 0
(XEN) CPU5: Guest atomics will try 18 times before pausing the domain
(XEN) CPU 5 booted.
(XEN) Bringing up CPU6
(XEN) Adding cpu 6 to runqueue 0
(XEN) CPU6: Guest atomics will try 15 times before pausing the domain
(XEN) CPU 6 booted.
(XEN) Bringing up CPU7
(XEN) Adding cpu 7 to runqueue 0
(XEN) CPU7: Guest atomics will try 18 times before pausing the domain
(XEN) CPU 7 booted.
(XEN) Brought up 8 CPUs
(XEN) P2M: 40-bit IPA with 40-bit PA and 8-bit VMID
(XEN) P2M: 3 levels with order-1 root, VTCR 0x80023558
(XEN) I/O virtualisation disabled
(XEN) alternatives: Patching with alt table 00000000002b3e00 -> 00000000002b4424
(XEN) *** LOADING DOMAIN 0 ***
(XEN) Loading d0 kernel from boot module @ 00000000b88f1000
(XEN) Allocating 1:1 mappings totalling 1500MB for dom0:
(XEN) BANK[0] 0x00000008000000-0x00000018000000 (256MB)
(XEN) BANK[1] 0x00000020000000-0x00000030000000 (256MB)
(XEN) BANK[2] 0x00000040000000-0x00000058000000 (384MB)
(XEN) BANK[3] 0x00000090000000-0x000000b4000000 (576MB)
(XEN) BANK[4] 0x000000ba800000-0x000000bc000000 (24MB)
(XEN) BANK[5] 0x000000bf800000-0x000000bfc00000 (4MB)
(XEN) Grant table range: 0x000000b87c8000-0x000000b8808000
(XEN) Allocating PPI 16 for event channel interrupt
(XEN) Loading zImage from 00000000b88f1000 to 0000000008080000-000000000903ca00
(XEN) Loading dom0 DTB to 0x0000000010000000-0x00000000100082a1
(XEN) Initial low memory virq threshold set at 0x4000 pages.
(XEN) Scrubbing Free RAM in background
(XEN) Std. Loglevel: All
(XEN) Guest Loglevel: All
(XEN) ***************************************************
(XEN) WARNING: HMP COMPUTING HAS BEEN ENABLED.
(XEN) It has implications on the security and stability of the system,
(XEN) unless the cpu affinity of all domains is specified.
(XEN) ***************************************************
(XEN) WARNING: SILO mode is not enabled.
(XEN) It has implications on the security of the system,
(XEN) unless the communications have been forbidden between
(XEN) untrusted domains.
(XEN) ***************************************************
(XEN) No support for ARM_SMCCC_ARCH_WORKAROUND_1.
(XEN) Please update your firmware.
(XEN) ***************************************************
(XEN) No support for ARM_SMCCC_ARCH_WORKAROUND_1.
(XEN) Please update your firmware.
(XEN) ***************************************************
(XEN) 3... 2... 1... 
(XEN) *** Serial input to DOM0 (type 'CTRL-a' three times to switch input)
(XEN) Freed 340kB init memory.
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.12.0-linaro-hikey960+ (konrad@localhost.localdomain) (gcc version 7.0.1 20170309 (Red Hat Cross 7.0.1-0.4) (GCC) ) #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
[    0.000000] Boot CPU: AArch64 Processor [410fd034]
[    0.000000] Machine model: HiKey960
[    0.000000] Xen 4.13 support found
[    0.000000] efi: Getting EFI parameters from FDT:
[    0.000000] efi: UEFI not found.
[    0.000000] cma: Reserved 16 MiB at 0x00000000bb000000
[    0.000000] NUMA: No NUMA configuration found
[    0.000000] NUMA: Faking a node at [mem 0x0000000000000000-0x00000000bfbfffff]
[    0.000000] NUMA: Adding memblock [0x8000000 - 0x17ffffff] on node 0
[    0.000000] NUMA: Adding memblock [0x20000000 - 0x2fffffff] on node 0
[    0.000000] NUMA: Adding memblock [0x32000000 - 0x320fffff] on node 0
[    0.000000] NUMA: Adding memblock [0x40000000 - 0x57ffffff] on node 0
[    0.000000] NUMA: Adding memblock [0x90000000 - 0xb3ffffff] on node 0
[    0.000000] NUMA: Adding memblock [0xba800000 - 0xbbffffff] on node 0
[    0.000000] NUMA: Adding memblock [0xbf800000 - 0xbfbfffff] on node 0
[    0.000000] NUMA: Initmem setup node 0 [mem 0x08000000-0xbfbfffff]
[    0.000000] NUMA: NODE_DATA [mem 0xbfbc2f80-0xbfbc4a7f]
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000008000000-0x00000000bfbfffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000008000000-0x0000000017ffffff]
[    0.000000]   node   0: [mem 0x0000000020000000-0x000000002fffffff]
[    0.000000]   node   0: [mem 0x0000000032000000-0x00000000320fffff]
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000057ffffff]
[    0.000000]   node   0: [mem 0x0000000090000000-0x00000000b3ffffff]
[    0.000000]   node   0: [mem 0x00000000ba800000-0x00000000bbffffff]
[    0.000000]   node   0: [mem 0x00000000bf800000-0x00000000bfbfffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000008000000-0x00000000bfbfffff]
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.1 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: Trusted OS migration not required
[    0.000000] percpu: Embedded 22 pages/cpu @ffff8000bfb0f000 s59160 r0 d30952 u90112
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: enabling workaround for ARM erratum 845719
[    0.000000] Built 1 zonelists in Node order, mobility grouping on.  Total pages: 378252
[    0.000000] Policy zone: DMA
[    0.000000] Kernel command line: console=tty0 console=hvc0 root=/dev/sdd10 rw efi=noruntime
[    0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Memory: 1452892K/1537024K available (10172K kernel code, 1138K rwdata, 3648K rodata, 1088K init, 406K bss, 67748K reserved, 16384K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     modules : 0xffff000000000000 - 0xffff000008000000   (   128 MB)
[    0.000000]     vmalloc : 0xffff000008000000 - 0xffff7dffbfff0000   (129022 GB)
[    0.000000]       .text : 0xffff000008080000 - 0xffff000008a70000   ( 10176 KB)
[    0.000000]     .rodata : 0xffff000008a70000 - 0xffff000008e10000   (  3712 KB)
[    0.000000]       .init : 0xffff000008e10000 - 0xffff000008f20000   (  1088 KB)
[    0.000000]       .data : 0xffff000008f20000 - 0xffff00000903ca00   (  1139 KB)
[    0.000000]        .bss : 0xffff00000903ca00 - 0xffff0000090a2334   (   407 KB)
[    0.000000]     fixed   : 0xffff7dfffe7fd000 - 0xffff7dfffec00000   (  4108 KB)
[    0.000000]     PCI I/O : 0xffff7dfffee00000 - 0xffff7dffffe00000   (    16 MB)
[    0.000000]     vmemmap : 0xffff7e0000000000 - 0xffff800000000000   (  2048 GB maximum)
[    0.000000]               0xffff7e0000200000 - 0xffff7e0002ff0000   (    45 MB actual)
[    0.000000]     memory  : 0xffff800008000000 - 0xffff8000bfc00000   (  2940 MB)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
[    0.000000] Preemptible hierarchical RCU implementation.
[    0.000000] 	RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=8.
[    0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=8
[    0.000000] NR_IRQS:64 nr_irqs:64 0
[    0.000000] arch_timer: cp15 timer(s) running at 1.92MHz (virt).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x1c570327e, max_idle_ns: 1763180809505 ns
[    0.000004] sched_clock: 56 bits at 1920kHz, resolution 520ns, wraps every 4398046510977ns
[    0.000091] clocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 58334160866034 ns
[    0.000424] Console: colour dummy device 80x25
[    0.000945] console [tty0] enabled
[    0.430141] console [hvc0] enabled
[    0.433672] Calibrating delay loop (skipped), value calculated using timer frequency.. 3.84 BogoMIPS (lpj=7680)
[    0.443777] pid_max: default: 32768 minimum: 301
[    0.448502] Security Framework initialized
[    0.452910] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes)
[    0.460951] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes)
[    0.468350] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes)
[    0.474959] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes)
[    0.498249] ASID allocator initialised with 65536 entries
[    0.504028] xen:grant_table: Grant tables using version 1 layout
[    0.509966] Grant table initialized
[    0.513518] xen:events: Using FIFO-based ABI
[    0.517886] Xen: initializing cpu0
[    0.534476] EFI services will not be available.
[    0.554967] smp: Bringing up secondary CPUs ...
[    0.591579] Detected VIPT I-cache on CPU1
[    0.591662] Xen: initializing cpu1
[    0.591682] CPU1: Booted secondary processor [410fd034]
[    0.623642] Detected VIPT I-cache on CPU2
[    0.623686] Xen: initializing cpu2
[    0.623701] CPU2: Booted secondary processor [410fd034]
[    0.655720] Detected VIPT I-cache on CPU3
[    0.655763] Xen: initializing cpu3
[    0.655776] CPU3: Booted secondary processor [410fd034]
[    0.687814] CPU features: enabling workaround for ARM erratum 858921
[    0.687819] Detected VIPT I-cache on CPU4
[    0.688442] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.688453] arch_timer: CPU4: Trapping CNTVCT access
[    0.688455] Xen: initializing cpu4
[    0.688472] CPU4: Booted secondary processor [410fd091]
[    0.719896] Detected VIPT I-cache on CPU5
[    0.719930] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.719938] arch_timer: CPU5: Trapping CNTVCT access
[    0.719940] Xen: initializing cpu5
[    0.719953] CPU5: Booted secondary processor [410fd091]
[    0.751987] Detected VIPT I-cache on CPU6
[    0.752021] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.752028] arch_timer: CPU6: Trapping CNTVCT access
[    0.752030] Xen: initializing cpu6
[    0.752043] CPU6: Booted secondary processor [410fd091]
[    0.784077] Detected VIPT I-cache on CPU7
[    0.784110] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.784117] arch_timer: CPU7: Trapping CNTVCT access
[    0.784119] Xen: initializing cpu7
[    0.784132] CPU7: Booted secondary processor [410fd091]
[    0.784193] smp: Brought up 1 node, 8 CPUs
[    0.931646] SMP: Total of 8 processors activated.
[    0.936412] CPU features: detected feature: 32-bit EL0 Support
[    0.943431] CPU: All CPU(s) started at EL1
[    0.947489] alternatives: patching kernel code
[    0.952658] devtmpfs: initialized
[    0.958766] OF: Duplicate name in base, renamed to "memory#1"
[    0.964939] DMI not present or invalid.
[    0.968911] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.978614] futex hash table entries: 2048 (order: 6, 262144 bytes)
[    0.985417] pinctrl core: initialized pinctrl subsystem
[    0.991927] NET: Registered protocol family 16
[    0.998299] vdso: 2 pages (1 code @ ffff000008a77000, 1 data @ ffff000008f25000)
[    1.005649] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    1.020741] DMA: preallocated 256 KiB pool for atomic allocations
[    1.026844] xen:swiotlb_xen: Warning: only able to allocate 4 MB for software IO TLB
[    1.035003] software IO TLB [mem 0xb0400000-0xb0800000] (4MB) mapped at [ffff8000b0400000-ffff8000b07fffff]
[    1.045001] Serial: AMBA PL011 UART driver
[    1.068164] hi3660-mbox e896b000.mailbox: Mailbox enabled
[    1.083003] uart-pl011 ffd74000.serial: could not find pctldev for node /soc/pinmux@e896c000/uart3_pmx_func, deferring probe
[    1.094290] uart-pl011 fdf01000.serial: could not find pctldev for node /soc/pinmux@e896c000/uart4_pmx_func, deferring probe
[    1.126144] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[    1.133629] ACPI: Interpreter disabled.
[    1.137884] xen:balloon: Initialising balloon driver
[    1.143231] xen_balloon: Initialising balloon driver
[    1.148775] vgaarb: loaded
[    1.151585] SCSI subsystem initialized
[    1.155543] ssp-pl022 ffd68000.spi: could not find pctldev for node /soc/pinmux@fff11000/spi2_pmx_func, deferring probe
[    1.166275] ssp-pl022 ff3b3000.spi: could not find pctldev for node /soc/pinmux@ff3b6000/spi3_pmx_func, deferring probe
[    1.177268] usbcore: registered new interface driver usbfs
[    1.182711] usbcore: registered new interface driver hub
[    1.188164] usbcore: registered new device driver usb
[    1.193168] tcpc_class_init_1.1.1_G
[    1.196712] TCPC class init OK
[    1.199844] Init Richtek RegMap
[    1.203194] i2c_designware ffd71000.i2c: could not find pctldev for node /soc/pinmux@fff11000/i2c0_pmx_func, deferring probe
[    1.214341] i2c_designware ffd72000.i2c: could not find pctldev for node /soc/pinmux@fff11000/i2c1_pmx_func, deferring probe
[    1.225618] i2c_designware fdf0b000.i2c: could not find pctldev for node /soc/pinmux@fff11000/i2c7_pmx_func, deferring probe
[    1.237265] pps_core: LinuxPPS API ver. 1 registered
[    1.242148] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    1.251351] PTP clock support registered
[    1.255440] dmi: Firmware registration failed.
[    1.260092] Advanced Linux Sound Architecture Driver Initialized.
[    1.267157] clocksource: Switched to clocksource arch_sys_counter
[    1.273352] VFS: Disk quotas dquot_6.6.0
[    1.277232] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    1.284299] pnp: PnP ACPI: disabled
[    1.293729] OF: /soc/thermal-zones/cls0/cooling-maps/map0: could not find phandle
[    1.301152] missing cooling_device property
[    1.305391] failed to build thermal zone cls0: -22
[    1.310340] NET: Registered protocol family 2
[    1.315025] TCP established hash table entries: 16384 (order: 5, 131072 bytes)
[    1.322259] TCP bind hash table entries: 16384 (order: 6, 262144 bytes)
[    1.329026] TCP: Hash tables configured (established 16384 bind 16384)
[    1.335578] UDP hash table entries: 1024 (order: 3, 32768 bytes)
[    1.341572] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes)
[    1.348194] NET: Registered protocol family 1
[    1.352873] RPC: Registered named UNIX socket transport module.
[    1.358704] RPC: Registered udp transport module.
[    1.363480] RPC: Registered tcp transport module.
[    1.368240] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.375629] kvm [1]: HYP mode not available
[    1.382109] audit: initializing netlink subsys (disabled)
[    1.387562] audit: type=2000 audit(1.084:1): state=initialized audit_enabled=0 res=1
[    1.387744] workingset: timestamp_bits=44 max_order=19 bucket_order=0
[    1.392019] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    1.392455] NFS: Registering the id_resolver key type
[    1.392482] Key type id_resolver registered
[    1.392483] Key type id_legacy registered
[    1.392490] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
[    1.392493] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
[    1.392626] 9p: Installing v9fs 9p2000 file system support
[    1.395236] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 247)
[    1.395241] io scheduler noop registered
[    1.395337] io scheduler cfq registered (default)
[    1.395340] io scheduler mq-deadline registered
[    1.395341] io scheduler kyber registered
[    1.403061] pinctrl-single e896c000.pinmux: 124 pins at pa ffff0000094d7000 size 496
[    1.403139] pinctrl-single ff37e000.pinmux: 6 pins at pa ffff0000094d9000 size 24
[    1.403195] pinctrl-single ff3b6000.pinmux: 12 pins at pa ffff0000094db000 size 48
[    1.403236] pinctrl-single ff3fd000.pinmux: 6 pins at pa ffff0000094dd000 size 24
[    1.403310] pinctrl-single fff11000.pinmux: 42 pins at pa ffff0000094df000 size 168
[    1.403433] pinctrl-single e896c800.pinmux: 128 pins at pa ffff0000094e1800 size 512
[    1.403473] pinctrl-single ff3b6800.pinmux: 6 pins at pa ffff0000094e3800 size 24
[    1.403512] pinctrl-single ff3fd800.pinmux: 6 pins at pa ffff0000094e5800 size 24
[    1.403561] pinctrl-single ff37e800.pinmux: 6 pins at pa ffff0000094e7800 size 24
[    1.403624] pinctrl-single fff11800.pinmux: 47 pins at pa ffff0000094e9800 size 188
[    1.404471] pl061_gpio e8a0b000.gpio: PL061 GPIO chip @0x00000000e8a0b000 registered
[    1.404653] pl061_gpio e8a0c000.gpio: PL061 GPIO chip @0x00000000e8a0c000 registered
[    1.404837] pl061_gpio e8a0d000.gpio: PL061 GPIO chip @0x00000000e8a0d000 registered
[    1.405009] pl061_gpio e8a0e000.gpio: PL061 GPIO chip @0x00000000e8a0e000 registered
[    1.405177] pl061_gpio e8a0f000.gpio: PL061 GPIO chip @0x00000000e8a0f000 registered
[    1.405350] pl061_gpio e8a10000.gpio: PL061 GPIO chip @0x00000000e8a10000 registered
[    1.405521] pl061_gpio e8a11000.gpio: PL061 GPIO chip @0x00000000e8a11000 registered
[    1.405690] pl061_gpio e8a12000.gpio: PL061 GPIO chip @0x00000000e8a12000 registered
[    1.405857] pl061_gpio e8a13000.gpio: PL061 GPIO chip @0x00000000e8a13000 registered
[    1.406028] pl061_gpio e8a14000.gpio: PL061 GPIO chip @0x00000000e8a14000 registered
[    1.406209] pl061_gpio e8a15000.gpio: PL061 GPIO chip @0x00000000e8a15000 registered
[    1.406378] pl061_gpio e8a16000.gpio: PL061 GPIO chip @0x00000000e8a16000 registered
[    1.406550] pl061_gpio e8a17000.gpio: PL061 GPIO chip @0x00000000e8a17000 registered
[    1.406723] pl061_gpio e8a18000.gpio: PL061 GPIO chip @0x00000000e8a18000 registered
[    1.406894] pl061_gpio e8a19000.gpio: PL061 GPIO chip @0x00000000e8a19000 registered
[    1.407068] pl061_gpio e8a1a000.gpio: PL061 GPIO chip @0x00000000e8a1a000 registered
[    1.407246] pl061_gpio e8a1b000.gpio: PL061 GPIO chip @0x00000000e8a1b000 registered
[    1.407419] pl061_gpio e8a1c000.gpio: PL061 GPIO chip @0x00000000e8a1c000 registered
[    1.407605] pl061_gpio ff3b4000.gpio: PL061 GPIO chip @0x00000000ff3b4000 registered
[    1.407777] pl061_gpio ff3b5000.gpio: PL061 GPIO chip @0x00000000ff3b5000 registered
[    1.407949] pl061_gpio e8a1f000.gpio: PL061 GPIO chip @0x00000000e8a1f000 registered
[    1.408120] pl061_gpio e8a20000.gpio: PL061 GPIO chip @0x00000000e8a20000 registered
[    1.408299] pl061_gpio fff0b000.gpio: PL061 GPIO chip @0x00000000fff0b000 registered
[    1.408473] pl061_gpio fff0c000.gpio: PL061 GPIO chip @0x00000000fff0c000 registered
[    1.408654] pl061_gpio fff0d000.gpio: PL061 GPIO chip @0x00000000fff0d000 registered
[    1.408842] pl061_gpio fff0e000.gpio: PL061 GPIO chip @0x00000000fff0e000 registered
[    1.409017] pl061_gpio fff0f000.gpio: PL061 GPIO chip @0x00000000fff0f000 registered
[    1.409197] pl061_gpio fff10000.gpio: PL061 GPIO chip @0x00000000fff10000 registered
[    1.409372] pl061_gpio fff1d000.gpio: PL061 GPIO chip @0x00000000fff1d000 registered
[    1.412294] xen:xen_evtchn: Event-channel device installed
[    1.416016] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    1.417008] SuperH (H)SCI(F) driver initialized
[    1.417167] msm_serial: driver initialized
[    1.421092] cacheinfo: Unable to detect cache hierarchy for CPU 0
[    1.424895] loop: module loaded
[    1.425090] [I/GPIO_HUB] gpio_hub_init:gpio hub init status:0
[    1.426329] ufshcd-hi3660 ff3b0000.ufs: ufshcd_populate_vreg: Unable to find vdd-hba-supply regulator, assuming enabled
[    1.426333] ufshcd-hi3660 ff3b0000.ufs: ufshcd_populate_vreg: Unable to find vcc-supply regulator, assuming enabled
[    1.426336] ufshcd-hi3660 ff3b0000.ufs: ufshcd_populate_vreg: Unable to find vccq-supply regulator, assuming enabled
[    1.426340] ufshcd-hi3660 ff3b0000.ufs: ufshcd_populate_vreg: Unable to find vccq2-supply regulator, assuming enabled
[    1.448657] scsi host0: ufshcd
[    1.463331] hisi_sas: driver version v1.6
[    1.464937] libphy: Fixed MDIO Bus: probed
[    1.465193] tun: Universal TUN/TAP device driver, 1.6
[    1.465844] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k
[    1.465845] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
[    1.465870] igb: Intel(R) Gigabit Ethernet Network Driver - version 5.4.0-k
[    1.465871] igb: Copyright (c) 2007-2014 Intel Corporation.
[    1.465895] igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.4.0-k
[    1.465896] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
[    1.466066] sky2: driver version 1.30
[    1.466317] xen_netfront: Initialising Xen virtual ethernet driver
[    1.466359] usbcore: registered new interface driver asix
[    1.466380] usbcore: registered new interface driver ax88179_178a
[    1.466538] VFIO - User Level meta-driver version: 0.3
[    1.467009] [USB3][hisi_dwc3_probe]+
[    1.467090] [USB3][get_phy_param]eye diagram param: 0x1c466e3
[    1.467093] [USB3][get_phy_param]eye diagram host param: 0x1c466e3
[    1.467095] [USB3][get_phy_param]usb3_phy_cr_param: 0xb80
[    1.467097] [USB3][get_phy_param]usb3_phy_host_cr_param: 0x980
[    1.467100] [USB3][get_phy_param]usb3_phy_tx_vboost_lvl: 5
[    1.467120] [USB3][get_resource]this is asic platform (fpga flag 0)
[    1.467121] [USB3][create_attr_file]+
[    1.467206] [USB3][create_attr_file]-
[    1.467210] [USB3][hi3660_usb3phy_init]+
[    1.495310] [USB3][config_femtophy_param]set hs phy param 0x1c466e3 for device
[    1.495861] [USB3][config_femtophy_param]set ss phy rx equalization 0xb80
[    1.496895] [USB3][config_femtophy_param]set ss RX_SCOPE_VDCC 0x1
[    1.496898] [USB3][config_femtophy_param]set ss phy tx vboost lvl 0x5
[    1.496902] [USB3][set_hisi_dwc3_power_flag]set hisi_dwc3_power_flag 1
[    1.496903] [USB3][hi3660_usb3phy_init]-
[    1.497967] [dwc3_otg_init]+
[    1.497971] DWC3_OCFG:	0x0
[    1.497972] DWC3_OCTL:	0x40
[    1.497974] DWC3_OEVT:	0x80000000
[    1.497975] DWC3_OEVTEN:	0x0
[    1.497976] DWC3_OSTS:	0x19
[    1.497978] DWC3_BCFG:	0x0
[    1.497979] DWC3_BCEVT:	0x0
[    1.497980] DWC3_BCEVTEN:	0x0
[    1.497981] [dwc3_otg_init]-
[    1.498003] dwc3 ff100000.dwc3: dwc3_host_init if otg, otg will do device_add.
[    1.499800] [USB3][hisi_dwc3_wake_lock]usb otg wake lock
[    1.499807] [USB3][hisi_dwc3_probe]init state: OFF
[    1.499810] [USB3][hisi_usb_otg_event]hisi_usb_otg_event in:1
[    1.499812] [USB3][hisi_usb_otg_event]hisi_usb_otg_event in otg:1
[    1.499814] [USB3][hisi_usb_otg_event]event: 1
[    1.499823] [USB3][event_work]+
[    1.499826] [USB3][handle_event][handle_event] type: 1
[    1.499831] [USB3][handle_event]cancel bc_again_work sync:0
[    1.499834] [dwc3_otg_work]+
[    1.499834]  evt = 4
[    1.499837] [dwc3_otg_stop_peripheral]+
[    1.499838] [dwc3_otg_stop_peripheral]-
[    1.499839] [dwc3_otg_work]-
[    1.499841] [USB3][hisi_dwc3_wake_unlock]usb otg wake unlock
[    1.499845] [USB3][handle_event]hisi usb status: DEVICE -> OFF
[    1.499846] [USB3][event_work]-
[    1.499851] [USB3][hisi_dwc3_probe]-
[    1.500311] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    1.500314] ehci-pci: EHCI PCI platform driver
[    1.500339] ehci-platform: EHCI generic platform driver
[    1.500408] ehci-orion: EHCI orion driver
[    1.500461] ehci-exynos: EHCI EXYNOS driver
[    1.500515] ehci-msm: Qualcomm On-Chip EHCI Host Controller
[    1.500561] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    1.500571] ohci-pci: OHCI PCI platform driver
[    1.500597] ohci-platform: OHCI generic platform driver
[    1.500655] ohci-exynos: OHCI EXYNOS driver
[    1.500914] usbcore: registered new interface driver usb-storage
[    1.501365] [I/hisi_pd] pd_dpm_init
[    1.501429] [I/hisi_pd] pd_dpm_probe : +++++++++
[    1.501472] [I/hisi_pd] pd_dpm_probe ++++
[    1.501472] 
[    1.501665] rt1711h_init (1.1.8_G): initializing...
[    1.501676] rt1711h node found...
[    1.502348] rtc-pl031 fff04000.rtc: rtc core: registered pl031 as rtc0
[    1.502711] i2c /dev entries driver
[    1.504014] hi3660_thermal fff30000.tsensor: failed to register thermal sensor0: -19
[    1.504022] hi3660_thermal fff30000.tsensor: failed to register thermal sensor1: -19
[    1.504029] hi3660_thermal fff30000.tsensor: failed to register thermal sensor2: -19
[    1.504035] hi3660_thermal fff30000.tsensor: failed to register thermal sensor3: -19
[    1.504043] hi3660_thermal fff30000.tsensor: failed to register thermal sensor4: -517
[    1.504050] hi3660_thermal fff30000.tsensor: failed to register thermal sensor5: -19
[    1.504052] hi3660_thermal fff30000.tsensor: Thermal Sensor Loaded
[    1.504663] cpu cpu0: failed to get clock: -2
[    1.504674] cpufreq-dt: probe of cpufreq-dt failed with error -2
[    1.504883] sdhci: Secure Digital Host Controller Interface driver
[    1.504884] sdhci: Copyright(c) Pierre Ossman
[    1.505070] Synopsys Designware Multimedia Card Interface Driver
[    1.505467] dwmmc_k3 ff37f000.dwmmc1: fifo-depth property not found, using value of FIFOTH register as default
[    1.507636] dwmmc_k3 ff37f000.dwmmc1: IDMAC supports 64-bit address mode.
[    1.507808] dwmmc_k3 ff37f000.dwmmc1: Using internal DMA controller.
[    1.507815] dwmmc_k3 ff37f000.dwmmc1: Version ID is 270a
[    1.507881] dwmmc_k3 ff37f000.dwmmc1: DW MMC controller at irq 46,32 bit host data width,256 deep fifo
[    1.508052] dwmmc_k3 ff37f000.dwmmc1: Got CD GPIO
[    1.529636] mmc_host mmc0: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
[    1.547340] dwmmc_k3 ff37f000.dwmmc1: 1 slots initialized
[    1.547557] dwmmc_k3 ff3ff000.dwmmc2: fifo-depth property not found, using value of FIFOTH register as default
[    1.549710] dwmmc_k3 ff3ff000.dwmmc2: IDMAC supports 64-bit address mode.
[    1.549900] dwmmc_k3 ff3ff000.dwmmc2: Using internal DMA controller.
[    1.549906] dwmmc_k3 ff3ff000.dwmmc2: Version ID is 270a
[    1.549955] dwmmc_k3 ff3ff000.dwmmc2: DW MMC controller at irq 47,32 bit host data width,256 deep fifo
[    1.550486] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.558007] ledtrig-cpu: registered to indicate activity on CPUs
[    1.558668] usbcore: registered new interface driver usbhid
[    1.558669] usbhid: USB HID core driver
[    1.560131] NET: Registered protocol family 17
[    1.560222] 9pnet: Installing 9P2000 support
[    1.560269] Key type dns_resolver registered
[    1.560791] registered taskstats version 1
[    1.567071] ffd74000.serial: ttyAMA3 at MMIO 0xffd74000 (irq = 12, base_baud = 0) is a PL011 rev2
[    1.569673] fdf01000.serial: ttyAMA4 at MMIO 0xfdf01000 (irq = 13, base_baud = 0) is a PL011 rev2
[    1.569758] serial serial0: tty port ttyAMA4 registered
[    1.570128] ssp-pl022 ffd68000.spi: ARM PL022 driver, device ID: 0x00041022
[    1.570166] ssp-pl022 ffd68000.spi: mapped registers from 0x00000000ffd68000 to ffff0000095ee000
[    1.578995] ssp-pl022 ffd68000.spi: Failed to work in dma mode, work without dma!
[    1.579239] ssp-pl022 ff3b3000.spi: ARM PL022 driver, device ID: 0x00041022
[    1.579268] ssp-pl022 ff3b3000.spi: mapped registers from 0x00000000ff3b3000 to ffff0000095f0000
[    1.579301] ssp-pl022 ff3b3000.spi: Failed to work in dma mode, work without dma!
[    1.631197] rt1711_i2c_probe
[    1.631200] I2C functionality : OK...
[    1.722701] ufshcd-hi3660 ff3b0000.ufs: ufshcd_print_pwr_info:[RX, TX]: gear=[1, 1], lane[1, 1], pwr[SLOWAUTO_MODE, SLOWAUTO_MODE], rate = 0
[    1.754676] rt_parse_dt
[    1.754687] rt1711h_chipID = 0x2171
[    1.754695] regmap_device_register: name = rt1711-4e
[    1.754718]  rt_regmap_rt1711-4e: rt register cache data init
[    1.754724]  rt_regmap_rt1711-4e: cache cata init successfully
[    1.754797] tcpc_device_register register tcpc device (type_c_port0)
[    1.754861] [I/hisi_pd] tcpc_device_register register_pd_wake_unlock_notifier OK
[    1.754863] PD Timer number = 37
[    1.754942] tcpci_timer_init : init OK
[    1.755009] pd_parse_pdata
[    1.755017] pd_parse_pdata src pdo data =
[    1.755019] pd_parse_pdata 0: 0x00019064
[    1.755020] pd_parse_pdata snk pdo data =
[    1.755022] pd_parse_pdata 0: 0x000190c8
[    1.755023] pd_parse_pdata 1: 0x0002d0c8
[    1.755026] pd_parse_pdata id vdos data =
[    1.755027] pd_parse_pdata 0: 0xd00029cf
[    1.755028] pd_parse_pdata 1: 0x00000000
[    1.755029] pd_parse_pdata 2: 0x00010000
[    1.755031] dpm_caps: local_dr_power
[    1.755033] dpm_caps: local_dr_data
[    1.755038] dpm_caps: local_ext_power
[    1.755039] dpm_caps: local_usb_comm
[    1.755041] dpm_caps: local_usb_suspend
[    1.755042] dpm_caps: local_high_cap
[    1.755043] dpm_caps: local_give_back
[    1.755044] dpm_caps: local_no_suspend
[    1.755046] dpm_caps: local_vconn_supply
[    1.755047] dpm_caps: attemp_discover_cable_dfp
[    1.755048] dpm_caps: attemp_enter_dp_mode
[    1.755050] dpm_caps: attemp_discover_cable
[    1.755052] dpm_caps: attemp_discover_id
[    1.755053] dpm_caps: pr_reject_as_source
[    1.755054] dpm_caps: pr_reject_as_sink
[    1.755055] dpm_caps: pr_check_gp_source
[    1.755056] dpm_caps: pr_check_gp_sink
[    1.755058] dpm_caps: dr_reject_as_dfp
[    1.755059] dpm_caps: dr_reject_as_ufp
[    1.755060] dpm_caps: snk_prefer_low_voltage
[    1.755062] dpm_caps: snk_ignore_mismatch_current
[    1.755064] dpm_caps = 0xc010c10b
[    1.755066] [I/hisi_pd] PE:pd_core_init
[    1.806683] rt1711_init_alert name = type_c_port0
[    1.806684] rt1711_init_alert gpio # = 291
[    1.806706] GPIO requested...
[    1.806711] rt1711_init_alert : IRQ number = 271
[    1.806711] rt1711_init_alert : irq initialized...
[    1.806778] IRQF_NO_THREAD Test
[    2.031644] [I/hisi_pd] [TCPC-I]SkipAlert:0x20000
[    2.287025] ufs final power mode: gear = 3, lane = 1, pwr = 1, rate = 2
[    2.287031] ufshcd-hi3660 ff3b0000.ufs: set TX_EQUALIZER 3.5db
[    2.353315] [I/hisi_pd] TPC-I:typec_init: DRP
[    2.584086] ufshcd-hi3660 ff3b0000.ufs: check TX_EQUALIZER DB value lane0 = 0x1
[    2.584090] ufshcd-hi3660 ff3b0000.ufs: ufshcd_print_pwr_info:[RX, TX]: gear=[3, 3], lane[1, 1], pwr[FAST MODE, FAST MODE], rate = 2
[    2.592913] ufshcd-hi3660 ff3b0000.ufs: ufshcd_find_max_sup_active_icc_level: Regulator capability was not set, actvIccLevel=0
[    2.598707] [E/hisi_pd] typec_wait_ps_change: typec_wait_ps_change!!!+++++++++++
[    2.598709] [E/hisi_pd] typec_wait_ps_change: typec_wait_ps_change!!!-----------
[    2.598710] [E/hisi_pd] typec_unattached_power_entry:!!!+++++++++++
[    2.627703] scsi 0:0:0:49488: scsi_add_lun: correcting incorrect peripheral device type 0x0 for W-LUN 0x            c150hN
[    2.627709] scsi 0:0:0:49488: Well-known LUN    SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    2.650767] [E/hisi_pd] tcpci_disable_vbus_control: !!!++++++++
[    2.650770] [E/hisi_pd] pd_dpm_handle_pe_event:!!!,event=0,+++
[    2.650771] [E/hisi_pd] typec_unattached_power_entry:!!!-----------
[    2.650774] [E/GPIO_HUB] gpio_hub_switch_to_hub: otg_switch_gpio is err
[    2.650776] [E/GPIO_HUB] gpio_hub_change_typec_power: typec power gpio is err
[    2.650778] [E/GPIO_HUB] gpio_hub_power_on: gpio hub hub vbus set err
[    2.650782] [USB3][hisi_usb_otg_event]hisi_usb_otg_event in:1
[    2.650783] [USB3][hisi_usb_otg_event]hisi_usb_otg_event in otg:1
[    2.650785] [USB3][hisi_usb_otg_event]hisi_usb_otg_event in:2
[    2.650786] [USB3][hisi_usb_otg_event]hisi_usb_otg_event in otg:2
[    2.650788] [USB3][hisi_usb_otg_event]event: 2
[    2.650796] [I/hisi_pd] TPC-I:** Unattached.SNK
[    2.660119] [USB3][event_work]+
[    2.660121] [USB3][handle_event][handle_event] type: 2
[    2.660123] [USB3][set_vbus_power]set port power 1
[    2.660127] [dwc3_otg_work]+
[    2.660127]  evt = 2
[    2.660128] [dwc3_otg_start_host]+
[    2.660504] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[    2.660521] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1
[    2.660955] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220fe65 hci version 0x110 quirks 0x00010010
[    2.661010] xhci-hcd xhci-hcd.0.auto: irq 285, io mem 0xff100000
[    2.661448] hub 1-0:1.0: USB hub found
[    2.661466] hub 1-0:1.0: 1 port detected
[    2.661613] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller
[    2.661624] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2
[    2.661676] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[    2.661972] hub 2-0:1.0: USB hub found
[    2.661986] hub 2-0:1.0: 1 port detected
[    2.662096] [dwc3_otg_start_host]-
[    2.662097] [dwc3_otg_work]-
[    2.662101] [USB3][hisi_dwc3_wake_lock]usb otg wake lock
[    2.662105] [USB3][handle_event]hisi usb_status: OFF -> HOST
[    2.662106] [USB3][event_work]-
[    2.721402] tcpc_device_irq_enable : tcpc irq enable OK!
[    2.721404] rt1711_i2c_probe probe OK!
[    2.723130] dwmmc_k3 ff3ff000.dwmmc2: fifo-depth property not found, using value of FIFOTH register as default
[    2.725307] dwmmc_k3 ff3ff000.dwmmc2: IDMAC supports 64-bit address mode.
[    2.725439] dwmmc_k3 ff3ff000.dwmmc2: Using internal DMA controller.
[    2.725446] dwmmc_k3 ff3ff000.dwmmc2: Version ID is 270a
[    2.725490] dwmmc_k3 ff3ff000.dwmmc2: DW MMC controller at irq 47,32 bit host data width,128 deep fifo
[    2.725595] mmc_host mmc1: card is non-removable.
[    2.751421] scsi 0:0:0:49456: scsi_add_lun: correcting incorrect peripheral device type 0x0 for W-LUN 0x            c130hN
[    2.751426] scsi 0:0:0:49456: Well-known LUN    SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    2.833026] scsi 0:0:0:49476: scsi_add_lun: correcting incorrect peripheral device type 0x0 for W-LUN 0x            c144hN
[    2.833031] scsi 0:0:0:49476: Well-known LUN    SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    2.837307] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
[    2.855317] dwmmc_k3 ff3ff000.dwmmc2: 1 slots initialized
[    2.855876] input: keys as /devices/platform/keys/input/input0
[    2.861879] rtc-pl031 fff04000.rtc: setting system clock to 1970-01-01 03:30:03 UTC (12603)
[    2.879145] dwmmc_k3 ff3ff000.dwmmc2: card claims to support voltages below defined range
[    2.879155] scsi 0:0:0:0: Direct-Access     SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    2.881882] ALSA device list:
[    2.881884]   No soundcards found.
[    2.948100] scsi 0:0:0:1: Direct-Access     SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    2.974891] sd 0:0:0:0: [sda] 1024 4096-byte logical blocks: (4.19 MB/4.00 MiB)
[    2.974894] sd 0:0:0:0: [sda] 16384-byte physical blocks
[    2.974942] scsi 0:0:0:2: Direct-Access     SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    2.980630] sd 0:0:0:0: [sda] Write Protect is off
[    2.989718] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, supports DPO and FUA
[    3.004486] scsi 0:0:0:3: Direct-Access     SAMSUNG  KLUBG4G1CE-B0B1  1000 PQ: 0 ANSI: 6
[    3.013821] sd 0:0:0:1: [sdb] 1024 4096-byte logical blocks: (4.19 MB/4.00 MiB)
[    3.013825] sd 0:0:0:1: [sdb] 16384-byte physical blocks
[    3.018086] sd 0:0:0:1: [sdb] Write Protect is off
[    3.029960] sd 0:0:0:1: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA
[    3.034509] sd 0:0:0:2: [sdc] 2048 4096-byte logical blocks: (8.39 MB/8.00 MiB)
[    3.034512] sd 0:0:0:2: [sdc] 16384-byte physical blocks
[    3.039744] sd 0:0:0:2: [sdc] Write Protect is off
[    3.050072] sd 0:0:0:2: [sdc] Write cache: enabled, read cache: enabled, supports DPO and FUA
[    3.052216] mmc_host mmc1: Bus speed (slot 0) = 25000000Hz (slot req 25000000Hz, actual 25000000HZ div = 0)
[    3.053582] random: fast init done
[    3.072447] sd 0:0:0:3: [sdd] 7805952 4096-byte logical blocks: (32.0 GB/29.8 GiB)
[    3.072450] sd 0:0:0:3: [sdd] 16384-byte physical blocks
[    3.079050] sd 0:0:0:3: [sdd] Write Protect is off
[    3.082679] sd 0:0:0:3: [sdd] Write cache: enabled, read cache: enabled, supports DPO and FUA
[    3.135756] sd 0:0:0:0: [sda] Attached SCSI disk
[    3.173035] sd 0:0:0:1: [sdb] Attached SCSI disk
[    3.173065] Alternate GPT is invalid, using primary GPT.
[    3.173072]  sdc: sdc1
[    3.243944]  sdd: sdd1 sdd2 sdd3 sdd4 sdd5 sdd6 sdd7 sdd8 sdd9 sdd10 sdd11 sdd12 sdd13
[    3.258638] sd 0:0:0:2: [sdc] Attached SCSI disk
[    3.315172] sd 0:0:0:3: [sdd] Attached SCSI disk
[    3.613991] mmc1: new SDIO card at address 0001
[    3.652858] wl18xx_driver wl18xx.1.auto: Direct firmware load for ti-connectivity/wl18xx-conf.bin failed with error -2
[    3.652864] wlcore: ERROR could not get configuration binary ti-connectivity/wl18xx-conf.bin: -2
[    3.652866] wlcore: WARNING falling back to default config
[    4.210100] wlcore: wl18xx HW: 183x or 180x, PG 2.2 (ROM 0x11)
[    4.219088] wlcore: loaded
[    4.222294] EXT4-fs (sdd10): couldn't mount as ext3 due to feature incompatibilities
[    4.232524] EXT4-fs (sdd10): mounted filesystem with ordered data mode. Opts: (null)
[    4.240232] VFS: Mounted root (ext4 filesystem) on device 8:58.
[    4.246415] devtmpfs: mounted
[    4.249638] Freeing unused kernel memory: 1088K
[    4.322030] systemd[1]: System time before build time, advancing clock.

Welcome to ^[[1mDebian GNU/Linux 9 (stretch)^[[0m!

NetworkManager-wait-online.service: Cannot add dependency job, ignoring: Unit NetworkManager-wait-online.service is masked.
[^[[0;32m  OK  ^[[0m] Listening on Journal Socket (/dev/log).
[^[[0;32m  OK  ^[[0m] Created slice User and Session Slice.
[^[[0;32m  OK  ^[[0m] Started Dispatch Password Requests to Console Directory Watch.
[^[[0;32m  OK  ^[[0m] Created slice System Slice.
         Mounting Debug File System...
[^[[0;32m  OK  ^[[0m] Reached target Slices.
[^[[0;32m  OK  ^[[0m] Listening on /dev/initctl Compatibility Named Pipe.
[^[[0;32m  OK  ^[[0m] Listening on Journal Socket.
         Starting Remount Root and Kernel File Systems...
         Starting Nameserver information manager...
         Starting Set the console keyboard layout...
         Starting Load Kernel Modules...
[^[[0;32m  OK  ^[[0m] Listening on udev Kernel Socket.
[^[[0;32m  OK  ^[[0m] Created slice system-serial\x2dgetty.slice.
[^[[0;32m  OK  ^[[0m] Reached target Remote File Systems.
[^[[0;32m  OK  ^[[0m] Started Forward Password Requests to Wall Directory Watch.
[^[[0;32m  OK  ^[[0m] Reached target Encrypted Volumes.
         Starting Create Static Device Nodes in /dev...
[^[[0;32m  OK  ^[[0m] Listening on udev Control Socket.
         Mounting Huge Pages File System...
         Mounting POSIX Message Queue File System...
[^[[0;32m  OK  ^[[0m] Created slice system-getty.slice.
[^[[0;32m  OK  ^[[0m] Listening on Network Service Netlink Socket.
[^[[0;32m  OK  ^[[0m] Listening on Journal Audit Socket.
[^[[0;32m  OK  ^[[0m] Listening on Syslog Socket.
         Starting Journal Service...
[^[[0;32m  OK  ^[[0m] Mounted POSIX Message Queue File System.
[^[[0;32m  OK  ^[[0m] Mounted Debug File System.
[^[[0;32m  OK  ^[[0m] Mounted Huge Pages File System.
[^[[0;32m  OK  ^[[0m] Started Remount Root and Kernel File Systems.
[^[[0;32m  OK  ^[[0m] Started Load Kernel Modules.
[^[[0;32m  OK  ^[[0m] Started Create Static Device Nodes in /dev.
[^[[0;32m  OK  ^[[0m] Started Nameserver information manager.
[^[[0;32m  OK  ^[[0m] Started Set the console keyboard layout.
         Starting udev Kernel Device Manager...
         Starting Apply Kernel Variables...
         Mounting Configuration File System...
[^[[0;32m  OK  ^[[0m] Reached target Local File Systems (Pre).
         Starting Load/Save Random Seed...
         Starting udev Coldplug all Devices...
[^[[0;32m  OK  ^[[0m] Mounted Configuration File System.
[^[[0;32m  OK  ^[[0m] Started Journal Service.
[^[[0;32m  OK  ^[[0m] Started Apply Kernel Variables.
[^[[0;32m  OK  ^[[0m] Started Load/Save Random Seed.
[^[[0;32m  OK  ^[[0m] Started udev Kernel Device Manager.
         Starting Network Service...
         Starting Flush Journal to Persistent Storage...
[^[[0;32m  OK  ^[[0m] Started Network Service.
[    4.787441] systemd-journald[1510]: Received request to flush runtime journal from PID 1
[^[[0;32m  OK  ^[[0m] Started Flush Journal to Persistent Storage.
[^[[0;32m  OK  ^[[0m] Started udev Coldplug all Devices.
[^[[0;32m  OK  ^[[0m] Found device /dev/hvc0.
[^[[0;32m  OK  ^[[0m] Found device KLUBG4G1CE-B0B1 vendor.
[^[[0;32m  OK  ^[[0m] Found device KLUBG4G1CE-B0B1 userdata.
         Mounting /home...
         [    5.075784] EActivating swap /dev/sdd11...XT4-fs (sdd13): 
mounted filesystem with ordered data mode. Opts: (null)
[    5.086896] Adding 802812k swap on /dev/sdd11.  Priority:-1 extents:1 across:802812k SS
[^[[0;32m  OK  ^[[0m] Mounted /home.
[^[[0;32m  OK  ^[[0m] Activated swap /dev/sdd11.
[^[[0;32m  OK  ^[[0m] Reached target Swap.
[^[[0;32m  OK  ^[[0m] Reached target Local File Systems.
         Starting Raise network interfaces...
         Starting Set console font and keymap...
         Starting Create Volatile Files and Directories...
[^[[0;32m  OK  ^[[0m] Started Set console font and keymap.
[^[[0;32m  OK  ^[[0m] Started Create Volatile Files and Directories.
         Starting Network Time Synchronization...
         Starting Update UTMP about System Boot/Shutdown...
[^[[0;32m  OK  ^[[0m] Started Update UTMP about System Boot/Shutdown.
[^[[0;32m  OK  ^[[0m] Started Raise network interfaces.
[^[[0;32m  OK  ^[[0m] Started Network Time Synchronization.
[^[[0;32m  OK  ^[[0m] Reached target System Initialization.
[^[[0;32m  OK  ^[[0m] Listening on D-Bus System Message Bus Socket.
[^[[0;32m  OK  ^[[0m] Listening on OpenBSD Secure Shell server socket.
[^[[0;32m  OK  ^[[0m] Started Daily Cleanup of Temporary Directories.
[^[[0;32m  OK  ^[[0m] Listening on ACPID Listen Socket.
[^[[0;32m  OK  ^[[0m] Reached target Sockets.
[^[[0;32m  OK  ^[[0m] Started ACPI Events Check.
[^[[0;32m  OK  ^[[0m] Reached target Paths.
[^[[0;32m  OK  ^[[0m] Reached target Basic System.
         Starting Initialize hardware monitoring sensors...
[^[[0;32m  OK  ^[[0m] Started D-Bus System Message Bus.
         Starting Network Manager...
         Starting Login Service...
         Starting System Logging Service...
         Starting Modem Manager...
         Starting Restore /etc/resolv.conf i…fore the ppp link was shut down...
         Starting Provide limited super user privileges to specific users...
[^[[0;32m  OK  ^[[0m] Started Regular background program processing daemon.
         Starting RealtimeKit Scheduling Policy Service...
         Starting WPA supplicant...
         Starting LSB: Load kernel modules needed to enable cpufreq scaling...
[^[[0;32m  OK  ^[[0m] Started ACPI event daemon.
[^[[0;32m  OK  ^[[0m] Reached target System Time Synchronized.
[^[[0;32m  OK  ^[[0m] Started Daily apt download activities.
[^[[0;32m  OK  ^[[0m] Started Daily apt upgrade and clean activities.
[^[[0;32m  OK  ^[[0m] Reached target Timers.
[^[[0;32m  OK  ^[[0m] Started System Logging Service.
[^[[0;32m  OK  ^[[0m] Started Restore /etc/resolv.conf if…before the ppp link was shut down.
[^[[0;32m  OK  ^[[0m] Started Provide limited super user privileges to specific users.
[^[[0;32m  OK  ^[[0m] Started Initialize hardware monitoring sensors.
[^[[0;32m  OK  ^[[0m] Started RealtimeKit Scheduling Policy Service.
[^[[0;32m  OK  ^[[0m] Started LSB: Load kernel modules needed to enable cpufreq scaling.
[^[[0;32m  OK  ^[[0m] Started WPA supplicant.
[^[[0;32m  OK  ^[[0m] Started Network Manager.
[^[[0;32m  OK  ^[[0m] Started Login Service.
         Starting Network Manager Script Dispatcher Service...
[^[[0;32m  OK  ^[[0m] Reached target Network.
         Starting Network Name Resolution...
[^[[0;32m  OK  ^[[0m] Reached target Network is Online.
         Starting /etc/rc.local Compatibility...
         Starting LSB: Advanced IEEE 802.11 management daemon...
         Starting LSB: exim Mail Transport Agent...
         Starting Permit User Sessions...
         Starting Authorization Manager...
         Starting LSB: set CPUFreq kernel parameters...
[^[[0;32m  OK  ^[[0m] Started /etc/rc.local Compatibility.
[^[[0;32m  OK  ^[[0m] Started LSB: Advanced IEEE 802.11 management daemon.
[^[[0;32m  OK  ^[[0m] Started Permit User Sessions.
[^[[0;32m  OK  ^[[0m] Started Network Manager Script Dispatcher Service.
[^[[0;32m  OK  ^[[0m] Started Authorization Manager.
[^[[0;32m  OK  ^[[0m] Started Modem Manager.
[^[[0;32m  OK  ^[[0m] Started LSB: set CPUFreq kernel parameters.
         Starting Hostname Service...
[^[[0;32m  OK  ^[[0m] Started Getty on tty1.
[^[[0;32m  OK  ^[[0m] Started Serial Getty on hvc0.
[^[[0;32m  OK  ^[[0m] Reached target Login Prompts.
[^[[0;32m  OK  ^[[0m] Started Hostname Service.
[^[[0;32m  OK  ^[[0m] Started Network Name Resolution.
[    6.081315] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
[    6.124893] mmc_host mmc1: Bus speed (slot 0) = 25000000Hz (slot req 25000000Hz, actual 25000000HZ div = 0)
[    6.541622] wlcore: PHY firmware version: Rev 8.2.0.0.236
[    6.652461] wlcore: firmware booted (Rev 8.9.0.0.69)
[    6.675754] wlcore: down
[    6.809294] mmc_host mmc1: Bus speed (slot 0) = 400000Hz (slot req 400000Hz, actual 400000HZ div = 0)
[    6.853278] mmc_host mmc1: Bus speed (slot 0) = 25000000Hz (slot req 25000000Hz, actual 25000000HZ div = 0)
[    7.263605] wlcore: PHY firmware version: Rev 8.2.0.0.236
[    7.369249] wlcore: firmware booted (Rev 8.9.0.0.69)
[^[[0;32m  OK  ^[[0m] Started LSB: exim Mail Transport Agent.
[^[[0;32m  OK  ^[[0m] Reached target Multi-User System.
[^[[0;32m  OK  ^[[0m] Reached target Graphical Interface.
         Starting Update UTMP about System Runlevel Changes...
[^[[0;32m  OK  ^[[0m] Started Update UTMP about System Runlevel Changes.

Debian GNU/Linux 9 hikey960 hvc0

hikey960 login: root (automatic login)

Last login: Thu Aug 29 16:47:49 UTC 2019 on hvc0
Linux hikey960 4.12.0-linaro-hikey960+ #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017 aarch64

HiKey 960
root@hikey960:~# [   11.675304] wlcore: down
[   11.751925] wlan0: authenticate with 70:3a:cb:23:d7:dc
[   11.767979] wlan0: send auth to 70:3a:cb:23:d7:dc (try 1/3)
[   11.805622] wlan0: authenticated
[   11.811227] wlan0: associate with 70:3a:cb:23:d7:dc (try 1/3)
[   11.820091] wlan0: RX AssocResp from 70:3a:cb:23:d7:dc (capab=0x1011 status=0 aid=4)
[   11.840447] wlan0: associated
[   11.850740] wlcore: Association completed.

root@hikey960:~# xl info
host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : -unstable
xen_version            : 4.13-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
root@hikey960:~# ./live\apatch_test.pl
Have 37 test-cases
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch list)' .. ID                                     | status
----------------------------------------+------------
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch list)' .. ID                                     | status
----------------------------------------+------------
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : -unstable
xen_version            : 4.13-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : -unstable
xen_version            : 4.13-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch revert xen_hello_world)' ..Failed to get status of xen_hello_world.
Error 2: No such file or directory
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch load xen_hello_world.livepatch)' ..Uploading xen_hello_world.livepatch... (XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .note.gnu.build-id at 0000000000a04000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .text at 0000000000a02000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata at 0000000000a04028
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .altinstructions at 0000000000a04052
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .altinstr_replacement at 0000000000a04060
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata.str1.8 at 0000000000a04068
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata.str at 0000000000a040e8
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .bug_frames.1 at 0000000000a040fc
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.depends at 0000000000a0410c
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.xen_depends at 0000000000a04130
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.funcs at 0000000000a03000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.hooks.load at 0000000000a03068
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.hooks.unload at 0000000000a03078
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04052 (.altinstructions)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04060 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04068 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa040e8 (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa040fc (.bug_frames.1)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa0410c (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04130 (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03090 (.bss)
(XEN) livepatch_elf.c:319: livepatch: xen_hello_world: Absolute symbol: xen_hello_world_func.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa04060 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04068 (.rodata.str1.8)
(XEN) livepatch_elf.c:319: livepatch: xen_hello_world: Absolute symbol: xen_hello_world.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa02010 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: apply_hook => 0xa02010 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: revert_hook => 0xa0202c (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: hi_func => 0xa02048 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: check_fnc => 0xa0207c (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa040fc (.bug_frames.1)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: __func__.4777 => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: __func__.4781 => 0xa04030 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: hello_world_patch_this_fnc => 0xa04040 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03090 (.bss)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: cnt => 0xa03090 (.bss)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04078 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: .L2\x021 => 0xa040e8 (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: .L3\x021 => 0xa040fa (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_load_data_hi_func => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: xen_hello_world => 0xa02000 (.text)
(XEN) livepatch_elf.c:314: livepatch: xen_hello_world: Undefined symbol resolved: xen_extra_version => 0x23cd50
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_check_fnc => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_load_data_apply_hook => 0xa03070 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_revert_hook => 0xa03088 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:314: livepatch: xen_hello_world: Undefined symbol resolved: printk => 0x241e2c
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_xen_hello_world => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_hi_func => 0xa03080 (.livepatch.hooks.unload)
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.postrevert is missing
(XEN) alternatives: Patching with alt table 0000000000a04052 -> 0000000000a0405e
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol apply_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol revert_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol hi_func
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol check_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol __func__.4777
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol __func__.4781
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol hello_world_patch_this_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol cnt
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_load_data_hi_func
(XEN) livepatch.c:968: livepatch: xen_hello_world: overriding symbol xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_check_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_load_data_apply_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_revert_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_hi_func
completed(XEN) livepatch: xen_hello_world: Verifying enabled expectations for all functions

(XEN) livepatch.c:1501: livepatch: xen_hello_world: timeout is 30000000ns
Applying xen_hello_world... (XEN) livepatch.c:1609: livepatch: xen_hello_world: CPU2 - IPIing the other 7 CPUs
(XEN) livepatch: xen_hello_world: Applying 1 functions
(XEN) hi_func: Hi! (called 1 times)
(XEN) Hook executing.
(XEN) livepatch: xen_hello_world finished APPLY with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch load xen_hello_world.livepatch)' ..Uploading xen_hello_world.livepatch... failed
Error 17: File exists
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch list)' .. ID                                     | status
----------------------------------------+------------
xen_hello_world                         | APPLIED
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : Hello World
xen_version            : 4.13Hello World
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch revert xen_hello_world)' ..(XEN) livepatch.c:1501: livepatch: xen_hello_world: timeout is 30000000ns
Reverting xen_hello_world... (XEN) livepatch.c:1609: livepatch: xen_hello_world: CPU1 - IPIing the other 7 CPUs
(XEN) livepatch: xen_hello_world: Reverting
(XEN) check_fnc: Hi func called 1 times
(XEN) hi_func: Hi! (called 2 times)
(XEN) Hook unloaded.
(XEN) livepatch: xen_hello_world finished REVERT with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : -unstable
xen_version            : 4.13-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_hello_world)' ..Unloading xen_hello_world... completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_hello_world)' ..Failed to get status of xen_hello_world.
Error 2: No such file or directory
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : -unstable
xen_version            : 4.13-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch load xen_hello_world.livepatch)' ..Uploading xen_hello_world.livepatch... (XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .note.gnu.build-id at 0000000000a04000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .text at 0000000000a02000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata at 0000000000a04028
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .altinstructions at 0000000000a04052
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .altinstr_replacement at 0000000000a04060
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata.str1.8 at 0000000000a04068
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata.str at 0000000000a040e8
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .bug_frames.1 at 0000000000a040fc
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.depends at 0000000000a0410c
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.xen_depends at 0000000000a04130
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.funcs at 0000000000a03000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.hooks.load at 0000000000a03068
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.hooks.unload at 0000000000a03078
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04052 (.altinstructions)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04060 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04068 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa040e8 (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa040fc (.bug_frames.1)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa0410c (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04130 (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03090 (.bss)
(XEN) livepatch_elf.c:319: livepatch: xen_hello_world: Absolute symbol: xen_hello_world_func.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa04060 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04068 (.rodata.str1.8)
(XEN) livepatch_elf.c:319: livepatch: xen_hello_world: Absolute symbol: xen_hello_world.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa02010 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: apply_hook => 0xa02010 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: revert_hook => 0xa0202c (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: hi_func => 0xa02048 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: check_fnc => 0xa0207c (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa040fc (.bug_frames.1)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: __func__.4777 => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: __func__.4781 => 0xa04030 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: hello_world_patch_this_fnc => 0xa04040 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03090 (.bss)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: cnt => 0xa03090 (.bss)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04078 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: .L2\x021 => 0xa040e8 (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: .L3\x021 => 0xa040fa (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_load_data_hi_func => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: xen_hello_world => 0xa02000 (.text)
(XEN) livepatch_elf.c:314: livepatch: xen_hello_world: Undefined symbol resolved: xen_extra_version => 0x23cd50
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_check_fnc => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_load_data_apply_hook => 0xa03070 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_revert_hook => 0xa03088 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:314: livepatch: xen_hello_world: Undefined symbol resolved: printk => 0x241e2c
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_xen_hello_world => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_hi_func => 0xa03080 (.livepatch.hooks.unload)
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.postrevert is missing
(XEN) alternatives: Patching with alt table 0000000000a04052 -> 0000000000a0405e
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol apply_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol revert_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol hi_func
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol check_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol __func__.4777
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol __func__.4781
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol hello_world_patch_this_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol cnt
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_load_data_hi_func
(XEN) livepatch.c:968: livepatch: xen_hello_world: overriding symbol xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_check_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_load_data_apply_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_revert_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_hi_func
completed(XEN) livepatch: xen_hello_world: Verifying enabled expectations for all functions

(XEN) livepatch.c:1501: livepatch: xen_hello_world: timeout is 30000000ns
Applying xen_hello_world... (XEN) livepatch.c:1609: livepatch: xen_hello_world: CPU7 - IPIing the other 7 CPUs
(XEN) livepatch: xen_hello_world: Applying 1 functions
(XEN) hi_func: Hi! (called 1 times)
(XEN) Hook executing.
(XEN) livepatch: xen_hello_world finished APPLY with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : Hello World
xen_version            : 4.13Hello World
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch load xen_bye_world.livepatch)' ..Uploading xen_bye_world.livepatch... (XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .note.gnu.build-id at 0000000000a08000
(XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .text at 0000000000a06000
(XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .rodata at 0000000000a08028
(XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .rodata.str1.8 at 0000000000a08040
(XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .livepatch.depends at 0000000000a0804b
(XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .livepatch.xen_depends at 0000000000a0806f
(XEN) livepatch.c:379: livepatch: xen_bye_world: Loaded .livepatch.funcs at 0000000000a07000
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa08000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa06000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa08028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa08040 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa0804b (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa0806f (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved:  => 0xa07000 (.livepatch.funcs)
(XEN) livepatch_elf.c:319: livepatch: xen_bye_world: Absolute symbol: xen_bye_world_func.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: $x => 0xa06000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: $d => 0xa08040 (.rodata.str1.8)
(XEN) livepatch_elf.c:319: livepatch: xen_bye_world: Absolute symbol: xen_bye_world.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: $d => 0xa08028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: bye_world_patch_this_fnc => 0xa08028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: $d => 0xa07000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: livepatch_xen_bye_world => 0xa07000 (.livepatch.funcs)
(XEN) livepatch_elf.c:314: livepatch: xen_bye_world: Undefined symbol resolved: xen_extra_version => 0x23cd50
(XEN) livepatch_elf.c:343: livepatch: xen_bye_world: Symbol resolved: xen_bye_world => 0xa06000 (.text)
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.load is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.unload is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_bye_world: .livepatch.hooks.postrevert is missing
(XEN) livepatch.c:962: livepatch: xen_bye_world: new symbol bye_world_patch_this_fnc
(XEN) livepatch.c:962: livepatch: xen_bye_world: new symbol livepatch_xen_bye_world
(XEN) livepatch.c:968: livepatch: xen_bye_world: overriding symbol xen_bye_world
completed(XEN) livepatch: xen_bye_world: Verifying enabled expectations for all functions

(XEN) livepatch.c:1501: livepatch: xen_bye_world: timeout is 30000000ns
Applying xen_bye_world... (XEN) livepatch.c:1609: livepatch: xen_bye_world: CPU0 - IPIing the other 7 CPUs
(XEN) livepatch: xen_bye_world: Applying 1 functions
(XEN) livepatch: xen_bye_world finished APPLY with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : Bye World!
xen_version            : 4.13Bye World!
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch upload xen_replace xen_replace_world.livepatch)' ..Uploading xen_replace_world.livepatch... (XEN) livepatch.c:379: livepatch: xen_replace: Loaded .note.gnu.build-id at 0000000000a0c000
(XEN) livepatch.c:379: livepatch: xen_replace: Loaded .text at 0000000000a0a000
(XEN) livepatch.c:379: livepatch: xen_replace: Loaded .rodata at 0000000000a0c028
(XEN) livepatch.c:379: livepatch: xen_replace: Loaded .rodata.str1.8 at 0000000000a0c040
(XEN) livepatch.c:379: livepatch: xen_replace: Loaded .livepatch.depends at 0000000000a0c053
(XEN) livepatch.c:379: livepatch: xen_replace: Loaded .livepatch.xen_depends at 0000000000a0c077
(XEN) livepatch.c:379: livepatch: xen_replace: Loaded .livepatch.funcs at 0000000000a0b000
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0c000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0a000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0c028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0c040 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0c053 (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0c077 (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved:  => 0xa0b000 (.livepatch.funcs)
(XEN) livepatch_elf.c:319: livepatch: xen_replace: Absolute symbol: xen_replace_world_func.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: $x => 0xa0a000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: $d => 0xa0c040 (.rodata.str1.8)
(XEN) livepatch_elf.c:319: livepatch: xen_replace: Absolute symbol: xen_replace_world.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: $d => 0xa0c028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: xen_replace_world_name => 0xa0c028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: $d => 0xa0b000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: livepatch_xen_replace_world => 0xa0b000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_replace: Symbol resolved: xen_replace_world => 0xa0a000 (.text)
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.load is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.unload is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_replace: .livepatch.hooks.postrevert is missing
(XEN) livepatch.c:226: livepatch: xen_replace: Resolved old address xen_extra_version => 000000000023cd50
(XEN) livepatch.c:962: livepatch: xen_replace: new symbol xen_replace_world_name
(XEN) livepatch.c:962: livepatch: xen_replace: new symbol livepatch_xen_replace_world
(XEN) livepatch.c:968: livepatch: xen_replace: overriding symbol xen_replace_world
completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch replace xen_replace)' ..(XEN) livepatch.c:1501: livepatch: xen_replace: timeout is 30000000ns
Replacing all live patches with xen_replace... (XEN) livepatch.c:1609: livepatch: xen_replace: CPU7 - IPIing the other 7 CPUs
(XEN) livepatch: xen_bye_world: Reverting
(XEN) livepatch: xen_hello_world: Reverting
(XEN) check_fnc: Hi func called 1 times
(XEN) hi_func: Hi! (called 2 times)
(XEN) Hook unloaded.
(XEN) livepatch: xen_replace: Verifying enabled expectations for all functions
(XEN) livepatch: xen_replace: Applying 1 functions
(XEN) livepatch: xen_replace finished REPLACE with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : Hello Again Wor
xen_version            : 4.13Hello Again Wor
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch apply xen_hello_world)' ..(XEN) livepatch: xen_hello_world: can't revert as payload has .data. Please unload
Applying xen_hello_world... failed
Error 22: Invalid argument
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch apply xen_bye_world)' ..(XEN) livepatch: xen_bye_world: check against xen_replace build-id failed
Applying xen_bye_world... failed
Error 22: Invalid argument
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch apply xen_replace)' ..No action needed.
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch revert xen_replace)' ..(XEN) livepatch.c:1501: livepatch: xen_replace: timeout is 30000000ns
Reverting xen_replace... (XEN) livepatch.c:1609: livepatch: xen_replace: CPU7 - IPIing the other 7 CPUs
(XEN) livepatch: xen_replace: Reverting
(XEN) livepatch: xen_replace finished REVERT with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_replace)' ..Unloading xen_replace... completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_hello_world)' ..Unloading xen_hello_world... completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_bye_world)' ..Unloading xen_bye_world... completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch list)' .. ID                                     | status
----------------------------------------+------------
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 13
xen_extra              : -unstable
xen_version            : 4.13-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch load xen_nop.livepatch)' ..Uploading xen_nop.livepatch... (XEN) livepatch.c:379: livepatch: xen_nop: Loaded .note.gnu.build-id at 0000000000a03000
(XEN) livepatch.c:379: livepatch: xen_nop: Loaded .livepatch.depends at 0000000000a03024
(XEN) livepatch.c:379: livepatch: xen_nop: Loaded .livepatch.xen_depends at 0000000000a03048
(XEN) livepatch.c:379: livepatch: xen_nop: Loaded .livepatch.funcs at 0000000000a02000
(XEN) livepatch_elf.c:343: livepatch: xen_nop: Symbol resolved:  => 0xa03000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_nop: Symbol resolved:  => 0xa03024 (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_nop: Symbol resolved:  => 0xa03048 (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_nop: Symbol resolved:  => 0xa02000 (.livepatch.funcs)
(XEN) livepatch_elf.c:319: livepatch: xen_nop: Absolute symbol: xen_nop.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_nop: Symbol resolved: $d => 0xa02000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_nop: Symbol resolved: livepatch_nop => 0xa02000 (.livepatch.funcs)
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.load is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.unload is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_nop: .livepatch.hooks.postrevert is missing
(XEN) livepatch.c:962: livepatch: xen_nop: new symbol livepatch_nop
completed(XEN) livepatch: xen_nop: Verifying enabled expectations for all functions

(XEN) livepatch.c:1501: livepatch: xen_nop: timeout is 30000000ns
Applying xen_nop... (XEN) livepatch.c:1609: livepatch: xen_nop: CPU0 - IPIing the other 7 CPUs
(XEN) livepatch: xen_nop: Applying 1 functions
(XEN) livepatch: xen_nop finished APPLY with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch revert xen_nop)' ..(XEN) livepatch.c:1501: livepatch: xen_nop: timeout is 30000000ns
Reverting xen_nop... (XEN) livepatch.c:1609: livepatch: xen_nop: CPU7 - IPIing the other 7 CPUs
(XEN) livepatch: xen_nop: Reverting
(XEN) livepatch: xen_nop finished REVERT with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch apply xen_nop)' ..(XEN) livepatch: xen_nop: Verifying enabled expectations for all functions
Applying xen_nop... (XEN) livepatch.c:1501: livepatch: xen_nop: timeout is 30000000ns
(XEN) livepatch.c:1609: livepatch: xen_nop: CPU1 - IPIing the other 7 CPUs
(XEN) livepatch: xen_nop: Applying 1 functions
(XEN) livepatch: xen_nop finished APPLY with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xl info)' ..host                   : hikey960
release                : 4.12.0-linaro-hikey960+
version                : #3 SMP PREEMPT Mon Jul 17 13:26:13 EDT 2017
machine                : aarch64
nr_cpus                : 8
max_cpu_id             : 7
nr_nodes               : 1
cores_per_socket       : 1
threads_per_core       : 1
cpu_mhz                : 1.920
hw_caps                : 00000000:00000000:00000000:00000000:00000000:00000000:00000000:00000000
virt_caps              :
total_memory           : 2262
free_memory            : 713
sharing_freed_memory   : 0
sharing_used_memory    : 0
outstanding_claims     : 0
free_cpus              : 0
xen_major              : 4
xen_minor              : 4
xen_extra              : -unstable
xen_version            : 4.4-unstable
xen_caps               : xen-3.0-aarch64 xen-3.0-armv7l 
xen_scheduler          : credit2
xen_pagesize           : 4096
platform_params        : virt_start=0x200000
xen_changeset          : Thu Aug 29 15:43:23 2019 +0000 git:0a1b27af47-dirty
xen_commandline        : console=dtuart dtuart=/soc/serial@fff32000 efi=no-rs dom0_mem=1500M hmp-unsafe=true
cc_compiler            : gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
cc_compile_by          : root
cc_compile_domain      : lan
cc_compile_date        : Thu Aug 29 17:26:25 UTC 2019
build_id               : 416315091386424648bd584d25c7224ee5b5d998
xend_config_format     : 4
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_nop)' ..xen_nop is in the wrong state.
Current state: APPLIED
Expected state: CHECKED
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch revert xen_nop)' ..(XEN) livepatch.c:1501: livepatch: xen_nop: timeout is 30000000ns
Reverting xen_nop... (XEN) livepatch.c:1609: livepatch: xen_nop: CPU6 - IPIing the other 7 CPUs
(XEN) livepatch: xen_nop: Reverting
(XEN) livepatch: xen_nop finished REVERT with rc=0
completed
Executing: '(set -e;cd /root/test/livepatch;xen-livepatch unload xen_nop)' ..Unloading xen_nop... completed
Livepatch test returned 0root@hikey960:~# echo $?
0
root@hikey960:~# xl \b\b\b^[[K
root@hikey960:~# xen-livepatch load test/livepatch/xen_he\allo_world.livepatch 
Uploading test/livepatch/xen_hello_world.livepatch... (XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .note.gnu.build-id at 0000000000a04000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .text at 0000000000a02000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata at 0000000000a04028
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .altinstructions at 0000000000a04052
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .altinstr_replacement at 0000000000a04060
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata.str1.8 at 0000000000a04068
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .rodata.str at 0000000000a040e8
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .bug_frames.1 at 0000000000a040fc
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.depends at 0000000000a0410c
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.xen_depends at 0000000000a04130
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.funcs at 0000000000a03000
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.hooks.load at 0000000000a03068
(XEN) livepatch.c:379: livepatch: xen_hello_world: Loaded .livepatch.hooks.unload at 0000000000a03078
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04052 (.altinstructions)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04060 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04068 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa040e8 (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa040fc (.bug_frames.1)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa0410c (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa04130 (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved:  => 0xa03090 (.bss)
(XEN) livepatch_elf.c:319: livepatch: xen_hello_world: Absolute symbol: xen_hello_world_func.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa04060 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04068 (.rodata.str1.8)
(XEN) livepatch_elf.c:319: livepatch: xen_hello_world: Absolute symbol: xen_hello_world.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $x => 0xa02010 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: apply_hook => 0xa02010 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: revert_hook => 0xa0202c (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: hi_func => 0xa02048 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: check_fnc => 0xa0207c (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa040fc (.bug_frames.1)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: __func__.4777 => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: __func__.4781 => 0xa04030 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: hello_world_patch_this_fnc => 0xa04040 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03090 (.bss)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: cnt => 0xa03090 (.bss)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: $d => 0xa04078 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: .L2\x021 => 0xa040e8 (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: .L3\x021 => 0xa040fa (.rodata.str)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_load_data_hi_func => 0xa03068 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: xen_hello_world => 0xa02000 (.text)
(XEN) livepatch_elf.c:314: livepatch: xen_hello_world: Undefined symbol resolved: xen_extra_version => 0x23cd50
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_check_fnc => 0xa03078 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_load_data_apply_hook => 0xa03070 (.livepatch.hooks.load)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_revert_hook => 0xa03088 (.livepatch.hooks.unload)
(XEN) livepatch_elf.c:314: livepatch: xen_hello_world: Undefined symbol resolved: printk => 0x241e2c
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_xen_hello_world => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:343: livepatch: xen_hello_world: Symbol resolved: livepatch_unload_data_hi_func => 0xa03080 (.livepatch.hooks.unload)
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_hello_world: .livepatch.hooks.postrevert is missing
(XEN) alternatives: Patching with alt table 0000000000a04052 -> 0000000000a0405e
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol apply_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol revert_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol hi_func
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol check_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol __func__.4777
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol __func__.4781
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol hello_world_patch_this_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol cnt
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_load_data_hi_func
(XEN) livepatch.c:968: livepatch: xen_hello_world: overriding symbol xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_check_fnc
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_load_data_apply_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_revert_hook
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_hello_world: new symbol livepatch_unload_data_hi_func
completed
Applying xen_hello_world... (XEN) livepatch: xen_hello_world: Verifying enabled expectations for all functions
(XEN) livepatch.c:1501: livepatch: xen_hello_world: timeout is 30000000ns
(XEN) livepatch.c:1609: livepatch: xen_hello_world: CPU0 - IPIing the other 7 CPUs
(XEN) livepatch: xen_hello_world: Applying 1 functions
(XEN) hi_func: Hi! (called 1 times)
(XEN) Hook executing.
(XEN) livepatch: xen_hello_world finished APPLY with rc=0
completed
root@hikey960:~# xl debug-keys x
(XEN) 'x' pressed - Dumping all livepatch patches
(XEN) build-id: 416315091386424648bd584d25c7224ee5b5d998
(XEN)  name=xen_hello_world state=APPLIED(2) 0000000000a02000 (.data=0000000000a03000, .rodata=0000000000a04000) using 3 pages.
(XEN)     xen_extra_version patch 000000000023cd50(12) with 0000000000a02000 (16)
(XEN) build-id=da6f7f5b5de26f9f5581b0e14670d81b2ff8f6bb
(XEN) depend-on=416315091386424648bd584d25c7224ee5b5d998
(XEN) depend-on-xen=416315091386424648bd584d25c7224ee5b5d998
root@hikey960:~# ^[[A^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[K 
Uploading ./xen_expectations.livepatch... (XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .note.gnu.build-id at 0000000000a04000
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .text at 0000000000a02000
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .rodata at 0000000000a04028
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .altinstructions at 0000000000a0403a
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .altinstr_replacement at 0000000000a04048
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .rodata.str1.8 at 0000000000a04050
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .livepatch.depends at 0000000000a0405c
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .livepatch.xen_depends at 0000000000a04080
(XEN) livepatch.c:379: livepatch: xen_expectations: Loaded .livepatch.funcs at 0000000000a03000
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa04000 (.note.gnu.build-id)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa0403a (.altinstructions)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa04048 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa04050 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa0405c (.livepatch.depends)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa04080 (.livepatch.xen_depends)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved:  => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:319: livepatch: xen_expectations: Absolute symbol: xen_expectations.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: $d => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: livepatch_exceptions_str => 0xa04028 (.rodata)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: $d => 0xa03000 (.livepatch.funcs)
(XEN) livepatch_elf.c:319: livepatch: xen_expectations: Absolute symbol: xen_hello_world_func.c => 0
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: $x => 0xa02000 (.text)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: $x => 0xa04048 (.altinstr_replacement)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: $d => 0xa04050 (.rodata.str1.8)
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: xen_hello_world => 0xa02000 (.text)
(XEN) livepatch_elf.c:314: livepatch: xen_expectations: Undefined symbol resolved: xen_extra_version => 0x23cd50
(XEN) livepatch_elf.c:343: livepatch: xen_expectations: Symbol resolved: livepatch_exceptions => 0xa03000 (.livepatch.funcs)
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.load is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.unload is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.preapply is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.apply is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.postapply is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.prerevert is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.revert is missing
(XEN) livepatch.c:533: livepatch: xen_expectations: .livepatch.hooks.postrevert is missing
(XEN) alternatives: Patching with alt table 0000000000a0403a -> 0000000000a04046
(XEN) livepatch.c:962: livepatch: xen_expectations: new symbol livepatch_exceptions_str
(XEN) livepatch.c:968: livepatch: xen_expectations: overriding symbol xen_hello_world
(XEN) livepatch.c:962: livepatch: xen_expectations: new symbol livepatch_exceptions
completed
Applying xen_expectations... (XEN) livepatch: xen_expectations: Verifying enabled expectations for all functions
(XEN) livepatch: xen_extra_version: expectation failed: expected:f0000240911fe000, actual:400200f000e01f91
(XEN) livepatch: xen_expectations: expectations of xen_extra_version failed (rc=-22), aborting!
failed
Error 22: Invalid argument
Unloading xen_expectations... completed
root@hikey960:~/test/livepatch# (cd /home/xen.git/xen;objdump -d xen-syms | sed -n -e '/<xen_extra_version>:$/,/^$/ p' | tail -n +2)
  23cd50:	f0000240 	adrp	x0, 287000 <symbols_sorted_offsets+0xc800>
  23cd54:	911fe000 	add	x0, x0, #0x7f8
  23cd58:	d65f03c0 	ret

root@hikey960:/home/xen.git/xen# 

[-- Attachment #3: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  2019-08-29 17:49         ` Konrad Rzeszutek Wilk
@ 2019-08-29 19:07           ` Wieczorkiewicz, Pawel
  2019-08-29 20:48             ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 66+ messages in thread
From: Wieczorkiewicz, Pawel @ 2019-08-29 19:07 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, Ross Lagerwall,
	George Dunlap, Andrew Cooper, Ian Jackson, xen-devel, Pohlack,
	Martin, Wieczorkiewicz, Pawel, Julien Grall, Jan Beulich,
	xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1371 bytes --]



On 29. Aug 2019, at 19:49, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com<mailto:konrad.wilk@oracle.com>> wrote:

On Thu, Aug 29, 2019 at 04:16:13PM +0000, Wieczorkiewicz, Pawel wrote:


On 29. Aug 2019, at 17:58, Konrad Rzeszutek Wilk <konrad.wilk@oracle.com<mailto:konrad.wilk@oracle.com><mailto:konrad.wilk@oracle.com>> wrote:



…snip..


Could you please try with the patch attached?

It compiled, but the test-case was not happy. See attached the full serial log


Ah, I forgot about endianness of course...
I am sending an improved patch. I hope it works this time as expected.





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





If it still fails, could you please send me the output for the following
command with this build?

objdump -d xen-syms | sed -n -e '/<xen_extra_version>:$/,/^$/ p' | tail -n +2

Also included in the serial log.


Best Regards,
Pawel Wieczorkiewicz




<livepatch-hikey960.txt>



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



[-- Attachment #1.2: Type: text/html, Size: 3108 bytes --]

[-- Attachment #2: 0001-fixup-livepatch-Add-support-for-inline-asm-hotpatchi.patch --]
[-- Type: application/octet-stream, Size: 1460 bytes --]

From 3e0eb0cf37ddb197cdbcaf587b8ba6a6a1badbcc Mon Sep 17 00:00:00 2001
From: Pawel Wieczorkiewicz <wipawel@amazon.de>
Date: Thu, 29 Aug 2019 15:43:23 +0000
Subject: [PATCH] fixup! livepatch: Add support for inline asm hotpatching
 expectations

---
 xen/test/livepatch/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 067861903f..a7857d3a2e 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -186,10 +186,10 @@ xen_actions_hooks_norevert.o: config.h
 $(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) $^
 
-CODE_GET_EXPECT=$(shell objdump -d --insn-width=1 $(1) | grep -A6 -E '<'$(2)'>:' | tail -n +2 | awk 'BEGIN {printf "{"} {printf "0x%s,", $$2}' | sed 's/,$$/}/g')
+EXPECT_BYTES_COUNT := 8
+CODE_GET_EXPECT=$(shell $(OBJDUMP) -d --insn-width=1 $(1) | sed -n -e '/<'$(2)'>:$$/,/^$$/ p' | tail -n +2 | head -n $(EXPECT_BYTES_COUNT) | awk '$$0=$$2 {printf "%s", substr($$0,length-1)}' | sed 's/.\{2\}/0x&,/g' | sed 's/^/{/;s/,$$/}/g')
 .PHONY: expect_config.h
 expect_config.h: EXPECT_BYTES=$(call CODE_GET_EXPECT,$(BASEDIR)/xen-syms,xen_extra_version)
-expect_config.h: EXPECT_BYTES_COUNT=6
 expect_config.h: xen_expectations.o
 	(set -e; \
 	 echo "#define EXPECT_BYTES $(EXPECT_BYTES)"; \
-- 
2.16.5


[-- Attachment #3: ATT00001.htm --]
[-- Type: text/html, Size: 853 bytes --]

[-- Attachment #4: Type: text/plain, Size: 157 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (11 preceding siblings ...)
  2019-08-27  8:46   ` [Xen-devel] [PATCH v2 12/12] livepatch: Add python bindings for livepatch operations Pawel Wieczorkiewicz
@ 2019-08-29 19:23   ` Konrad Rzeszutek Wilk
  2019-09-05 19:13   ` Konrad Rzeszutek Wilk
  2019-09-06 22:42   ` Julien Grall
  14 siblings, 0 replies; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-29 19:23 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, xen-devel, Ross Lagerwall,
	Julien Grall, Jan Beulich, Marek Marczykowski-Górecki,
	xen-devel, Volodymyr Babchuk, Roger Pau Monné

> Pawel Wieczorkiewicz (12):
>   [1] livepatch: Always check hypervisor build ID upon hotpatch upload
>   [2] livepatch: Allow to override inter-modules buildid dependency
>   [3] livepatch: Export payload structure via livepatch_payload.h
>   [4] livepatch: Implement pre-|post- apply|revert hooks
>   [5] livepatch: Add support for apply|revert action replacement hooks
>   [6] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence
>   [7] livepatch: Add per-function applied/reverted state tracking marker

I've added the test-cases to the little tool I use (including the diff)
http://xenbits.xen.org/gitweb/?p=xentesttools/bootstrap.git;a=blob;f=root_image/debugspace/livepatch_test.pl;h=37fb668a53ca1e7a084bfc4417f90e8ae078f7e5;hb=HEAD


>   [8] livepatch: Add support for inline asm hotpatching expectations

..but didn't expand on #8 as it still needs a bit of help on ARM..

Irrespective of that:

a)  Need to update the docs to alter the text where it says that the
entries are 8 bytes long - as on ARM32 they are 4 bytes.

b) Update the docs to say it is spec 2, not 1.

c) Also need OK or Acked-by from Julie on ARM.

I can do a) and b) when v3 is posted or when the fixes for to patch #8 are
all good and can squash them in. (And will also update the test-case to
include the code change for the asm livepatch).

diff --git a/root_image/debugspace/livepatch_test.pl b/root_image/debugspace/livepatch_test.pl
index 37fb668..a96c9fc 100755
--- a/root_image/debugspace/livepatch_test.pl
+++ b/root_image/debugspace/livepatch_test.pl
@@ -9,7 +9,14 @@ use File::Temp qw(tempfile);
 my @livepatch_files = qw(xen_hello_world.livepatch
 			 xen_replace_world.livepatch
                          xen_bye_world.livepatch
-			 xen_nop.livepatch);
+			 xen_nop.livepatch
+			 xen_no_xen_buildid.livepatch
+			 xen_prepost_hooks_fail.livepatch
+			 xen_prepost_hooks.livepatch
+			 xen_action_hooks.livepatch
+			 xen_action_hooks_marker.livepatch
+			 xen_action_hooks_noapply.livepatch
+			 xen_action_hooks_norevert.livepatch);
 
 my $livepatch_dir="/usr/lib/debug/livepatch";
 my $xen_extra_info;
@@ -111,6 +118,25 @@ my @livepatch_tests = (
     { C => "xen-livepatch unload xen_nop", rc => 256 },
     { C => "xen-livepatch revert xen_nop" },
     { C => "xen-livepatch unload xen_nop" },
+    { C => "xen-livepatch load xen_no_xen_buildid.livepatch", rc => 256 },
+    { C => "xen-livepatch load xen_prepost_hooks_fail.livepatch", rc => 256 },
+    { C => "xen-livepatch load xen_prepost_hooks.livepatch" },
+    # First revert fails
+    { C => "xen-livepatch revert xen_prepost_hooks", rc => 256 },
+    { C => "xen-livepatch revert xen_prepost_hooks" },
+    { C => "xen-livepatch unload xen_prepost_hooks" },
+    { C => "xen-livepatch load xen_action_hooks.livepatch" },
+    { C => "xen-livepatch revert xen_action_hooks" },
+    { C => "xen-livepatch unload xen_action_hooks" },
+    { C => "xen-livepatch load xen_action_hooks_marker.livepatch" },
+    { C => "xen-livepatch revert xen_action_hooks_marker" },
+    { C => "xen-livepatch unload xen_action_hooks_marker" },
+    { C => "xen-livepatch load xen_action_hooks_noapply.livepatch" },
+    { C => "xen-livepatch revert xen_action_hooks_noapply" },
+    { C => "xen-livepatch unload xen_action_hooks_noapply" },
+    { C => "xen-livepatch load xen_action_hooks_norevert.livepatch" },
+    { C => "xen-livepatch revert xen_action_hooks_norevert" },
+    { C => "xen-livepatch unload xen_action_hooks_norevert" },
     );
 
 # Copied from https://stackoverflow.com/questions/11514947/capture-the-output-of-perl-system

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  2019-08-29 19:07           ` Wieczorkiewicz, Pawel
@ 2019-08-29 20:48             ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-29 20:48 UTC (permalink / raw)
  To: Wieczorkiewicz, Pawel
  Cc: Tim Deegan, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, xen-devel, Pohlack, Martin,
	Ross Lagerwall, Julien Grall, Jan Beulich, xen-devel

> Ah, I forgot about endianness of course...
> I am sending an improved patch. I hope it works this time as expected.

Works nicely! (Tested only on ARM64, hadn't tried ARM32 yet).

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 11/12] livepatch: Add metadata runtime retrieval mechanism
  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
  0 siblings, 0 replies; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-08-29 20:48 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, xen-devel, Ross Lagerwall,
	Julien Grall, Jan Beulich, xen-devel

On Tue, Aug 27, 2019 at 08:46:23AM +0000, Pawel Wieczorkiewicz wrote:
> Extend the livepatch list operation to fetch also payloads' metadata.
> This is achieved by extending the sysctl list interface with 2 extra
> guest handles:
> * metadata     - an array of arbitrary size strings
> * metadata_len - an array of metadata strings' lengths (uin32_t each)
> 
> Payloads' metadata is a string of arbitrary size and does not have an
> upper bound limit. It may also vary in size between payloads.
> 
> In order to let the userland allocate enough space for the incoming
> data add a metadata total size field to the list sysctl operation and
> fill it with total size of all payloads' metadata.
> 
> Extend the libxc to handle the metadata back-to-back data transfers
> as well as metadata length array data transfers.
> 
> The xen-livepatch userland tool is extended to always display the
> metadata for each received module. The metadata is received with the
> following format: key=value\0key=value\0...key=value\0. The format is
> modified to the following one: key=value;key=value;...key=value.
> The new format allows to easily parse the metadata for a given module
> by a machine.
> 
> Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
> Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
> Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
> Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
> ---
> Changed since v1:
>   * added corresponding documentation
>   * make metadata optional (do not display it when given payload
>     does not have it)
> 
>  docs/misc/livepatch.pandoc    | 31 ++++++++++++++++-----
>  tools/libxc/include/xenctrl.h | 22 +++++++++++----
>  tools/libxc/xc_misc.c         | 64 +++++++++++++++++++++++++++++++++++--------
>  tools/misc/xen-livepatch.c    | 43 +++++++++++++++++++++++------
>  xen/common/livepatch.c        | 22 +++++++++++----
>  xen/include/public/sysctl.h   | 19 +++++++++----
>  6 files changed, 157 insertions(+), 44 deletions(-)

And it may be worth folding this in:

diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index a7857d3a2e..3f088e74b2 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -79,9 +79,17 @@ config.h: xen_hello_world_func.o
 xen_hello_world.o: config.h
 
 .PHONY: $(LIVEPATCH)
-$(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o xen_note.o
+$(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o xen_note.o modinfo.o
        $(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH) $^
 
+.PHONY: modinfo.o
+modinfo.o:
+       (set -e; \
+        printf "LIVEPATCH_RULEZ\0") > $@.bin
+       $(OBJCOPY) $(OBJCOPY_MAGIC) \
+                  --rename-section=.data=.modinfo,alloc,load,readonly,data,contents -S $@.bin $@
+       #rm -f $@.bin
+
 #
 # This target is only accessible if CONFIG_LIVEPATCH is defined, which
 # depends on $(build_id_linker) being available. Hence we do not

.. which the test-case can test for.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 08/12] livepatch: Add support for inline asm hotpatching expectations
  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:58     ` Konrad Rzeszutek Wilk
@ 2019-09-05 18:05     ` Konrad Rzeszutek Wilk
  2 siblings, 0 replies; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-09-05 18:05 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu,
	Konrad Rzeszutek Wilk, George Dunlap, Andrew Cooper, Ian Jackson,
	mpohlack, xen-devel, Ross Lagerwall, Julien Grall, Jan Beulich,
	xen-devel

> diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc
> index 6ab7f4c2d2..92a424e918 100644
> --- a/docs/misc/livepatch.pandoc
> +++ b/docs/misc/livepatch.pandoc
> @@ -300,6 +300,7 @@ which describe the functions to be patched:
>          /* Added to livepatch payload version 2: */
>          uint8_t applied;
>          uint8_t _pad[7];
> +        livepatch_expectation_t expect;
>      };
>  
>  The size of the structure is 64 bytes on 64-bit hypervisors. It will be
                                ^^
I also updated this to be 104 and 92 (for 32-bit).

And added:
> @@ -336,6 +337,26 @@ 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.
> +  * `expect` is an optional structure containing expected to-be-replaced data
> +    (mostly for inline asm patching). The `expect` structure format is:
> +
> +    struct livepatch_expectation {
> +        uint8_t enabled : 1;
> +        uint8_t len : 5;

uint8_t rsv : 2;

To make it clear what the extra two bits in the bit-field should have.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (12 preceding siblings ...)
  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
  14 siblings, 1 reply; 66+ messages in thread
From: Konrad Rzeszutek Wilk @ 2019-09-05 19:13 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, xen-devel, Ross Lagerwall,
	Julien Grall, Jan Beulich, Marek Marczykowski-Górecki,
	xen-devel, Volodymyr Babchuk, Roger Pau Monné

On Tue, Aug 27, 2019 at 08:46:12AM +0000, Pawel Wieczorkiewicz wrote:
> This series introduces new features to the livepatch functionality as
> briefly discussed during Xen Developer Summit 2019: [a] and [b].
> It also provides a few fixes and some small improvements.
> 
> Main changes in v2:
> - added new features to livepatch documentation
> - added livepatch tests
> - enabled Arm support for [5]
> - make .modinfo optional for [11]
> - fixed typos

I took your patches, redid them per what I had responded on these patches
(and squashed your fix for xen_expectations) and stuck them in my branch:

http://xenbits.xen.org/gitweb/?p=people/konradwilk/xen.git;a=shortlog;h=refs/heads/livepatch.aws.v3

There are three extra patches that were needed for me to test on ARM32 - those
are known issues and they don't block your patches. I will post them independent
of your patches.

From my perspective, your patches are good to go.

But I believe I need:
 - the tools folks Ack on the libxc code changes,
 - and also an Ack from the REST on sysctl.h,
 - and Julian OK on the ARM32/ARM64 code changes which are tiny, but nonethless are his.

Pawel, If I don't get to send them out by the end of the next week - feel free
to grab them from my branch tree and repost them as v3.

Thank you!

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes
  2019-08-27  8:46 ` [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes Pawel Wieczorkiewicz
                     ` (13 preceding siblings ...)
  2019-09-05 19:13   ` Konrad Rzeszutek Wilk
@ 2019-09-06 22:42   ` Julien Grall
  14 siblings, 0 replies; 66+ messages in thread
From: Julien Grall @ 2019-09-06 22:42 UTC (permalink / raw)
  To: Pawel Wieczorkiewicz, xen-devel, xen-devel
  Cc: Marek Marczykowski-Górecki, wipawel, Stefano Stabellini,
	Wei Liu, Konrad Rzeszutek Wilk, George Dunlap, Andrew Cooper,
	Ian Jackson, mpohlack, Tim Deegan, Ross Lagerwall, Jan Beulich,
	Volodymyr Babchuk, Roger Pau Monné

Hi,

Thank you for the new version. However, I nearly missed the v2 as this 
is a sub-thread of v1. May I ask you to send a new version as a new 
thread instead?

Cheers,

On 8/27/19 9:46 AM, Pawel Wieczorkiewicz wrote:
> This series introduces new features to the livepatch functionality as
> briefly discussed during Xen Developer Summit 2019: [a] and [b].
> It also provides a few fixes and some small improvements.
> 
> Main changes in v2:
> - added new features to livepatch documentation
> - added livepatch tests
> - enabled Arm support for [5]
> - make .modinfo optional for [11]
> - fixed typos
> 
> FEATURES:
> 
> 1. independent modules (patches: [1], [2])
> 
>    * livepatch-build-tools repo dependency [A]
> 
>    Livepatch enforces the following buildid-based dependency chain
>    between hotpatch modules:
>      1) first module depends on given hypervisor buildid
>      2) every consecutive module depends on previous module's buildid
>    This way proper hotpatch stack order is maintained and enforced.
>    While it is important for production hotpatches it limits agility and
>    blocks usage of testing or debug hotpatches. These kinds of hotpatch
>    modules are typically expected to be loaded at any time irrespective
>    of current state of the modules stack.
> 
>    [A] livepatch-build: Embed hypervisor build id into every hotpatch
> 
> 2. pre- and post- apply|revert actions hooks (patches: [3], [4])
> 
>    * livepatch-build-tools repo dependency [B]
> 
>    This is an implementation of 4 new livepatch module vetoing hooks,
>    that can be optionally supplied along with modules.
>    Hooks that currently exists in the livepatch mechanism aren't agile
>    enough and have various limitations:
>    * run only from within a quiescing zone
>    * cannot conditionally prevent applying or reverting
>    * do not have access to the module context
>    To address these limitations the following has been implemented:
>    1) pre-apply hook
>    2) post-apply hook
>    3) pre-revert hook
>    4) post-revert hook
> 
>    [B] create-diff-object: Handle extra pre-|post- hooks
> 
> 3. apply|revert actions replacement hooks (patches: [5], [6], [7])
> 
>    * livepatch-build-tools repo dependency: [C], [D], [E]
> 
>    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.
> 
>    [C] create-diff-object: Do not create empty .livepatch.funcs section
>    [D] create-diff-object: Handle optional apply|revert hooks
>    [E] create-diff-object: Add support for applied/reverted marker
> 
> 4. inline asm hotpatching expectations (patches: [8])
> 
>    * livepatch-build-tools repo dependency: [F]
> 
>    Expectations are designed as optional feature, since the main use of
>    them is planned for inline asm hotpatching.
>    The payload structure is modified as each expectation structure is
>    part of the livepatch_func structure and hence extends the payload.
>    The payload version is bumped to 3 with this change to highlight the
>    ABI modification and enforce proper support.
>    The expectation is manually enabled during inline asm module
>    construction. If enabled, expectation ensures that the expected
>    content of memory is to be found at a given patching (old_addr)
>    location.
> 
>    [F] create-diff-object: Add support for expectations
> 
> 5. runtime hotpatch metadata support (patches: [9], [10], [11])
> 
>    Having detailed hotpatch metadata helps to properly identify module's
>    origin and version. It also allows to keep track of the history of
>    hotpatch loads in the system (at least within dmesg buffer size
>    limits).
>    Extend the livepatch list operation to fetch also payloads' metadata.
>    This is achieved by extending the sysctl list interface with 2 extra
>    guest handles:
>    * metadata     - an array of arbitrary size strings
>    * metadata_len - an array of metadata strings' lengths (uin32_t each)
>    To unify and simplify the interface, handle the modules' name strings
>    of arbitrary size by copying them in adhering chunks to the userland.
> 
> 6. python bindings for livepatch operations (patches: [12])
> 
>    Extend the XC python bindings library to support all common livepatch
>    operations and actions:
>    - status (pyxc_livepatch_status):
>    - action (pyxc_livepatch_action):
>    - upload (pyxc_livepatch_upload):
>    - list (pyxc_livepatch_list):
> 
> [a] https://wiki.xenproject.org/wiki/Design_Sessions_2019#LivePatch_improvements_and_features
> [b] https://lists.xenproject.org/archives/html/xen-devel/2019-07/msg00846.html
> 
> Merged in v1:
>    python: Add XC binding for Xen build ID
>    livepatch: always print XENLOG_ERR information
> 
> Pawel Wieczorkiewicz (12):
>    [1] livepatch: Always check hypervisor build ID upon hotpatch upload
>    [2] livepatch: Allow to override inter-modules buildid dependency
>    [3] livepatch: Export payload structure via livepatch_payload.h
>    [4] livepatch: Implement pre-|post- apply|revert hooks
>    [5] livepatch: Add support for apply|revert action replacement hooks
>    [6] livepatch: Do not enforce ELF_LIVEPATCH_FUNC section presence
>    [7] livepatch: Add per-function applied/reverted state tracking marker
>    [8] livepatch: Add support for inline asm hotpatching expectations
>    [9] livepatch: Add support for modules .modinfo section metadata
>    [10] livepatch: Handle arbitrary size names with the list operation
>    [11] livepatch: Add metadata runtime retrieval mechanism
>    [12] livepatch: Add python bindings for livepatch operations
> 
>   .gitignore                                     |   6 +-
>   docs/misc/livepatch.pandoc                     | 231 ++++++++-
>   tools/libxc/include/xenctrl.h                  |  68 ++-
>   tools/libxc/xc_misc.c                          | 162 +++++--
>   tools/misc/xen-livepatch.c                     | 258 +++++++---
>   tools/python/xen/lowlevel/xc/xc.c              | 273 +++++++++++
>   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                         | 647 +++++++++++++++++++++----
>   xen/include/public/sysctl.h                    |  61 ++-
>   xen/include/xen/livepatch.h                    |  42 +-
>   xen/include/xen/livepatch_payload.h            |  83 ++++
>   xen/test/livepatch/Makefile                    | 113 ++++-
>   xen/test/livepatch/xen_action_hooks.c          | 102 ++++
>   xen/test/livepatch/xen_action_hooks_marker.c   | 112 +++++
>   xen/test/livepatch/xen_action_hooks_noapply.c  | 136 ++++++
>   xen/test/livepatch/xen_action_hooks_nofunc.c   |  86 ++++
>   xen/test/livepatch/xen_action_hooks_norevert.c | 143 ++++++
>   xen/test/livepatch/xen_expectations.c          |  41 ++
>   xen/test/livepatch/xen_expectations_fail.c     |  42 ++
>   xen/test/livepatch/xen_prepost_hooks.c         | 122 +++++
>   xen/test/livepatch/xen_prepost_hooks_fail.c    |  75 +++
>   24 files changed, 2579 insertions(+), 280 deletions(-)
>   create mode 100644 xen/test/livepatch/xen_action_hooks.c
>   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_nofunc.c
>   create mode 100644 xen/test/livepatch/xen_action_hooks_norevert.c
>   create mode 100644 xen/test/livepatch/xen_expectations.c
>   create mode 100644 xen/test/livepatch/xen_expectations_fail.c
>   create mode 100644 xen/test/livepatch/xen_prepost_hooks.c
>   create mode 100644 xen/test/livepatch/xen_prepost_hooks_fail.c
> 

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

* Re: [Xen-devel] [PATCH v2 00/12] livepatch: new features and fixes
  2019-09-05 19:13   ` Konrad Rzeszutek Wilk
@ 2019-09-06 22:52     ` Julien Grall
  0 siblings, 0 replies; 66+ messages in thread
From: Julien Grall @ 2019-09-06 22:52 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, Pawel Wieczorkiewicz
  Cc: Tim Deegan, wipawel, Stefano Stabellini, Wei Liu, George Dunlap,
	Andrew Cooper, Ian Jackson, mpohlack, xen-devel, Ross Lagerwall,
	Jan Beulich, Marek Marczykowski-Górecki, xen-devel,
	Volodymyr Babchuk, Roger Pau Monné

Hi Konrad,

On 9/5/19 8:13 PM, Konrad Rzeszutek Wilk wrote:
> On Tue, Aug 27, 2019 at 08:46:12AM +0000, Pawel Wieczorkiewicz wrote:
>> This series introduces new features to the livepatch functionality as
>> briefly discussed during Xen Developer Summit 2019: [a] and [b].
>> It also provides a few fixes and some small improvements.
>>
>> Main changes in v2:
>> - added new features to livepatch documentation
>> - added livepatch tests
>> - enabled Arm support for [5]
>> - make .modinfo optional for [11]
>> - fixed typos
> 
> I took your patches, redid them per what I had responded on these patches
> (and squashed your fix for xen_expectations) and stuck them in my branch:
> 
> http://xenbits.xen.org/gitweb/?p=people/konradwilk/xen.git;a=shortlog;h=refs/heads/livepatch.aws.v3
> 
> There are three extra patches that were needed for me to test on ARM32 - those
> are known issues and they don't block your patches. I will post them independent
> of your patches.
> 
>  From my perspective, your patches are good to go.
> 
> But I believe I need:
>   - the tools folks Ack on the libxc code changes,
>   - and also an Ack from the REST on sysctl.h,
>   - and Julian OK on the ARM32/ARM64 code changes which are tiny, but nonethless are his.

I believe all the modifications are under in livepatch.c files. So your 
Ack should be sufficient here :).

Anyway, feel free to add mine on Arm specific modifications.

Cheers,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 66+ messages in thread

end of thread, other threads:[~2019-09-06 22:52 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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   ` [Xen-devel] [PATCH v2 07/12] livepatch: Add per-function applied/reverted state tracking marker Pawel Wieczorkiewicz
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).