lkml.org 
[lkml]   [2012]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 074/108] x86-32: Fix endless loop when processing signals for kernel tasks
    3.0-stable review patch.  If anyone has any objections, please let me know.

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

    From: Dmitry Adamushko <dmitry.adamushko@gmail.com>

    commit 29a2e2836ff9ea65a603c89df217f4198973a74f upstream.

    The problem occurs on !CONFIG_VM86 kernels [1] when a kernel-mode task
    returns from a system call with a pending signal.

    A real-life scenario is a child of 'khelper' returning from a failed
    kernel_execve() in ____call_usermodehelper() [ kernel/kmod.c ].
    kernel_execve() fails due to a pending SIGKILL, which is the result of
    "kill -9 -1" (at least, busybox's init does it upon reboot).

    The loop is as follows:

    * syscall_exit_work:
    - work_pending: // start_of_the_loop
    - work_notify_sig:
    - do_notify_resume()
    - do_signal()
    - if (!user_mode(regs)) return;
    - resume_userspace // TIF_SIGPENDING is still set
    - work_pending // so we call work_pending => goto
    // start_of_the_loop

    More information can be found in another LKML thread:
    http://www.serverphorums.com/read.php?12,457826

    [1] the problem was also seen on MIPS.

    Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com>
    Link: http://lkml.kernel.org/r/1332448765.2299.68.camel@dimm
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Roland McGrath <roland@hack.frob.com>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: H. Peter Anvin <hpa@zytor.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/kernel/entry_32.S | 17 ++++++++++-------
    1 file changed, 10 insertions(+), 7 deletions(-)

    --- a/arch/x86/kernel/entry_32.S
    +++ b/arch/x86/kernel/entry_32.S
    @@ -98,12 +98,6 @@
    #endif
    .endm

    -#ifdef CONFIG_VM86
    -#define resume_userspace_sig check_userspace
    -#else
    -#define resume_userspace_sig resume_userspace
    -#endif
    -
    /*
    * User gs save/restore
    *
    @@ -327,10 +321,19 @@ ret_from_exception:
    preempt_stop(CLBR_ANY)
    ret_from_intr:
    GET_THREAD_INFO(%ebp)
    -check_userspace:
    +resume_userspace_sig:
    +#ifdef CONFIG_VM86
    movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
    movb PT_CS(%esp), %al
    andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
    +#else
    + /*
    + * We can be coming here from a syscall done in the kernel space,
    + * e.g. a failed kernel_execve().
    + */
    + movl PT_CS(%esp), %eax
    + andl $SEGMENT_RPL_MASK, %eax
    +#endif
    cmpl $USER_RPL, %eax
    jb resume_kernel # not returning to v8086 or userspace




    \
     
     \ /
      Last update: 2012-03-30 23:09    [W:0.024 / U:0.316 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site