Re: [linux-safety] [RFC PATCH 2/2] bust_spinlocks: do not decrement oops_in_progress unconditionally

"Lukas Bulwahn" <[email protected]> Thu, 15 Oct 2020 08:44:35 +0200
Newsgroups tech.elisa.lists.linux-safety
Message-ID <CAKXUXMwb3c58Qc1vYQe6WsddUAnKgQmV2vhM1TuiQpEZtWmpSQ@mail.gmail.com>
On Wed, Oct 14, 2020 at 2:05 PM Paoloni, Gabriele
<[email protected]> wrote:
>
> Hi Lukas
>
> > -----Original Message-----
> > From: Lukas Bulwahn <[email protected]>
> > Sent: Wednesday, October 14, 2020 7:53 AM
> > To: Paoloni, Gabriele <[email protected]>
> > Cc: [email protected]
> > Subject: Re: [linux-safety] [RFC PATCH 2/2] bust_spinlocks: do not
> > decrement oops_in_progress unconditionally
> >
> >
> >
> > On Tue, 13 Oct 2020, Paoloni, Gabriele wrote:
> >
> > > In the current implementation if the input flag is 0
> > > oops_in_progress is unconditionally decremented, thus allowing
> > > to become a negative number. Since right now oops_in_progress
> > > is a global variable used in the kernel as a conditional flag
> > > to check if oops, panic(), BUG() or die() is in progress the
> > > current unconditional decrement may lead to unexpected behavior
> > > in the Kernel paths conditionally executing over this flag.
> > >
> > > This patch only decrement oops_in_progress if it is non zero
> > >
> > > Signed-off-by: Gabriele Paoloni <[email protected]>
> > > ---
> > >  lib/bust_spinlocks.c | 7 ++++++-
> > >  1 file changed, 6 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/lib/bust_spinlocks.c b/lib/bust_spinlocks.c
> > > index 594b270161d9..842633ac9130 100644
> > > --- a/lib/bust_spinlocks.c
> > > +++ b/lib/bust_spinlocks.c
> > > @@ -23,6 +23,9 @@
> > >   * @yes: input flag; if zero decreases oops_in_progress,
> > >   * otherwise increases it.
> > >   *
> > > + * Note: if oops_in_progress is already 0 it will not
> > > + * be decreased
> > > + *
> > >   */
> > >  void bust_spinlocks(int yes)
> > >  {
> > > @@ -33,7 +36,9 @@ void bust_spinlocks(int yes)
> > >             unblank_screen();
> > >  #endif
> > >             console_unblank();
> > > -           if (--oops_in_progress == 0)
> > > +           if (oops_in_progress)
> > > +                   oops_in_progress--;
> > > +           if (!oops_in_progress)
> > >                     wake_up_klogd();
> >
> > I did not get the original motivation stated above.
> >
> > But I believe you meant:
> >
> > 'I think there is race condition here (before this patch).'
> >
> > So do something in this patch: 'And now the race condition is gone?'
> >
> >
> > I think:
> >
> > 'The could be a race condition before, and probably the race condition is
> > still there after this patch.'
> >
> > But maybe I did even get the intent of this patch in the first place...
>
> What I meant is the following scenario:
> Let's assume oops_in_progress = 0, then we have
>
> func_a()
> {
>         bust_spinlocks(0);
> }
>
> In this case after the call, with the current implementation oops_in_progress = -1; that is not acceptable...
>

Okay, but that is just the contract of this bust_spinlocks() function, right?

As you wrote every caller must call bust_spinlocks(1) and ONLY then
when they are done bust_spinlocks(0) [if the machine has not
halted...].

Maybe if the functions would be bust_spinlocks_{en,dis}able() or
bust_spinlocks_{start,stop}() the contract is more clear. But in the
end, there are only a few users as far as see, in fault, panic, etc.

Of course, if you call bust_spinlocks_stop() before start() bad things
happen... use a static analyzer/model checker to see that that pattern
never appears :)

As I said, the patch looks good; I am looking forward to the feedback.

Lukas