[v3] lib/stackdepot: Fix global out-of-bounds in stackdepot
diff mbox series

Message ID 20200130064430.17198-1-walter-zh.wu@mediatek.com
State New
Headers show
Series
  • [v3] lib/stackdepot: Fix global out-of-bounds in stackdepot
Related show

Commit Message

Walter Wu Jan. 30, 2020, 6:44 a.m. UTC
If the depot_index = STACK_ALLOC_MAX_SLABS - 2 and next_slab_inited = 0,
then it will cause array out-of-bounds access, so that we should modify
the detection to avoid this array out-of-bounds bug.

Assume depot_index = STACK_ALLOC_MAX_SLABS - 3
Consider following call flow sequence:

stack_depot_save()
   depot_alloc_stack()
      if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
      depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 2
      if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) //enter
         smp_store_release(&next_slab_inited, 0); //next_slab_inited = 0
      init_stack_slab()
         if (stack_slabs[depot_index] == NULL) //enter and exit

stack_depot_save()
   depot_alloc_stack()
      if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
      depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 1
      init_stack_slab(&prealloc)
         stack_slabs[depot_index + 1]  //here get global out-of-bounds

Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Alexander Potapenko <glider@google.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kate Stewart <kstewart@linuxfoundation.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Kate Stewart <kstewart@linuxfoundation.org>
Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
---
changes in v2:
modify call flow sequence and preconditon

changes in v3:
add some reviewers
---
 lib/stackdepot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Alexander Potapenko Jan. 30, 2020, 12:03 p.m. UTC | #1
On Thu, Jan 30, 2020 at 7:44 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:

Hi Walter,

> If the depot_index = STACK_ALLOC_MAX_SLABS - 2 and next_slab_inited = 0,
> then it will cause array out-of-bounds access, so that we should modify
> the detection to avoid this array out-of-bounds bug.
>
> Assume depot_index = STACK_ALLOC_MAX_SLABS - 3
> Consider following call flow sequence:
>
> stack_depot_save()
>    depot_alloc_stack()
>       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
>       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 2
>       if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) //enter
>          smp_store_release(&next_slab_inited, 0); //next_slab_inited = 0
>       init_stack_slab()
>          if (stack_slabs[depot_index] == NULL) //enter and exit
>
> stack_depot_save()
>    depot_alloc_stack()
>       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
>       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 1
>       init_stack_slab(&prealloc)
>          stack_slabs[depot_index + 1]  //here get global out-of-bounds
>
> Cc: Dmitry Vyukov <dvyukov@google.com>
> Cc: Matthias Brugger <matthias.bgg@gmail.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Alexander Potapenko <glider@google.com>
> Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> Cc: Kate Stewart <kstewart@linuxfoundation.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Kate Stewart <kstewart@linuxfoundation.org>
> Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
> ---
> changes in v2:
> modify call flow sequence and preconditon
>
> changes in v3:
> add some reviewers
> ---
>  lib/stackdepot.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> index ed717dd08ff3..7e8a15e41600 100644
> --- a/lib/stackdepot.c
> +++ b/lib/stackdepot.c
> @@ -106,7 +106,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
>         required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
>
>         if (unlikely(depot_offset + required_size > STACK_ALLOC_SIZE)) {
> -               if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) {
> +               if (unlikely(depot_index + 2 >= STACK_ALLOC_MAX_SLABS)) {

I don't think this is the right way to fix the problem.
You're basically throwing away the last element of stack_slabs[], as
we won't allocate anything from it.

How about we set |next_slab_inited| to 1 here:

diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 2e7d2232ed3c..943a51eb746d 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -105,6 +105,8 @@ static bool init_stack_slab(void **prealloc)
                return true;
        if (stack_slabs[depot_index] == NULL) {
                stack_slabs[depot_index] = *prealloc;
+               if (depot_index + 1 == STACK_ALLOC_MAX_SLABS)
+                       smp_store_release(&next_slab_inited, 1);
        } else {
                stack_slabs[depot_index + 1] = *prealloc;
                /*

This will ensure we won't be preallocating pages once |depot_index|
reaches the last element, and we won't attempt to write those pages
anywhere either.

Could you please check if this fixes the problem for you?

>                         WARN_ONCE(1, "Stack depot reached limit capacity");
>                         return NULL;
>                 }
> --
> 2.18.0
Walter Wu Jan. 31, 2020, 2:05 a.m. UTC | #2
On Thu, 2020-01-30 at 13:03 +0100, Alexander Potapenko wrote:
> On Thu, Jan 30, 2020 at 7:44 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> 
> Hi Walter,
> 
> > If the depot_index = STACK_ALLOC_MAX_SLABS - 2 and next_slab_inited = 0,
> > then it will cause array out-of-bounds access, so that we should modify
> > the detection to avoid this array out-of-bounds bug.
> >
> > Assume depot_index = STACK_ALLOC_MAX_SLABS - 3
> > Consider following call flow sequence:
> >
> > stack_depot_save()
> >    depot_alloc_stack()
> >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 2
> >       if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) //enter
> >          smp_store_release(&next_slab_inited, 0); //next_slab_inited = 0
> >       init_stack_slab()
> >          if (stack_slabs[depot_index] == NULL) //enter and exit
> >
> > stack_depot_save()
> >    depot_alloc_stack()
> >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 1
> >       init_stack_slab(&prealloc)
> >          stack_slabs[depot_index + 1]  //here get global out-of-bounds
> >
> > Cc: Dmitry Vyukov <dvyukov@google.com>
> > Cc: Matthias Brugger <matthias.bgg@gmail.com>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Alexander Potapenko <glider@google.com>
> > Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
> > ---
> > changes in v2:
> > modify call flow sequence and preconditon
> >
> > changes in v3:
> > add some reviewers
> > ---
> >  lib/stackdepot.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> > index ed717dd08ff3..7e8a15e41600 100644
> > --- a/lib/stackdepot.c
> > +++ b/lib/stackdepot.c
> > @@ -106,7 +106,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
> >         required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
> >
> >         if (unlikely(depot_offset + required_size > STACK_ALLOC_SIZE)) {
> > -               if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) {
> > +               if (unlikely(depot_index + 2 >= STACK_ALLOC_MAX_SLABS)) {
> 
> I don't think this is the right way to fix the problem.
> You're basically throwing away the last element of stack_slabs[], as
> we won't allocate anything from it.
> 
ok, I agree.
 
> How about we set |next_slab_inited| to 1 here:
> 
> diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> index 2e7d2232ed3c..943a51eb746d 100644
> --- a/lib/stackdepot.c
> +++ b/lib/stackdepot.c
> @@ -105,6 +105,8 @@ static bool init_stack_slab(void **prealloc)
>                 return true;
>         if (stack_slabs[depot_index] == NULL) {
>                 stack_slabs[depot_index] = *prealloc;
> +               if (depot_index + 1 == STACK_ALLOC_MAX_SLABS)
> +                       smp_store_release(&next_slab_inited, 1);
>         } else {
>                 stack_slabs[depot_index + 1] = *prealloc;
>                 /*
> 
> This will ensure we won't be preallocating pages once |depot_index|
> reaches the last element, and we won't attempt to write those pages
> anywhere either.
> 
> Could you please check if this fixes the problem for you?
> 
Consider above call flow sequence at first stack_depot_save(),
depot_index = STACK_ALLOC_MAX_SLABS - 2 before enter init_stack_slab(),
so the fixes should be below.

--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -83,6 +83,8 @@ static bool init_stack_slab(void **prealloc)
                return true;
        if (stack_slabs[depot_index] == NULL) {
                stack_slabs[depot_index] = *prealloc;
+               if (depot_index + 2 == STACK_ALLOC_MAX_SLABS)
+                       smp_store_release(&next_slab_inited, 1);
        } else {
                stack_slabs[depot_index + 1] = *prealloc;
                /*


> >                         WARN_ONCE(1, "Stack depot reached limit capacity");
> >                         return NULL;
> >                 }
> > --
> > 2.18.0
> 
> 
>
Alexander Potapenko Jan. 31, 2020, 6:11 p.m. UTC | #3
On Fri, Jan 31, 2020 at 3:05 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
>
> On Thu, 2020-01-30 at 13:03 +0100, Alexander Potapenko wrote:
> > On Thu, Jan 30, 2020 at 7:44 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> >
> > Hi Walter,
> >
> > > If the depot_index = STACK_ALLOC_MAX_SLABS - 2 and next_slab_inited = 0,
> > > then it will cause array out-of-bounds access, so that we should modify
> > > the detection to avoid this array out-of-bounds bug.
> > >
> > > Assume depot_index = STACK_ALLOC_MAX_SLABS - 3
> > > Consider following call flow sequence:
> > >
> > > stack_depot_save()
> > >    depot_alloc_stack()
> > >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> > >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 2
> > >       if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) //enter
> > >          smp_store_release(&next_slab_inited, 0); //next_slab_inited = 0
> > >       init_stack_slab()
> > >          if (stack_slabs[depot_index] == NULL) //enter and exit
> > >
> > > stack_depot_save()
> > >    depot_alloc_stack()
> > >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> > >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 1
> > >       init_stack_slab(&prealloc)
> > >          stack_slabs[depot_index + 1]  //here get global out-of-bounds
> > >
> > > Cc: Dmitry Vyukov <dvyukov@google.com>
> > > Cc: Matthias Brugger <matthias.bgg@gmail.com>
> > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > Cc: Alexander Potapenko <glider@google.com>
> > > Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> > > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > > Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
> > > ---
> > > changes in v2:
> > > modify call flow sequence and preconditon
> > >
> > > changes in v3:
> > > add some reviewers
> > > ---
> > >  lib/stackdepot.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> > > index ed717dd08ff3..7e8a15e41600 100644
> > > --- a/lib/stackdepot.c
> > > +++ b/lib/stackdepot.c
> > > @@ -106,7 +106,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
> > >         required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
> > >
> > >         if (unlikely(depot_offset + required_size > STACK_ALLOC_SIZE)) {
> > > -               if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) {
> > > +               if (unlikely(depot_index + 2 >= STACK_ALLOC_MAX_SLABS)) {

This again means stack_slabs[STACK_ALLOC_MAX_SLABS - 2] gets
initialized, but stack_slabs[STACK_ALLOC_MAX_SLABS - 1] doesn't,
because we'll be bailing out from init_stack_slab() from now on.
Does this patch actually fix the problem (do you have a reliable reproducer?)
This addition of 2 is also counterintuitive, I don't think further
readers will understand the logic behind it.

What if we just check that depot_index + 1 is a valid index before accessing it?

diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 2e7d2232ed3c..c2e6ff18d716 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -106,7 +106,9 @@ static bool init_stack_slab(void **prealloc)
        if (stack_slabs[depot_index] == NULL) {
                stack_slabs[depot_index] = *prealloc;
        } else {
-               stack_slabs[depot_index + 1] = *prealloc;
+               /* If this is the last depot slab, do not touch the next one. */
+               if (depot_index + 1 < STACK_ALLOC_MAX_SLABS)
+                       stack_slabs[depot_index + 1] = *prealloc;
                /*
                 * This smp_store_release pairs with smp_load_acquire() from
                 * |next_slab_inited| above and in stack_depot_save().
Walter Wu Feb. 3, 2020, 2:05 a.m. UTC | #4
On Fri, 2020-01-31 at 19:11 +0100, Alexander Potapenko wrote:
> On Fri, Jan 31, 2020 at 3:05 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> >
> > On Thu, 2020-01-30 at 13:03 +0100, Alexander Potapenko wrote:
> > > On Thu, Jan 30, 2020 at 7:44 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> > >
> > > Hi Walter,
> > >
> > > > If the depot_index = STACK_ALLOC_MAX_SLABS - 2 and next_slab_inited = 0,
> > > > then it will cause array out-of-bounds access, so that we should modify
> > > > the detection to avoid this array out-of-bounds bug.
> > > >
> > > > Assume depot_index = STACK_ALLOC_MAX_SLABS - 3
> > > > Consider following call flow sequence:
> > > >
> > > > stack_depot_save()
> > > >    depot_alloc_stack()
> > > >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> > > >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 2
> > > >       if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) //enter
> > > >          smp_store_release(&next_slab_inited, 0); //next_slab_inited = 0
> > > >       init_stack_slab()
> > > >          if (stack_slabs[depot_index] == NULL) //enter and exit
> > > >
> > > > stack_depot_save()
> > > >    depot_alloc_stack()
> > > >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> > > >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 1
> > > >       init_stack_slab(&prealloc)
> > > >          stack_slabs[depot_index + 1]  //here get global out-of-bounds
> > > >
> > > > Cc: Dmitry Vyukov <dvyukov@google.com>
> > > > Cc: Matthias Brugger <matthias.bgg@gmail.com>
> > > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > > Cc: Alexander Potapenko <glider@google.com>
> > > > Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> > > > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > > > Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
> > > > ---
> > > > changes in v2:
> > > > modify call flow sequence and preconditon
> > > >
> > > > changes in v3:
> > > > add some reviewers
> > > > ---
> > > >  lib/stackdepot.c | 2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> > > > index ed717dd08ff3..7e8a15e41600 100644
> > > > --- a/lib/stackdepot.c
> > > > +++ b/lib/stackdepot.c
> > > > @@ -106,7 +106,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
> > > >         required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
> > > >
> > > >         if (unlikely(depot_offset + required_size > STACK_ALLOC_SIZE)) {
> > > > -               if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) {
> > > > +               if (unlikely(depot_index + 2 >= STACK_ALLOC_MAX_SLABS)) {
> 
> This again means stack_slabs[STACK_ALLOC_MAX_SLABS - 2] gets
> initialized, but stack_slabs[STACK_ALLOC_MAX_SLABS - 1] doesn't,
> because we'll be bailing out from init_stack_slab() from now on.
> Does this patch actually fix the problem (do you have a reliable reproducer?)
We get it by reviewing code, because Kasan doesn't scan it and we catch
another bug internally, we found it unintentionally.

> This addition of 2 is also counterintuitive, I don't think further
> readers will understand the logic behind it.
> 
Yes

> What if we just check that depot_index + 1 is a valid index before accessing it?
> 
It should fix the problem, do you want to send this patch?

> diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> index 2e7d2232ed3c..c2e6ff18d716 100644
> --- a/lib/stackdepot.c
> +++ b/lib/stackdepot.c
> @@ -106,7 +106,9 @@ static bool init_stack_slab(void **prealloc)
>         if (stack_slabs[depot_index] == NULL) {
>                 stack_slabs[depot_index] = *prealloc;
>         } else {
> -               stack_slabs[depot_index + 1] = *prealloc;
> +               /* If this is the last depot slab, do not touch the next one. */
> +               if (depot_index + 1 < STACK_ALLOC_MAX_SLABS)
> +                       stack_slabs[depot_index + 1] = *prealloc;
>                 /*
>                  * This smp_store_release pairs with smp_load_acquire() from
>                  * |next_slab_inited| above and in stack_depot_save().
Alexander Potapenko Feb. 3, 2020, 10:30 a.m. UTC | #5
On Mon, Feb 3, 2020 at 3:05 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
>
> On Fri, 2020-01-31 at 19:11 +0100, Alexander Potapenko wrote:
> > On Fri, Jan 31, 2020 at 3:05 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> > >
> > > On Thu, 2020-01-30 at 13:03 +0100, Alexander Potapenko wrote:
> > > > On Thu, Jan 30, 2020 at 7:44 AM Walter Wu <walter-zh.wu@mediatek.com> wrote:
> > > >
> > > > Hi Walter,
> > > >
> > > > > If the depot_index = STACK_ALLOC_MAX_SLABS - 2 and next_slab_inited = 0,
> > > > > then it will cause array out-of-bounds access, so that we should modify
> > > > > the detection to avoid this array out-of-bounds bug.
> > > > >
> > > > > Assume depot_index = STACK_ALLOC_MAX_SLABS - 3
> > > > > Consider following call flow sequence:
> > > > >
> > > > > stack_depot_save()
> > > > >    depot_alloc_stack()
> > > > >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> > > > >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 2
> > > > >       if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) //enter
> > > > >          smp_store_release(&next_slab_inited, 0); //next_slab_inited = 0
> > > > >       init_stack_slab()
> > > > >          if (stack_slabs[depot_index] == NULL) //enter and exit
> > > > >
> > > > > stack_depot_save()
> > > > >    depot_alloc_stack()
> > > > >       if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) //pass
> > > > >       depot_index++  //depot_index = STACK_ALLOC_MAX_SLABS - 1
> > > > >       init_stack_slab(&prealloc)
> > > > >          stack_slabs[depot_index + 1]  //here get global out-of-bounds
> > > > >
> > > > > Cc: Dmitry Vyukov <dvyukov@google.com>
> > > > > Cc: Matthias Brugger <matthias.bgg@gmail.com>
> > > > > Cc: Thomas Gleixner <tglx@linutronix.de>
> > > > > Cc: Alexander Potapenko <glider@google.com>
> > > > > Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> > > > > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > > > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > > > Cc: Kate Stewart <kstewart@linuxfoundation.org>
> > > > > Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
> > > > > ---
> > > > > changes in v2:
> > > > > modify call flow sequence and preconditon
> > > > >
> > > > > changes in v3:
> > > > > add some reviewers
> > > > > ---
> > > > >  lib/stackdepot.c | 2 +-
> > > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/lib/stackdepot.c b/lib/stackdepot.c
> > > > > index ed717dd08ff3..7e8a15e41600 100644
> > > > > --- a/lib/stackdepot.c
> > > > > +++ b/lib/stackdepot.c
> > > > > @@ -106,7 +106,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
> > > > >         required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
> > > > >
> > > > >         if (unlikely(depot_offset + required_size > STACK_ALLOC_SIZE)) {
> > > > > -               if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) {
> > > > > +               if (unlikely(depot_index + 2 >= STACK_ALLOC_MAX_SLABS)) {
> >
> > This again means stack_slabs[STACK_ALLOC_MAX_SLABS - 2] gets
> > initialized, but stack_slabs[STACK_ALLOC_MAX_SLABS - 1] doesn't,
> > because we'll be bailing out from init_stack_slab() from now on.
> > Does this patch actually fix the problem (do you have a reliable reproducer?)
> We get it by reviewing code, because Kasan doesn't scan it and we catch
> another bug internally, we found it unintentionally.
>
> > This addition of 2 is also counterintuitive, I don't think further
> > readers will understand the logic behind it.
> >
> Yes
>
> > What if we just check that depot_index + 1 is a valid index before accessing it?
> >
> It should fix the problem, do you want to send this patch?

I've sent the patch. Thanks for the report!

Patch
diff mbox series

diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index ed717dd08ff3..7e8a15e41600 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -106,7 +106,7 @@  static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
 	required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
 
 	if (unlikely(depot_offset + required_size > STACK_ALLOC_SIZE)) {
-		if (unlikely(depot_index + 1 >= STACK_ALLOC_MAX_SLABS)) {
+		if (unlikely(depot_index + 2 >= STACK_ALLOC_MAX_SLABS)) {
 			WARN_ONCE(1, "Stack depot reached limit capacity");
 			return NULL;
 		}