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

Re: [Minios-devel] [UNIKRAFT PATCH] lib/ukboot: Fix handling of main arguments



Hi Simon,

Please see inline.

On 6/6/19 3:34 PM, Simon Kuenzer wrote:
> Hey Costin,
> 
> On 06.06.19, 12:30, "Costin Lupu" <costin.lup@xxxxxxxxx> wrote:
> 
>     Hi Simon,
>     
>     I've read your comments but I couldn't find out why you don't agree with
>     global approach. So, what are the reasons why you would prefer declaring
>     the arguments static rather than global?
> 
> The change that I mention as alternative is minimal and less invasive to the 
> existing code. You do not need to add it as exported symbol and most code can 
> stay as is. I also do not see why we would need the global approach. Do you 
> have a use case? I think this is conflicting how argc and argv is intended to 
> be used: The idea about them is that they are private to your main() function 
> of your program (ukplat_entry() in our case). It can do whatever with it and 
> this does not have any effect on something else.
> As an example you can take getopt(): It starts re-ordering the pointers on 
> argv for doing its argument parsing.
> On a global and shared data structure you would not want this.

Yeah, that's what I was looking for. Thanks for the explanations. I'll
send a v2 making the argv array static.

> 
>     Personally I find making the arguments global to be more elegant and
>     offer a unified approach, since they would have the same location for
>     all platforms.
>     
>     Also, please see a comment inline.
>     
>     On 6/6/19 12:34 PM, Simon Kuenzer wrote:
>     > Hey Costin,
>     > 
>     > thanks a lot for the patch. I think the actual problem is that the boot
>     > stack could be released later after boot for something else, so it is
>     > not guaranteed anymore that the arguments are safe and staying.
>     > However, I don't agree to make argv and argc global available. Just
>     > allocate them in the bss section.
>     > See my comments inline.
>     > 
>     > On 05.06.19 21:55, Costin Lupu wrote:
>     >> When the command line is parsed and split into arguments, each argument
>     >> is saved in an array of pointers allocated on the stack ('argv' array 
> in
>     >> ukplat_entry_argp()). This means that the array can be overwritten any
>     >> time before starting the main thread which needs the arguments. This
>     >> patch fixes that by making the array global, encapsulated by the
>     >> 'main_arg' structure.
>     >>
>     >> Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx>
>     >> ---
>     >>   include/uk/plat/bootstrap.h | 11 ++++++++++-
>     >>   lib/ukboot/boot.c           | 33 ++++++++++++---------------------
>     >>   lib/ukboot/exportsyms.uk    |  1 +
>     >>   plat/linuxu/setup.c         |  7 ++++++-
>     >>   4 files changed, 29 insertions(+), 23 deletions(-)
>     >>
>     >> diff --git a/include/uk/plat/bootstrap.h b/include/uk/plat/bootstrap.h
>     >> index 0652ccd1..a9e404e8 100644
>     >> --- a/include/uk/plat/bootstrap.h
>     >> +++ b/include/uk/plat/bootstrap.h
>     >> @@ -36,6 +36,7 @@
>     >>   #ifndef __UKPLAT_BOOTSTRAP__
>     >>   #define __UKPLAT_BOOTSTRAP__
>     >>   +#include <uk/config.h>
>     >>   #include <uk/arch/types.h>
>     >>   #include <uk/essentials.h>
>     >>   @@ -43,6 +44,14 @@
>     >>   extern "C" {
>     >>   #endif
>     >>   +/* Main arguments structure */
>     >> +struct main_arg {
>     >> +    int argc;
>     >> +    char *argv[CONFIG_LIBUKBOOT_MAXNBARGS];
>     >> +};
>     >> +/* Main arguments */
>     >> +extern struct main_arg global_main_arg;
>     >> +
>     >>   /**
>     >>    * Called by platform library during initialization
>     >>    * This function has to be provided by a non-platform library for
>     >> bootstrapping
>     >> @@ -52,7 +61,7 @@ extern "C" {
>     >>    * @param argc Number of arguments
>     >>    * @param args Array to '\0'-terminated arguments
>     >>    */
>     >> -void ukplat_entry(int argc, char *argv[]) __noreturn;
>     >> +void ukplat_entry(struct main_arg *arg) __noreturn;
>     >>     /**
>     >>    * Called by platform library during initialization
>     >> diff --git a/lib/ukboot/boot.c b/lib/ukboot/boot.c
>     >> index 4dcc0afb..5cc3b573 100644
>     >> --- a/lib/ukboot/boot.c
>     >> +++ b/lib/ukboot/boot.c
>     >> @@ -68,17 +68,13 @@ extern int liblwip_init(void);
>     >>   #endif /* CONFIG_LIBLWIP */
>     >>     static void main_thread_func(void *arg) __noreturn;
>     >> -
>     >> -struct thread_main_arg {
>     >> -    int argc;
>     >> -    char **argv;
>     >> -};
>     >> +struct main_arg global_main_arg;
>     >>     static void main_thread_func(void *arg)
>     >>   {
>     >>       int i;
>     >>       int ret;
>     >> -    struct thread_main_arg *tma = arg;
>     >> +    struct main_arg *tma = arg;
>     >>         uk_pr_info("Pre-init table at %p - %p\n",
>     >>              __preinit_array_start, &__preinit_array_end);
>     >> @@ -145,26 +141,26 @@ static void main_thread_func(void *arg)
>     >>   /* defined in <uk/plat.h> */
>     >>   void ukplat_entry_argp(char *arg0, char *argb, __sz argb_len)
>     >>   {
>     >> -    char *argv[CONFIG_LIBUKBOOT_MAXNBARGS];
>     > 
>     > Just declare
>     >     char *argv[CONFIG_LIBUKBOOT_MAXNBARGS];
>     > as
>     >     static char *argv[CONFIG_LIBUKBOOT_MAXNBARGS];
>     > 
>     > The same for argc.
> 
> Actually, we do not need to declare `argc` as static, only `argv`. I was 
> wrong. `argc` is anyways handed over by-value on a function call, not 
> by-reference (like argv) - so we are good.
> 
>     > 
>     > We also need to double-check that our string buffer with the arguments
>     > (where argv is pointing to), is not allocated on the stack in the
>     > platform. If this is the case, we are safe.
>     > 
>     
>     I'm not sure I follow this, you mean to check if the strings aren't
>     allocated on this stack? Or to check if it comes from bss?
> 
> In case the boot stack is released or used for something else, there should 
> be no reference to it. The buffer where the strings are stored (and where the 
> pointers of argv are pointing to) shouldn't be on the stack either. I 
> mentioned this because I wanted to say that we should double check that our 
> platform are storing this buffer on something else than the stack.
>     

I'd rather not add this to the next version because it needs substantial
changes in order to access the bootstack.

>     >> -    int argc = 0;
>     >> +    global_main_arg.argc = 0;
>     >>         if (arg0) {
>     >> -        argv[0] = arg0;
>     >> -        argc += 1;
>     >> +        global_main_arg.argv[0] = arg0;
>     >> +        global_main_arg.argc += 1;
>     >>       }
>     >>       if (argb && argb_len) {
>     >> -        argc += uk_argnparse(argb, argb_len, arg0 ? &argv[1] : 
> &argv[0],
>     >> +        global_main_arg.argc += uk_argnparse(argb, argb_len,
>     >> +                     arg0 ? &global_main_arg.argv[1]
>     >> +                      : &global_main_arg.argv[0],
>     >>                        arg0 ? (CONFIG_LIBUKBOOT_MAXNBARGS - 1)
>     >>                         : CONFIG_LIBUKBOOT_MAXNBARGS);
>     >>       }
>     >> -    ukplat_entry(argc, argv);
>     >> +    ukplat_entry(&global_main_arg);
>     > 
>     > If you declare the arguments as global you do not need to hand them over
>     > anymore, but as I said I would not change this at all.
>     > 
>     >>   }
>     >>     /* defined in <uk/plat.h> */
>     >> -void ukplat_entry(int argc, char *argv[])
>     >> +void ukplat_entry(struct main_arg *arg)
>     >>   {
>     >>       const uk_ctor_func_t *cfn;
>     >> -    struct thread_main_arg tma;
>     >>   #if CONFIG_LIBUKALLOC
>     >>       struct uk_alloc *a = NULL;
>     >>       int rc;
>     >> @@ -234,19 +230,14 @@ void ukplat_entry(int argc, char *argv[])
>     >>       s = uk_sched_default_init(a);
>     >>       if (unlikely(!s))
>     >>           UK_CRASH("Could not initialize the scheduler\n");
>     >> -#endif
>     >>   -    tma.argc = argc;
>     >> -    tma.argv = argv;
>     >> -
>     >> -#if CONFIG_LIBUKSCHED
>     >> -    main_thread = uk_thread_create("main", main_thread_func, &tma);
>     >> +    main_thread = uk_thread_create("main", main_thread_func, arg);
>     >>       if (unlikely(!main_thread))
>     >>           UK_CRASH("Could not create main thread\n");
>     >>       uk_sched_start(s);
>     >>   #else
>     >>       /* Enable interrupts before starting the application */
>     >>       ukplat_lcpu_enable_irq();
>     >> -    main_thread_func(&tma);
>     >> +    main_thread_func(arg);
>     >>   #endif
>     >>   }
>     >> diff --git a/lib/ukboot/exportsyms.uk b/lib/ukboot/exportsyms.uk
>     >> index 3edc6c6a..adbb84fb 100644
>     >> --- a/lib/ukboot/exportsyms.uk
>     >> +++ b/lib/ukboot/exportsyms.uk
>     >> @@ -1,3 +1,4 @@
>     >>   ukplat_entry_argp
>     >>   ukplat_entry
>     >> +global_main_arg
>     >>   main
>     >> diff --git a/plat/linuxu/setup.c b/plat/linuxu/setup.c
>     >> index 50454437..4f6f5688 100644
>     >> --- a/plat/linuxu/setup.c
>     >> +++ b/plat/linuxu/setup.c
>     >> @@ -172,6 +172,11 @@ void _liblinuxuplat_entry(int argc, char *argv[])
>     >>       argv += (ret - 1);
>     >>       argv[0] = progname;
>     > 
>     > Make also sure that argv and argc are declared as static here, instead.
>     > 
>     >>   +    /* Setup global arguments */
>     >> +    global_main_arg.argc = argc;
>     >> +    for (int i = 0; i < argc; i++)
>     >> +        global_main_arg.argv[i] = argv[i];
>     >> +
>     >>       /*
>     >>        * Allocate heap memory
>     >>        */
>     >> @@ -186,5 +191,5 @@ void _liblinuxuplat_entry(int argc, char *argv[])
>     >>       /*
>     >>        * Enter Unikraft
>     >>        */
>     >> -    ukplat_entry(argc, argv);
>     >> +    ukplat_entry(&global_main_arg);
>     >>   }
>     >>
>     > 
>     > Thanks,
>     > 
>     > Simon
>     > 
>     > _______________________________________________
>     > Minios-devel mailing list
>     > Minios-devel@xxxxxxxxxxxxxxxxxxxx
>     > https://lists.xenproject.org/mailman/listinfo/minios-devel
>     
> 

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

 


Rackspace

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