lkml.org 
[lkml]   [2018]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 098/108] alpha: fix crash if pthread_create races with signal delivery
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Mikulas Patocka <mpatocka@redhat.com>

    commit 21ffceda1c8b3807615c40d440d7815e0c85d366 upstream.

    On alpha, a process will crash if it attempts to start a thread and a
    signal is delivered at the same time. The crash can be reproduced with
    this program: https://cygwin.com/ml/cygwin/2014-11/msg00473.html

    The reason for the crash is this:
    * we call the clone syscall
    * we go to the function copy_process
    * copy process calls copy_thread_tls, it is a wrapper around copy_thread
    * copy_thread sets the tls pointer: childti->pcb.unique = regs->r20
    * copy_thread sets regs->r20 to zero
    * we go back to copy_process
    * copy process checks "if (signal_pending(current))" and returns
    -ERESTARTNOINTR
    * the clone syscall is restarted, but this time, regs->r20 is zero, so
    the new thread is created with zero tls pointer
    * the new thread crashes in start_thread when attempting to access tls

    The comment in the code says that setting the register r20 is some
    compatibility with OSF/1. But OSF/1 doesn't use the CLONE_SETTLS flag, so
    we don't have to zero r20 if CLONE_SETTLS is set. This patch fixes the bug
    by zeroing regs->r20 only if CLONE_SETTLS is not set.

    Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
    Signed-off-by: Matt Turner <mattst88@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/alpha/kernel/process.c | 3 ++-
    1 file changed, 2 insertions(+), 1 deletion(-)

    --- a/arch/alpha/kernel/process.c
    +++ b/arch/alpha/kernel/process.c
    @@ -273,12 +273,13 @@ copy_thread(unsigned long clone_flags, u
    application calling fork. */
    if (clone_flags & CLONE_SETTLS)
    childti->pcb.unique = regs->r20;
    + else
    + regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */
    childti->pcb.usp = usp ?: rdusp();
    *childregs = *regs;
    childregs->r0 = 0;
    childregs->r19 = 0;
    childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
    - regs->r20 = 0;
    stack = ((struct switch_stack *) regs) - 1;
    *childstack = *stack;
    childstack->r26 = (unsigned long) ret_from_fork;

    \
     
     \ /
      Last update: 2018-02-15 19:32    [W:3.603 / U:0.228 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site