|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |