[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [livepatch: independ. modules v2 2/3] livepatch: Allow to override inter-modules buildid dependency



> On 20. Aug 2019, at 15:35, Julien Grall <julien.grall@xxxxxxx> wrote:
> 
> Hi,
> 
> Something looks fishy in the threading:
> 
>  - The patch #1 is answered in reply-to the patch #1 of version 1.
>  - This patch (#2) is answered in reply-to the patch #2 of version 1.
>  - The patch #3 is labeled as v3 an in reply-to the patch #3 of version 1.
> 
> If you send them as series, then they should be sent together for a new 
> version and in a new thread. Not mangled to the previous thread as this makes 
> quite difficult to follow what's going on.
> 
> Also it looks like the series is still lacking of the cover letter. So I 
> still have no clue what "livepatch: independ. modules" in your [...] refers 
> to.
> 

Yeah, since I got feedback and reviews on various patches that I have already 
submitted the way I did,
I simply continue with what I have until all comments are addressed (I do not 
want to lose anything).

Then, I will re-send the patches in 2 series: livepatch-build-tools and xen 
with all changes,
Reviewed-by/Acked-by and cover letters. This is the way recommended by Andrew.

Unfortunately, it will be also quite confusing I think, because various changes 
belonging to different topics,
are distributed between those 2 distinct repos. 

Best,
Pawel

> Cheers,
> 
> On 20/08/2019 14:28, Pawel Wieczorkiewicz wrote:
>> 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@xxxxxxxxx>
>> Reviewed-by: Andra-Irina Paraschiv <andraprs@xxxxxxxxxx>
>> Reviewed-by: Eslam Elnikety <elnikety@xxxxxxxxx>
>> Reviewed-by: Petre Eftime <epetre@xxxxxxxxxx>
>> Reviewed-by: Leonard Foerster <foersleo@xxxxxxxxx>
>> Reviewed-by: Martin Pohlack <mpohlack@xxxxxxxxx>
>> Reviewed-by: Norbert Manthey <nmanthey@xxxxxxxxx>
>> ---
>> v2:
>> * Bump XEN_SYSCTL_INTERFACE_VERSION to 0x00000013
>> ---
>>  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 {
> 
> -- 
> Julien Grall




Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Ralf Herbrich
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879




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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.