lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Fri, 26 Jun 2020 11:18:34 -0700
From:   Nick Desaulniers <ndesaulniers@...gle.com>
To:     Al Viro <viro@...iv.linux.org.uk>
Cc:     Oleg Nesterov <oleg@...hat.com>,
        Thomas Gleixner <tglx@...utronix.de>,
        Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
        Peter Zijlstra <peterz@...radead.org>,
        clang-built-linux <clang-built-linux@...glegroups.com>,
        Linus Torvalds <torvalds@...ux-foundation.org>,
        "H. Peter Anvin" <hpa@...or.com>,
        "maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)" <x86@...nel.org>,
        Sebastian Andrzej Siewior <bigeasy@...utronix.de>,
        Andy Lutomirski <luto@...nel.org>,
        Sami Tolvanen <samitolvanen@...gle.com>,
        Marco Elver <elver@...gle.com>,
        Brian Gerst <brgerst@...il.com>, Arnd Bergmann <arnd@...db.de>,
        Andrew Morton <akpm@...ux-foundation.org>,
        "Eric W. Biederman" <ebiederm@...ssion.com>,
        LKML <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v2] x86: signal: move save_altstack_ex out of generic headers

On Sat, Apr 4, 2020 at 10:06 AM Al Viro <viro@...iv.linux.org.uk> wrote:
>
> On Sat, Apr 04, 2020 at 06:01:00PM +0200, Oleg Nesterov wrote:
> > On 04/03, Nick Desaulniers wrote:
> > >
> > > --- a/arch/x86/kernel/signal.c
> > > +++ b/arch/x86/kernel/signal.c
> > > @@ -416,6 +416,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
> > >     return 0;
> > >  Efault:
> > >     user_access_end();
> > > +   reset_altstack();
> > >     return -EFAULT;
> > >  }
> > >  #else /* !CONFIG_X86_32 */
> > > @@ -507,6 +508,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
> > >
> > >  Efault:
> > >     user_access_end();
> > > +   reset_altstack();
> > >     return -EFAULT;
> > >  }
> >
> > I must have missed something, but this looks just wrong.
> >
> > reset_altstack() should be called when __setup_rt_frame() (and
> > unsafe_save_altstack() in particular) succeeds, not when it fails.
> >
> > Nevermind, Al has already suggested to use signal_delivered()...
>
> FWIW, I propose to do is the patch below (against the current mainline);
> objections?
>
> Don't do sas_ss_reset() until we are certain that sigframe won't be abandoned
>
> Currently we handle SS_AUTODISARM as soon as we have stored the
> altstack settings into sigframe - that's the point when we have
> set the things up for eventual sigreturn to restore the old settings.
> And if we manage to set the sigframe up (we are not done with that
> yet), everything's fine.  However, in case of failure we end up
> with sigframe-to-be abandoned and SIGSEGV force-delivered.  And
> in that case we end up with inconsistent rules - late failures
> have altstack reset, early ones do not.
>
> It's trivial to get consistent behaviour - just handle SS_AUTODISARM
> once we have set the sigframe up and are committed to entering
> the handler, i.e. in signal_delivered().
>
> Signed-off-by: Al Viro <viro@...iv.linux.org.uk>

Hi Al,
Have you had time to wrap this up as its own commit and send?  I was
doing a bug scrub of our KernelCI warnings and noticed this is still
an issue.  Looks like everyone was happy with your approach.  Let me
know if you're too busy, and I'll collect all of the tags and send for
you.  I appreciate you taking the time to help us fix this.

> ---
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index 0480ba4db592..f614967374f5 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -461,8 +461,6 @@ int __compat_save_altstack(compat_stack_t __user *, unsigned long);
>                         &__uss->ss_sp, label); \
>         unsafe_put_user(t->sas_ss_flags, &__uss->ss_flags, label); \
>         unsafe_put_user(t->sas_ss_size, &__uss->ss_size, label); \
> -       if (t->sas_ss_flags & SS_AUTODISARM) \
> -               sas_ss_reset(t); \
>  } while (0);
>
>  /*
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index 05bacd2ab135..28fe9cc134f7 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -450,8 +450,6 @@ int __save_altstack(stack_t __user *, unsigned long);
>         unsafe_put_user((void __user *)t->sas_ss_sp, &__uss->ss_sp, label); \
>         unsafe_put_user(t->sas_ss_flags, &__uss->ss_flags, label); \
>         unsafe_put_user(t->sas_ss_size, &__uss->ss_size, label); \
> -       if (t->sas_ss_flags & SS_AUTODISARM) \
> -               sas_ss_reset(t); \
>  } while (0);
>
>  #ifdef CONFIG_PROC_FS
> diff --git a/kernel/signal.c b/kernel/signal.c
> index e58a6c619824..4cfe0b9af588 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -2769,6 +2769,8 @@ static void signal_delivered(struct ksignal *ksig, int stepping)
>         if (!(ksig->ka.sa.sa_flags & SA_NODEFER))
>                 sigaddset(&blocked, ksig->sig);
>         set_current_blocked(&blocked);
> +       if (current->sas_ss_flags & SS_AUTODISARM)
> +               sas_ss_reset(current);
>         tracehook_signal_handler(stepping);
>  }
>
> @@ -4070,11 +4072,7 @@ int __save_altstack(stack_t __user *uss, unsigned long sp)
>         int err = __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) |
>                 __put_user(t->sas_ss_flags, &uss->ss_flags) |
>                 __put_user(t->sas_ss_size, &uss->ss_size);
> -       if (err)
> -               return err;
> -       if (t->sas_ss_flags & SS_AUTODISARM)
> -               sas_ss_reset(t);
> -       return 0;
> +       return err;
>  }
>
>  #ifdef CONFIG_COMPAT
> @@ -4129,11 +4127,7 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp)
>                          &uss->ss_sp) |
>                 __put_user(t->sas_ss_flags, &uss->ss_flags) |
>                 __put_user(t->sas_ss_size, &uss->ss_size);
> -       if (err)
> -               return err;
> -       if (t->sas_ss_flags & SS_AUTODISARM)
> -               sas_ss_reset(t);
> -       return 0;
> +       return err;
>  }
>  #endif
>


-- 
Thanks,
~Nick Desaulniers

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ