Re: [PATCH] kconfig: Prevent segfault when getting filename

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

 



On Tue, Jun 18, 2024 at 6:37 PM Masahiro Yamada <masahiroy@xxxxxxxxxx> wrote:
>
> On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@xxxxxxxxxx> wrote:
> >
> > ... and lineno in recursive checks.
> >
> > If the following snippet is found in Kconfig:
> >
> > config FOO
> >         tristate
> >         depends on BAR
> >         select BAR
> >         help
> >           foo
> >
> > ... without BAR defined; then if one runs
> > `make tinyconfig`, there is a segfault.
> >
> >   Kconfig:34:error: recursive dependency detected!
> >   Kconfig:34:   symbol FOO depends on BAR
> >   make[4]: *** [scripts/kconfig/Makefile:85: allnoconfig] Segmentation fault
> >
> > This is because of the following. BAR is
> > a fake entry created by sym_lookup() with prop
> > being NULL. In the recursive check, there is a
> > NULL check for prop to fall back to
> > stack->sym->prop if stack->prop is NULL. However,
> > in this case, stack->sym points to the fake BAR
> > entry created by sym_lookup(), so prop is still
> > NULL. prop was then referenced without additional
> > NULL checks, causing segfault.
> >
> > Similarly, menu is also accessed without NULL
> > checks. However, sym_lookup() creates entry
> > that is not a choice, so technically it shouldn't
> > fall into the state where menu is NULL for
> > choices. But I mechnically apply the NULL check
> > anyways for completeness.
> >
> > This mechnical patch avoids the segfault. The
> > above snippet produces the following error with
> > this patch:
> >
> >   Kconfig:34:error: recursive dependency detected!
> >   Kconfig:34:   symbol FOO depends on BAR
> >   ???:-1:       symbol BAR is selected by FOO
> >
> > That being said, I am not sure if it is the right
> > fix conceptually and in functionality.
>
>
>
>   "???:-1:       symbol BAR is selected by FOO"
>
> is weird, as there is no property
> like "selected by".
>
> It should print the file and lineno of
> "select BAR".
>
>
>
>
>
> The existing code is already wrong.
>
> In the past, I was thinking of fixing it to reference
> the relevant menu entry.
>
>
> Currently, it points to an unrelated location.
>
>
>
> [Test Code]
>
>
> config FOO
>        bool
>
> config BAR
>        bool
>
> config FOO
>        bool "FOO"
>        depends on BAR
>        select BAR
>
>
>
>
> $ make defconfig
> *** Default configuration is based on 'x86_64_defconfig'
> Kconfig:1:error: recursive dependency detected!
> Kconfig:1: symbol FOO depends on BAR
> Kconfig:4: symbol BAR is selected by FOO
> For a resolution refer to Documentation/kbuild/kconfig-language.rst
> subsection "Kconfig recursive dependency limitations"
>
>
>
>
> "Kconfig:1: symbol FOO depends on BAR"
> points to the other unrelated definition
> because "depends on BAR" appears the second
> entry starting line 7.
>
>
>
>
> So, I am not keen on applying another cheap fix
> to already-wrong code.
>
> If you want to fix it now, please remove all
> file/lineno logs from this function.

Thanks for your reply, Masahiro!

Do you mean to delete the file/lineno for "selected by" only, or for the whole
sym_check_print_recursive function? It appears to me that some file/lineno
information (Like `Kconfig:1: symbol FOO` above) is still useful. I
agree that the
`Kconfig:4` is wrong, though.

I think a segfault indicates that the program is
not robust against bad user input. In my opinion, it should fail gracefully with
some information to tell the user. I wish I can fix this properly; but
unfortunately
I am not too familiar with this code. That was why I only provided a
mechanical fix.

I am happy to remove the file/lineno's; I just want to confirm which to remove.

>
> Then, somebody may rewrite the code some day.
>
>
>
>
>
>
>
>
>
>
> >
> > Signed-off-by: Yifan Hong <elsk@xxxxxxxxxx>
> > ---
> >  scripts/kconfig/symbol.c | 29 +++++++++++++++++++++--------
> >  1 file changed, 21 insertions(+), 8 deletions(-)
> >
> > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
> > index 8df0a75f40b9..72ab4f274289 100644
> > --- a/scripts/kconfig/symbol.c
> > +++ b/scripts/kconfig/symbol.c
> > @@ -1045,6 +1045,8 @@ static void sym_check_print_recursive(struct symbol *last_sym)
> >         struct menu *menu = NULL;
> >         struct property *prop;
> >         struct dep_stack cv_stack;
> > +       const char *filename = NULL;
> > +       int lineno = 0;
> >
> >         if (sym_is_choice_value(last_sym)) {
> >                 dep_stack_insert(&cv_stack, last_sym);
> > @@ -1060,6 +1062,10 @@ static void sym_check_print_recursive(struct symbol *last_sym)
> >         }
> >
> >         for (; stack; stack = stack->next) {
> > +               filename = "???";
> > +               lineno = 0;
> > +               menu = NULL;
> > +
> >                 sym = stack->sym;
> >                 next_sym = stack->next ? stack->next->sym : last_sym;
> >                 prop = stack->prop;
> > @@ -1073,45 +1079,52 @@ static void sym_check_print_recursive(struct symbol *last_sym)
> >                                 if (prop->menu)
> >                                         break;
> >                         }
> > +                       if (menu) {
> > +                               filename = menu->filename;
> > +                               lineno = menu->lineno;
> > +                       }
> > +               } else if (prop) {
> > +                       filename = prop->filename;
> > +                       lineno = prop->lineno;
> >                 }
> >                 if (stack->sym == last_sym)
> >                         fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
> > -                               prop->filename, prop->lineno);
> > +                               filename, lineno);
> >
> >                 if (sym_is_choice(sym)) {
> >                         fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
> > -                               menu->filename, menu->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (sym_is_choice_value(sym)) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
> > -                               menu->filename, menu->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr == &sym->dir_dep.expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr == &sym->rev_dep.expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr == &sym->implied.expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 prop_get_type_name(prop->type),
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 prop_get_type_name(prop->type),
> >                                 next_sym->name ? next_sym->name : "<choice>");
> > --
> > 2.45.2.627.g7a2c4fd464-goog
> >
> >
>
>
> --
> Best Regards
> Masahiro Yamada


On Tue, Jun 18, 2024 at 6:37 PM Masahiro Yamada <masahiroy@xxxxxxxxxx> wrote:
>
> On Wed, Jun 19, 2024 at 3:56 AM Yifan Hong <elsk@xxxxxxxxxx> wrote:
> >
> > ... and lineno in recursive checks.
> >
> > If the following snippet is found in Kconfig:
> >
> > config FOO
> >         tristate
> >         depends on BAR
> >         select BAR
> >         help
> >           foo
> >
> > ... without BAR defined; then if one runs
> > `make tinyconfig`, there is a segfault.
> >
> >   Kconfig:34:error: recursive dependency detected!
> >   Kconfig:34:   symbol FOO depends on BAR
> >   make[4]: *** [scripts/kconfig/Makefile:85: allnoconfig] Segmentation fault
> >
> > This is because of the following. BAR is
> > a fake entry created by sym_lookup() with prop
> > being NULL. In the recursive check, there is a
> > NULL check for prop to fall back to
> > stack->sym->prop if stack->prop is NULL. However,
> > in this case, stack->sym points to the fake BAR
> > entry created by sym_lookup(), so prop is still
> > NULL. prop was then referenced without additional
> > NULL checks, causing segfault.
> >
> > Similarly, menu is also accessed without NULL
> > checks. However, sym_lookup() creates entry
> > that is not a choice, so technically it shouldn't
> > fall into the state where menu is NULL for
> > choices. But I mechnically apply the NULL check
> > anyways for completeness.
> >
> > This mechnical patch avoids the segfault. The
> > above snippet produces the following error with
> > this patch:
> >
> >   Kconfig:34:error: recursive dependency detected!
> >   Kconfig:34:   symbol FOO depends on BAR
> >   ???:-1:       symbol BAR is selected by FOO
> >
> > That being said, I am not sure if it is the right
> > fix conceptually and in functionality.
>
>
>
>   "???:-1:       symbol BAR is selected by FOO"
>
> is weird, as there is no property
> like "selected by".
>
> It should print the file and lineno of
> "select BAR".
>
>
>
>
>
> The existing code is already wrong.
>
> In the past, I was thinking of fixing it to reference
> the relevant menu entry.
>
>
> Currently, it points to an unrelated location.
>
>
>
> [Test Code]
>
>
> config FOO
>        bool
>
> config BAR
>        bool
>
> config FOO
>        bool "FOO"
>        depends on BAR
>        select BAR
>
>
>
>
> $ make defconfig
> *** Default configuration is based on 'x86_64_defconfig'
> Kconfig:1:error: recursive dependency detected!
> Kconfig:1: symbol FOO depends on BAR
> Kconfig:4: symbol BAR is selected by FOO
> For a resolution refer to Documentation/kbuild/kconfig-language.rst
> subsection "Kconfig recursive dependency limitations"
>
>
>
>
> "Kconfig:1: symbol FOO depends on BAR"
> points to the other unrelated definition
> because "depends on BAR" appears the second
> entry starting line 7.
>
>
>
>
> So, I am not keen on applying another cheap fix
> to already-wrong code.
>
> If you want to fix it now, please remove all
> file/lineno logs from this function.
>
> Then, somebody may rewrite the code some day.
>
>
>
>
>
>
>
>
>
>
> >
> > Signed-off-by: Yifan Hong <elsk@xxxxxxxxxx>
> > ---
> >  scripts/kconfig/symbol.c | 29 +++++++++++++++++++++--------
> >  1 file changed, 21 insertions(+), 8 deletions(-)
> >
> > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
> > index 8df0a75f40b9..72ab4f274289 100644
> > --- a/scripts/kconfig/symbol.c
> > +++ b/scripts/kconfig/symbol.c
> > @@ -1045,6 +1045,8 @@ static void sym_check_print_recursive(struct symbol *last_sym)
> >         struct menu *menu = NULL;
> >         struct property *prop;
> >         struct dep_stack cv_stack;
> > +       const char *filename = NULL;
> > +       int lineno = 0;
> >
> >         if (sym_is_choice_value(last_sym)) {
> >                 dep_stack_insert(&cv_stack, last_sym);
> > @@ -1060,6 +1062,10 @@ static void sym_check_print_recursive(struct symbol *last_sym)
> >         }
> >
> >         for (; stack; stack = stack->next) {
> > +               filename = "???";
> > +               lineno = 0;
> > +               menu = NULL;
> > +
> >                 sym = stack->sym;
> >                 next_sym = stack->next ? stack->next->sym : last_sym;
> >                 prop = stack->prop;
> > @@ -1073,45 +1079,52 @@ static void sym_check_print_recursive(struct symbol *last_sym)
> >                                 if (prop->menu)
> >                                         break;
> >                         }
> > +                       if (menu) {
> > +                               filename = menu->filename;
> > +                               lineno = menu->lineno;
> > +                       }
> > +               } else if (prop) {
> > +                       filename = prop->filename;
> > +                       lineno = prop->lineno;
> >                 }
> >                 if (stack->sym == last_sym)
> >                         fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
> > -                               prop->filename, prop->lineno);
> > +                               filename, lineno);
> >
> >                 if (sym_is_choice(sym)) {
> >                         fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
> > -                               menu->filename, menu->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (sym_is_choice_value(sym)) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
> > -                               menu->filename, menu->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr == &sym->dir_dep.expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr == &sym->rev_dep.expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr == &sym->implied.expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else if (stack->expr) {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 prop_get_type_name(prop->type),
> >                                 next_sym->name ? next_sym->name : "<choice>");
> >                 } else {
> >                         fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
> > -                               prop->filename, prop->lineno,
> > +                               filename, lineno,
> >                                 sym->name ? sym->name : "<choice>",
> >                                 prop_get_type_name(prop->type),
> >                                 next_sym->name ? next_sym->name : "<choice>");
> > --
> > 2.45.2.627.g7a2c4fd464-goog
> >
> >
>
>
> --
> Best Regards
> Masahiro Yamada





[Index of Archives]     [Linux&nblp;USB Development]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite Secrets]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux