[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 5/7] doc: correct livepatch.markdown syntax
"make -C docs all" fails due to incorrect markdown syntax in livepatch.markdown. Correct it. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> --- docs/misc/livepatch.markdown | 589 ++++++++++++++++++++----------------------- 1 file changed, 272 insertions(+), 317 deletions(-) diff --git a/docs/misc/livepatch.markdown b/docs/misc/livepatch.markdown index 54a6b850cb..f3c1320e5a 100644 --- a/docs/misc/livepatch.markdown +++ b/docs/misc/livepatch.markdown @@ -89,33 +89,26 @@ As example we will assume the hypervisor does not have XSA-132 (see 4ff3449f0e9d175ceb9551d3f2aecb59273f639d) and we would like to binary patch the hypervisor with it. The original code looks as so: -<pre> - 48 89 e0 mov %rsp,%rax - 48 25 00 80 ff ff and $0xffffffffffff8000,%rax -</pre> + 48 89 e0 mov %rsp,%rax + 48 25 00 80 ff ff and $0xffffffffffff8000,%rax while the new patched hypervisor would be: -<pre> - 48 c7 45 b8 00 00 00 00 movq $0x0,-0x48(%rbp) - 48 c7 45 c0 00 00 00 00 movq $0x0,-0x40(%rbp) - 48 c7 45 c8 00 00 00 00 movq $0x0,-0x38(%rbp) - 48 89 e0 mov %rsp,%rax - 48 25 00 80 ff ff and $0xffffffffffff8000,%rax -</pre> + 48 c7 45 c0 00 00 00 00 movq $0x0,-0x40(%rbp) + 48 c7 45 c8 00 00 00 00 movq $0x0,-0x38(%rbp) + 48 89 e0 mov %rsp,%rax + 48 25 00 80 ff ff and $0xffffffffffff8000,%rax -This is inside the arch_do_domctl. This new change adds 21 extra +This is inside the arch\_do\_domctl. This new change adds 21 extra bytes of code which alters all the offsets inside the function. To alter these offsets and add the extra 21 bytes of code we might not have enough space in .text to squeeze this in. As such we could simplify this problem by only patching the site -which calls arch_do_domctl: +which calls arch\_do\_domctl: -<pre> -do_domctl: - e8 4b b1 05 00 callq ffff82d08015fbb9 <arch_do_domctl> -</pre> + do_domctl: + e8 4b b1 05 00 callq ffff82d08015fbb9 <arch_do_domctl> with a new address for where the new `arch_do_domctl` would be (this area would be allocated dynamically). @@ -123,15 +116,13 @@ area would be allocated dynamically). Astute readers will wonder what we need to do if we were to patch `do_domctl` - which is not called directly by hypervisor but on behalf of the guests via the `compat_hypercall_table` and `hypercall_table`. -Patching the offset in `hypercall_table` for `do_domctl: -(ffff82d080103079 <do_domctl>:) +Patching the offset in `hypercall_table` for `do_domctl`: +(ffff82d080103079 <do\_domctl>:) -<pre> - - ffff82d08024d490: 79 30 - ffff82d08024d492: 10 80 d0 82 ff ff - -</pre> + + ffff82d08024d490: 79 30 + ffff82d08024d492: 10 80 d0 82 ff ff + with the new address where the new `do_domctl` is possible. The other place where it is used is in `hvm_hypercall64_table` which would need @@ -164,19 +155,17 @@ CPU branching logic (I-cache, but it is just one unconditional jump). For this example we will assume that the hypervisor has not been compiled with fe2e079f642effb3d24a6e1a7096ef26e691d93e (XSA-125: *pre-fill structures -for certain HYPERVISOR_xen_version sub-ops*) which mem-sets an structure +for certain HYPERVISOR\_xen\_version sub-ops*) which mem-sets an structure in `xen_version` hypercall. This function is not called **anywhere** in the hypervisor (it is called by the guest) but referenced in the `compat_hypercall_table` and `hypercall_table` (and indirectly called from that). Patching the offset in `hypercall_table` for the old -`do_xen_version` (ffff82d080112f9e <do_xen_version>) - -</pre> - ffff82d08024b270 <hypercall_table>: - ... - ffff82d08024b2f8: 9e 2f 11 80 d0 82 ff ff +`do_xen_version` (ffff82d080112f9e <do\_xen\_version>) -</pre> + ffff82d08024b270 <hypercall_table>: + ... + ffff82d08024b2f8: 9e 2f 11 80 d0 82 ff ff + with the new address where the new `do_xen_version` is possible. The other place where it is used is in `hvm_hypercall64_table` which would need @@ -184,21 +173,17 @@ to be patched in a similar way. This would require an in-place splicing of the new virtual address of `do_xen_version`. An alternative solution would be to patch insert a trampoline in the -old `do_xen_version' function to directly jump to the new `do_xen_version`. +old `do_xen_version` function to directly jump to the new `do_xen_version`. -<pre> - ffff82d080112f9e do_xen_version: - ffff82d080112f9e: 48 c7 c0 da ff ff ff mov $0xffffffffffffffda,%rax - ffff82d080112fa5: 83 ff 09 cmp $0x9,%edi - ffff82d080112fa8: 0f 87 24 05 00 00 ja ffff82d0801134d2 ; do_xen_version+0x534 -</pre> + ffff82d080112f9e do_xen_version: + ffff82d080112f9e: 48 c7 c0 da ff ff ff mov $0xffffffffffffffda,%rax + ffff82d080112fa5: 83 ff 09 cmp $0x9,%edi + ffff82d080112fa8: 0f 87 24 05 00 00 ja ffff82d0801134d2 ; do_xen_version+0x534 with: -<pre> - ffff82d080112f9e do_xen_version: - ffff82d080112f9e: e9 XX YY ZZ QQ jmpq [new do_xen_version] -</pre> + ffff82d080112f9e do_xen_version: + ffff82d080112f9e: e9 XX YY ZZ QQ jmpq [new do_xen_version] which would lessen the amount of patching to just one location. @@ -208,7 +193,7 @@ new replacement function which required: * inserting trampoline with new offset in the old function to point to the new function. * Optionally we can insert in the old function a trampoline jump to an function - providing an BUG_ON to catch errant code. + providing an BUG\_ON to catch errant code. The disadvantage of this are that the unconditional jump will consume a small I-cache penalty. However the simplicity of the patching and higher chance @@ -260,7 +245,7 @@ Note that every structure has padding. This is added so that the hypervisor can re-use those fields as it sees fit. Earlier design attempted to ineptly explain the relations of the ELF sections -to each other without using proper ELF mechanism (sh_info, sh_link, data +to each other without using proper ELF mechanism (sh\_info, sh\_link, data structures using Elf types, etc). This design will explain the structures and how they are used together and not dig in the ELF format - except mention that the section names should match the structure names. @@ -285,27 +270,25 @@ 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.funcs` - which is an array of livepatch\_func structures. * `.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. ### .livepatch.funcs -The `.livepatch.funcs` contains an array of livepatch_func structures +The `.livepatch.funcs` contains an array of livepatch\_func structures which describe the functions to be patched: -<pre> -struct livepatch_func { - const char *name; - void *new_addr; - void *old_addr; - uint32_t new_size; - uint32_t old_size; - uint8_t version; - uint8_t opaque[31]; -}; -</pre> + struct livepatch_func { + const char *name; + void *new_addr; + void *old_addr; + uint32_t new_size; + uint32_t old_size; + uint8_t version; + uint8_t opaque[31]; + }; The size of the structure is 64 bytes on 64-bit hypervisors. It will be 52 on 32-bit hypervisors. @@ -362,36 +345,34 @@ being applied and after being reverted: A simple example of what a payload file can be: -<pre> -/* MUST be in sync with hypervisor. */ -struct livepatch_func { - const char *name; - void *new_addr; - void *old_addr; - uint32_t new_size; - uint32_t old_size; - uint8_t version; - uint8_t pad[31]; -}; - -/* Our replacement function for xen_extra_version. */ -const char *xen_hello_world(void) -{ - return "Hello World"; -} - -static unsigned char patch_this_fnc[] = "xen_extra_version"; - -struct livepatch_func livepatch_hello_world = { - .version = LIVEPATCH_PAYLOAD_VERSION, - .name = patch_this_fnc, - .new_addr = xen_hello_world, - .old_addr = (void *)0xffff82d08013963c, /* Extracted from xen-syms. */ - .new_size = 13, /* To be be computed by scripts. */ - .old_size = 13, /* -----------""--------------- */ -} __attribute__((__section__(".livepatch.funcs"))); - -</pre> + /* MUST be in sync with hypervisor. */ + struct livepatch_func { + const char *name; + void *new_addr; + void *old_addr; + uint32_t new_size; + uint32_t old_size; + uint8_t version; + uint8_t pad[31]; + }; + + /* Our replacement function for xen_extra_version. */ + const char *xen_hello_world(void) + { + return "Hello World"; + } + + static unsigned char patch_this_fnc[] = "xen_extra_version"; + + struct livepatch_func livepatch_hello_world = { + .version = LIVEPATCH_PAYLOAD_VERSION, + .name = patch_this_fnc, + .new_addr = xen_hello_world, + .old_addr = (void *)0xffff82d08013963c, /* Extracted from xen-syms. */ + .new_size = 13, /* To be be computed by scripts. */ + .old_size = 13, /* -----------""--------------- */ + } __attribute__((__section__(".livepatch.funcs"))); + Code must be compiled with -fPIC. @@ -406,10 +387,8 @@ Each entry in this array is eight bytes. The type definition of the function are as follow: -<pre> -typedef void (*livepatch_loadcall_t)(void); -typedef void (*livepatch_unloadcall_t)(void); -</pre> + typedef void (*livepatch_loadcall_t)(void); + typedef void (*livepatch_unloadcall_t)(void); ### .livepatch.depends and .note.gnu.build-id @@ -423,7 +402,7 @@ which follows the format of an ELF Note. The contents of this 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 +is a NT\_GNU\_BUILD\_ID type ID. The description can be an SHA1 checksum, MD5 checksum or any unique value. The size of these structures varies with the --build-id linker option. @@ -454,22 +433,20 @@ Furthermore it is possible to have multiple different payloads for the same function. As such an unique name per payload has to be visible to allow proper manipulation. The hypercall is part of the `xen_sysctl`. The top level structure contains -one uint32_t to determine the sub-operations and one padding field which +one uint32\_t to determine the sub-operations and one padding field which *MUST* always be zero. -<pre> -struct xen_sysctl_livepatch_op { - uint32_t cmd; /* IN: XEN_SYSCTL_LIVEPATCH_*. */ - uint32_t pad; /* IN: Always zero. */ - union { - ... see below ... - } u; -}; - -</pre> + struct xen_sysctl_livepatch_op { + uint32_t cmd; /* IN: XEN_SYSCTL_LIVEPATCH_*. */ + uint32_t pad; /* IN: Always zero. */ + union { + ... see below ... + } u; + }; + while the rest of hypercall specific structures are part of the this structure. -### Basic type: struct xen_livepatch_name +### Basic type: struct xen\_livepatch\_name Most of the hypercalls employ an shared structure called `struct xen_livepatch_name` which contains: @@ -480,26 +457,24 @@ which contains: The structure is as follow: -<pre> -/* - * Uniquely identifies the payload. Should be human readable. - * Includes the NUL terminator - */ -#define XEN_LIVEPATCH_NAME_SIZE 128 -struct xen_livepatch_name { - XEN_GUEST_HANDLE_64(char) name; /* IN, pointer to name. */ - uint16_t size; /* IN, size of name. May be upto - XEN_LIVEPATCH_NAME_SIZE. */ - uint16_t pad[3]; /* IN: MUST be zero. */ -}; -</pre> - -### XEN_SYSCTL_LIVEPATCH_UPLOAD (0) + /* + * Uniquely identifies the payload. Should be human readable. + * Includes the NUL terminator + */ + #define XEN_LIVEPATCH_NAME_SIZE 128 + struct xen_livepatch_name { + XEN_GUEST_HANDLE_64(char) name; /* IN, pointer to name. */ + uint16_t size; /* IN, size of name. May be upto + XEN_LIVEPATCH_NAME_SIZE. */ + uint16_t pad[3]; /* IN: MUST be zero. */ + }; + +### XEN\_SYSCTL\_LIVEPATCH\_UPLOAD (0) Upload a payload to the hypervisor. The payload is verified against basic checks and if there are any issues the proper return code will be returned. The payload is not applied at this time - that is -controlled by *XEN_SYSCTL_LIVEPATCH_ACTION*. +controlled by *XEN\_SYSCTL\_LIVEPATCH\_ACTION*. The caller provides: @@ -512,21 +487,19 @@ payload. It can be embedded into the ELF payload at creation time and extracted by tools. The return value is zero if the payload was succesfully uploaded. -Otherwise an -XEN_EXX return value is provided. Duplicate `name` are not supported. +Otherwise an -XEN\_EXX return value is provided. Duplicate `name` are not supported. The `payload` is the ELF payload as mentioned in the `Payload format` section. The structure is as follow: -<pre> -struct xen_sysctl_livepatch_upload { - xen_livepatch_name_t name; /* IN, name of the patch. */ - uint64_t size; /* IN, size of the ELF file. */ - XEN_GUEST_HANDLE_64(uint8) payload; /* IN: ELF file. */ -}; -</pre> + struct xen_sysctl_livepatch_upload { + xen_livepatch_name_t name; /* IN, name of the patch. */ + uint64_t size; /* IN, size of the ELF file. */ + XEN_GUEST_HANDLE_64(uint8) payload; /* IN: ELF file. */ + }; -### XEN_SYSCTL_LIVEPATCH_GET (1) +### XEN\_SYSCTL\_LIVEPATCH\_GET (1) Retrieve an status of an specific payload. This caller provides: @@ -537,33 +510,29 @@ Retrieve an status of an specific payload. This caller provides: Upon completion the `struct xen_livepatch_status` is updated. * `status` - indicates the current status of the payload: - * *LIVEPATCH_STATUS_CHECKED* (1) loaded and the ELF payload safety checks passed. - * *LIVEPATCH_STATUS_APPLIED* (2) loaded, checked, and applied. + * *LIVEPATCH\_STATUS\_CHECKED* (1) loaded and the ELF payload safety checks passed. + * *LIVEPATCH\_STATUS\_APPLIED* (2) loaded, checked, and applied. * No other value is possible. - * `rc` - -XEN_EXX type errors encountered while performing the last - LIVEPATCH_ACTION_* operation. The normal values can be zero or -XEN_EAGAIN which + * `rc` - -XEN\_EXX type errors encountered while performing the last + LIVEPATCH\_ACTION\_\* operation. The normal values can be zero or -XEN\_EAGAIN which respectively mean: success or operation in progress. Other values imply an error occurred. If there is an error in `rc`, `status` will **NOT** have changed. -The return value of the hypercall is zero on success and -XEN_EXX on failure. -(Note that the `rc`` value can be different from the return value, as in -rc=-XEN_EAGAIN and return value can be 0). +The return value of the hypercall is zero on success and -XEN\_EXX on failure. +(Note that the `rc` value can be different from the return value, as in +rc=-XEN\_EAGAIN and return value can be 0). For example, supposing there is an payload: -<pre> - status: LIVEPATCH_STATUS_CHECKED - rc: 0 -</pre> + status: LIVEPATCH_STATUS_CHECKED + rc: 0 -We apply an action - LIVEPATCH_ACTION_REVERT - to revert it (which won't work +We apply an action - LIVEPATCH\_ACTION\_REVERT - to revert it (which won't work as we have not even applied it. Afterwards we will have: -<pre> - status: LIVEPATCH_STATUS_CHECKED - rc: -XEN_EINVAL -</pre> + status: LIVEPATCH_STATUS_CHECKED + rc: -XEN_EINVAL It has failed but it remains loaded. @@ -571,21 +540,19 @@ This operation is synchronous and does not require preemption. The structure is as follow: -<pre> -struct xen_livepatch_status { -#define LIVEPATCH_STATUS_CHECKED 1 -#define LIVEPATCH_STATUS_APPLIED 2 - uint32_t state; /* OUT: LIVEPATCH_STATE_*. */ - int32_t rc; /* OUT: 0 if no error, otherwise -XEN_EXX. */ -}; + struct xen_livepatch_status { + #define LIVEPATCH_STATUS_CHECKED 1 + #define LIVEPATCH_STATUS_APPLIED 2 + uint32_t state; /* OUT: LIVEPATCH_STATE_*. */ + int32_t rc; /* OUT: 0 if no error, otherwise -XEN_EXX. */ + }; + + struct xen_sysctl_livepatch_get { + xen_livepatch_name_t name; /* IN, the name of the payload. */ + xen_livepatch_status_t status; /* IN/OUT: status of the payload. */ + }; -struct xen_sysctl_livepatch_get { - xen_livepatch_name_t name; /* IN, the name of the payload. */ - xen_livepatch_status_t status; /* IN/OUT: status of the payload. */ -}; -</pre> - -### XEN_SYSCTL_LIVEPATCH_LIST (2) +### XEN\_SYSCTL\_LIVEPATCH\_LIST (2) Retrieve an array of abbreviated status and names of payloads that are loaded in the hypervisor. @@ -606,20 +573,20 @@ The caller provides: 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 + **XEN\_LIVEPATCH\_NAME\_SIZE** size. 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). + 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). The `status`, `name`, and `len`' are updated at their designed index +fail). 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 +If the hypercall returns -XEN\_E2BIG the `nr` is too big and should be lowered. If the hypercall returns an zero value there are no more payloads. @@ -634,61 +601,59 @@ data and start from scratch. It is OK for the toolstack to use the new The `struct xen_livepatch_status` structure contains an status of payload which includes: * `status` - indicates the current status of the payload: - * *LIVEPATCH_STATUS_CHECKED* (1) loaded and the ELF payload safety checks passed. - * *LIVEPATCH_STATUS_APPLIED* (2) loaded, checked, and applied. + * *LIVEPATCH\_STATUS\_CHECKED* (1) loaded and the ELF payload safety checks passed. + * *LIVEPATCH\_STATUS\_APPLIED* (2) loaded, checked, and applied. * No other value is possible. - * `rc` - -XEN_EXX type errors encountered while performing the last - LIVEPATCH_ACTION_* operation. The normal values can be zero or -XEN_EAGAIN which + * `rc` - -XEN\_EXX type errors encountered while performing the last + LIVEPATCH\_ACTION\_\* operation. The normal values can be zero or -XEN\_EAGAIN which respectively mean: success or operation in progress. Other values imply an error occurred. If there is an error in `rc`, `status` will **NOT** have changed. The structure is as follow: -<pre> -struct xen_sysctl_livepatch_list { - uint32_t version; /* OUT: Hypervisor stamps value. - If varies between calls, we are - getting stale data. */ - uint32_t idx; /* IN: Index into hypervisor list. */ - uint32_t nr; /* IN: How many status, names, and len - should be filled out. Can be zero to get - amount of payloads and version. - OUT: How many payloads left. */ - uint32_t pad; /* IN: Must be zero. */ - 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(uint32) len; /* OUT: Array of lengths of name's. - Must have nr of them. */ -}; -</pre> - -### XEN_SYSCTL_LIVEPATCH_ACTION (3) + struct xen_sysctl_livepatch_list { + uint32_t version; /* OUT: Hypervisor stamps value. + If varies between calls, we are + getting stale data. */ + uint32_t idx; /* IN: Index into hypervisor list. */ + uint32_t nr; /* IN: How many status, names, and len + should be filled out. Can be zero to get + amount of payloads and version. + OUT: How many payloads left. */ + uint32_t pad; /* IN: Must be zero. */ + 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(uint32) len; /* OUT: Array of lengths of name's. + Must have nr of them. */ + }; + +### XEN\_SYSCTL\_LIVEPATCH\_ACTION (3) Perform an operation on the payload structure referenced by the `name` field. The operation request is asynchronous and the status should be retrieved -by using either **XEN_SYSCTL_LIVEPATCH_GET** or **XEN_SYSCTL_LIVEPATCH_LIST** hypercall. +by using either **XEN\_SYSCTL\_LIVEPATCH\_GET** or **XEN\_SYSCTL\_LIVEPATCH\_LIST** hypercall. The caller provides: - * A 'struct xen_livepatch_name` `name` containing the unique name. + * A `struct xen_livepatch_name` `name` containing the unique name. * `cmd` the command requested: - * *LIVEPATCH_ACTION_UNLOAD* (1) unload the payload. + * *LIVEPATCH\_ACTION\_UNLOAD* (1) unload the payload. Any further hypercalls against the `name` will result in failure unless - **XEN_SYSCTL_LIVEPATCH_UPLOAD** hypercall is perfomed with same `name`. - * *LIVEPATCH_ACTION_REVERT* (2) revert the payload. If the operation takes - more time than the upper bound of time the `rc` in `xen_livepatch_status' - retrieved via **XEN_SYSCTL_LIVEPATCH_GET** will be -XEN_EBUSY. - * *LIVEPATCH_ACTION_APPLY* (3) apply the payload. If the operation takes - more time than the upper bound of time the `rc` in `xen_livepatch_status' - retrieved via **XEN_SYSCTL_LIVEPATCH_GET** will be -XEN_EBUSY. - * *LIVEPATCH_ACTION_REPLACE* (4) revert all applied payloads and apply this + **XEN\_SYSCTL\_LIVEPATCH\_UPLOAD** hypercall is perfomed with same `name`. + * *LIVEPATCH\_ACTION\_REVERT* (2) revert the payload. If the operation takes + more time than the upper bound of time the `rc` in `xen_livepatch_status` + retrieved via **XEN\_SYSCTL\_LIVEPATCH\_GET** will be -XEN\_EBUSY. + * *LIVEPATCH\_ACTION\_APPLY* (3) apply the payload. If the operation takes + more time than the upper bound of time the `rc` in `xen_livepatch_status` + retrieved via **XEN\_SYSCTL\_LIVEPATCH\_GET** will be -XEN\_EBUSY. + * *LIVEPATCH\_ACTION\_REPLACE* (4) revert all applied payloads and apply this payload. If the operation takes more time than the upper bound of time - the `rc` in `xen_livepatch_status' retrieved via **XEN_SYSCTL_LIVEPATCH_GET** - will be -XEN_EBUSY. + the `rc` in `xen_livepatch_status` retrieved via **XEN\_SYSCTL\_LIVEPATCH\_GET** + will be -XEN\_EBUSY. * `time` the upper bound of time (ns) the cmd should take. Zero means to use the hypervisor default. If within the time the operation does not succeed the operation would go in error state. @@ -698,71 +663,65 @@ The return value will be zero unless the provided fields are incorrect. The structure is as follow: -<pre> -#define LIVEPATCH_ACTION_UNLOAD 1 -#define LIVEPATCH_ACTION_REVERT 2 -#define LIVEPATCH_ACTION_APPLY 3 -#define LIVEPATCH_ACTION_REPLACE 4 -struct xen_sysctl_livepatch_action { - xen_livepatch_name_t name; /* IN, name of the patch. */ - uint32_t cmd; /* IN: LIVEPATCH_ACTION_* */ - uint32_t time; /* IN: If zero then uses */ - /* hypervisor default. */ - /* Or upper bound of time (ns) */ - /* for operation to take. */ -}; - -</pre> - -## State diagrams of LIVEPATCH_ACTION commands. + #define LIVEPATCH_ACTION_UNLOAD 1 + #define LIVEPATCH_ACTION_REVERT 2 + #define LIVEPATCH_ACTION_APPLY 3 + #define LIVEPATCH_ACTION_REPLACE 4 + struct xen_sysctl_livepatch_action { + xen_livepatch_name_t name; /* IN, name of the patch. */ + uint32_t cmd; /* IN: LIVEPATCH_ACTION_* */ + uint32_t time; /* IN: If zero then uses */ + /* hypervisor default. */ + /* Or upper bound of time (ns) */ + /* for operation to take. */ + }; + + +## State diagrams of LIVEPATCH\_ACTION commands. There is a strict ordering state of what the commands can be. -The LIVEPATCH_ACTION prefix has been dropped to easy reading and -does not include the LIVEPATCH_STATES: +The LIVEPATCH\_ACTION prefix has been dropped to easy reading and +does not include the LIVEPATCH\_STATES: -<pre> - /->\ - \ / - UNLOAD <--- CHECK ---> REPLACE|APPLY --> REVERT --\ - \ | - \-------------------<-------------/ - -</pre> -## State transition table of LIVEPATCH_ACTION commands and LIVEPATCH_STATUS. + /->\ + \ / + UNLOAD <--- CHECK ---> REPLACE|APPLY --> REVERT --\ + \ | + \-------------------<-------------/ + +## State transition table of LIVEPATCH\_ACTION commands and LIVEPATCH\_STATUS. Note that: - - The CHECKED state is the starting one achieved with *XEN_SYSCTL_LIVEPATCH_UPLOAD* hypercall. + - The CHECKED state is the starting one achieved with *XEN\_SYSCTL\_LIVEPATCH\_UPLOAD* hypercall. - The REVERT operation on success will automatically move to the CHECKED state. - There are two STATES: CHECKED and APPLIED. - There are four actions (aka commands): APPLY, REPLACE, REVERT, and UNLOAD. The state transition table of valid states and action states: -<pre> - -+---------+---------+--------------------------------+-------+--------+ -| ACTION | Current | Result | Next STATE: | -| ACTION | STATE | |CHECKED|APPLIED | -+---------+----------+-------------------------------+-------+--------+ -| UNLOAD | CHECKED | Unload payload. Always works. | | | -| | | No next states. | | | -+---------+---------+--------------------------------+-------+--------+ -| APPLY | CHECKED | Apply payload (success). | | x | -+---------+---------+--------------------------------+-------+--------+ -| APPLY | CHECKED | Apply payload (error|timeout) | x | | -+---------+---------+--------------------------------+-------+--------+ -| REPLACE | CHECKED | Revert payloads and apply new | | x | -| | | payload with success. | | | -+---------+---------+--------------------------------+-------+--------+ -| REPLACE | CHECKED | Revert payloads and apply new | x | | -| | | payload with error. | | | -+---------+---------+--------------------------------+-------+--------+ -| REVERT | APPLIED | Revert payload (success). | x | | -+---------+---------+--------------------------------+-------+--------+ -| REVERT | APPLIED | Revert payload (error|timeout) | | x | -+---------+---------+--------------------------------+-------+--------+ -</pre> + + +---------+---------+--------------------------------+-------+--------+ + | ACTION | Current | Result | Next STATE: | + | ACTION | STATE | |CHECKED|APPLIED | + +---------+----------+-------------------------------+-------+--------+ + | UNLOAD | CHECKED | Unload payload. Always works. | | | + | | | No next states. | | | + +---------+---------+--------------------------------+-------+--------+ + | APPLY | CHECKED | Apply payload (success). | | x | + +---------+---------+--------------------------------+-------+--------+ + | APPLY | CHECKED | Apply payload (error|timeout) | x | | + +---------+---------+--------------------------------+-------+--------+ + | REPLACE | CHECKED | Revert payloads and apply new | | x | + | | | payload with success. | | | + +---------+---------+--------------------------------+-------+--------+ + | REPLACE | CHECKED | Revert payloads and apply new | x | | + | | | payload with error. | | | + +---------+---------+--------------------------------+-------+--------+ + | REVERT | APPLIED | Revert payload (success). | x | | + +---------+---------+--------------------------------+-------+--------+ + | REVERT | APPLIED | Revert payload (error|timeout) | | x | + +---------+---------+--------------------------------+-------+--------+ All the other state transitions are invalid. @@ -770,10 +729,10 @@ All the other state transitions are invalid. The normal sequence of events is to: - 1. *XEN_SYSCTL_LIVEPATCH_UPLOAD* to upload the payload. If there are errors *STOP* here. - 2. *XEN_SYSCTL_LIVEPATCH_GET* to check the `->rc`. If *-XEN_EAGAIN* spin. If zero go to next step. - 3. *XEN_SYSCTL_LIVEPATCH_ACTION* with *LIVEPATCH_ACTION_APPLY* to apply the patch. - 4. *XEN_SYSCTL_LIVEPATCH_GET* to check the `->rc`. If in *-XEN_EAGAIN* spin. If zero exit with success. + 1. *XEN\_SYSCTL\_LIVEPATCH\_UPLOAD* to upload the payload. If there are errors *STOP* here. + 2. *XEN\_SYSCTL\_LIVEPATCH\_GET* to check the `->rc`. If *-XEN\_EAGAIN* spin. If zero go to next step. + 3. *XEN\_SYSCTL\_LIVEPATCH\_ACTION* with *LIVEPATCH\_ACTION\_APPLY* to apply the patch. + 4. *XEN\_SYSCTL\_LIVEPATCH\_GET* to check the `->rc`. If in *-XEN\_EAGAIN* spin. If zero exit with success. ## Addendum @@ -807,18 +766,18 @@ minimize the chance of the patch not being applied due to safety checks failing. Safety checks such as not patching code which is on the stack - which can lead to corruption. -#### Rendezvous code instead of stop_machine for patching +#### Rendezvous code instead of stop\_machine for patching The hypervisor's time rendezvous code runs synchronously across all CPUs -every second. Using the stop_machine to patch can stall the time rendezvous +every second. Using the stop\_machine to patch can stall the time rendezvous code and result in NMI. As such having the patching be done at the tail of rendezvous code should avoid this problem. However the entrance point for that code is -do_softirq->timer_softirq_action->time_calibration -which ends up calling on_selected_cpus on remote CPUs. +do\_softirq->timer\_softirq\_action->time\_calibration +which ends up calling on\_selected\_cpus on remote CPUs. -The remote CPUs receive CALL_FUNCTION_VECTOR IPI and execute the +The remote CPUs receive CALL\_FUNCTION\_VECTOR IPI and execute the desired function. #### Before entering the guest code. @@ -832,7 +791,7 @@ could be adjusted), combined with forcing all other CPUs through the hypervisor with IPIs, can be utilized to execute lockstep instructions on all CPUs. -The approach is similar in concept to stop_machine and the time rendezvous +The approach is similar in concept to stop\_machine and the time rendezvous but is time-bound. However the local CPU stack is much shorter and a lot more deterministic. @@ -967,10 +926,10 @@ The implementation must also have a mechanism for (in no particular order): the stack, make sure the payload is built with same compiler as hypervisor). Specifically we want to make sure that live patching codepaths cannot be patched. * NOP out the code sequence if `new_size` is zero. - * Deal with other relocation types: R_X86_64_[8,16,32,32S], R_X86_64_PC[8,16,64] + * Deal with other relocation types: R\_X86\_64\_[8,16,32,32S], R\_X86\_64\_PC[8,16,64] in payload file. -### Handle inlined __LINE__ +### Handle inlined \_\_LINE\_\_ This problem is related to hotpatch construction and potentially has influence on the design of the hotpatching @@ -1030,7 +989,7 @@ Options: For BUG(), WARN(), etc., the line number is embedded into the bug frame, not the function itself. -Similar considerations are true to a lesser extent for __FILE__, but it +Similar considerations are true to a lesser extent for \_\_FILE\_\_, but it could be argued that file renaming should be done outside of hotpatches. ## Signature checking requirements. @@ -1042,49 +1001,47 @@ expecting such that it can properly do signature verification. The signature is based on the all of the payloads continuously laid out in memory. The signature is to be appended at the end of the ELF payload -prefixed with the string `'~Module signature appended~\n'`, followed by +prefixed with the string '`~Module signature appended~\n`', followed by an signature header then followed by the signature, key identifier, and signers name. Specifically the signature header would be: -<pre> -#define PKEY_ALGO_DSA 0 -#define PKEY_ALGO_RSA 1 - -#define PKEY_ID_PGP 0 /* OpenPGP generated key ID */ -#define PKEY_ID_X509 1 /* X.509 arbitrary subjectKeyIdentifier */ - -#define HASH_ALGO_MD4 0 -#define HASH_ALGO_MD5 1 -#define HASH_ALGO_SHA1 2 -#define HASH_ALGO_RIPE_MD_160 3 -#define HASH_ALGO_SHA256 4 -#define HASH_ALGO_SHA384 5 -#define HASH_ALGO_SHA512 6 -#define HASH_ALGO_SHA224 7 -#define HASH_ALGO_RIPE_MD_128 8 -#define HASH_ALGO_RIPE_MD_256 9 -#define HASH_ALGO_RIPE_MD_320 10 -#define HASH_ALGO_WP_256 11 -#define HASH_ALGO_WP_384 12 -#define HASH_ALGO_WP_512 13 -#define HASH_ALGO_TGR_128 14 -#define HASH_ALGO_TGR_160 15 -#define HASH_ALGO_TGR_192 16 - - -struct elf_payload_signature { - u8 algo; /* Public-key crypto algorithm PKEY_ALGO_*. */ - u8 hash; /* Digest algorithm: HASH_ALGO_*. */ - u8 id_type; /* Key identifier type PKEY_ID*. */ - u8 signer_len; /* Length of signer's name */ - u8 key_id_len; /* Length of key identifier */ - u8 __pad[3]; - __be32 sig_len; /* Length of signature data */ -}; - -</pre> + #define PKEY_ALGO_DSA 0 + #define PKEY_ALGO_RSA 1 + + #define PKEY_ID_PGP 0 /* OpenPGP generated key ID */ + #define PKEY_ID_X509 1 /* X.509 arbitrary subjectKeyIdentifier */ + + #define HASH_ALGO_MD4 0 + #define HASH_ALGO_MD5 1 + #define HASH_ALGO_SHA1 2 + #define HASH_ALGO_RIPE_MD_160 3 + #define HASH_ALGO_SHA256 4 + #define HASH_ALGO_SHA384 5 + #define HASH_ALGO_SHA512 6 + #define HASH_ALGO_SHA224 7 + #define HASH_ALGO_RIPE_MD_128 8 + #define HASH_ALGO_RIPE_MD_256 9 + #define HASH_ALGO_RIPE_MD_320 10 + #define HASH_ALGO_WP_256 11 + #define HASH_ALGO_WP_384 12 + #define HASH_ALGO_WP_512 13 + #define HASH_ALGO_TGR_128 14 + #define HASH_ALGO_TGR_160 15 + #define HASH_ALGO_TGR_192 16 + + + struct elf_payload_signature { + u8 algo; /* Public-key crypto algorithm PKEY_ALGO_*. */ + u8 hash; /* Digest algorithm: HASH_ALGO_*. */ + u8 id_type; /* Key identifier type PKEY_ID*. */ + u8 signer_len; /* Length of signer's name */ + u8 key_id_len; /* Length of key identifier */ + u8 __pad[3]; + __be32 sig_len; /* Length of signature data */ + }; + (Note that this has been borrowed from Linux module signature code.). @@ -1128,15 +1085,13 @@ at least five bytes if patching in trampoline. Depending on compiler settings, there are several functions in Xen that are smaller (without inter-function padding). -<pre> -readelf -sW xen-syms | grep " FUNC " | \ - awk '{ if ($3 < 5) print $3, $4, $5, $8 }' - -... -3 FUNC LOCAL wbinvd_ipi -3 FUNC LOCAL shadow_l1_index -... -</pre> + readelf -sW xen-syms | grep " FUNC " | \ + awk '{ if ($3 < 5) print $3, $4, $5, $8 }' + + ... + 3 FUNC LOCAL wbinvd_ipi + 3 FUNC LOCAL shadow_l1_index + ... A compile-time check for, e.g., a minimum alignment of functions or a runtime check that verifies symbol size (+ padding to next symbols) for that in the hypervisor is advised. -- 2.13.6 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |