Message ID | 20190821081931.90887-11-wipawel@amazon.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | livepatch: new features and fixes | expand |
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.
> 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
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,
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
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