lkml.org 
[lkml]   [2017]   [Feb]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    Subject[BUGFIX PATCH tip/master V2 0/3] kprobes: Fix a possible deadlock in kretprobe
    Date
    Hi,

    Here is 2nd version of the series. I just updated the
    patch description to make it easier to understand
    on arm and arm64, no code change.

    V1 is here:
    http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1327856.html

    ----
    This series will fix a possible deadlock case in kretprobe
    on x86, arm, arm64. Since kretprobe has been optimized on
    those arch, they have similar possible deadlock issue.

    Problem
    =====

    The deadlock senario is when a user puts 2 kretprobes,
    one on normal function and one on a function which can be
    called from NMI or FIQ where normal interrupt disabled.
    (we don't recommend it, but possible.) In this case, if
    the kernel hits the 1st kretprobe on a normal function
    return which calls trampoline_handler(), acquire a
    spinlock on the hash table in kretprobe_hash_lock() and
    disable irqs.
    After that, if NMI(or FIQ on arm/arm64) is occurred and
    the 2nd kretprobe is kicked, it also calls
    trampoline_handler() and tries to acquire the same
    spinlock (since the hash is based on current task, same
    as the 1st kretprobe), it causes a deadlock on the
    spinlock.
    Note that this is very rare case, but theoretically happens.

    Reason and Affected Arch
    =====

    Actually, this bug has been introduced by kretprobe-booster,
    which removes a kprobe from return trampoline code, but also
    resets current kprobe, which can be a stopper for the nested
    k(ret)probes. So, currently only x86, arm, and arm64 are
    affected, because other arch have not implemented the
    kretprobe-booster.

    Solution
    =====

    To fix this issue, I introduced a dummy kprobe which is set
    as a current kprobe while holding the kretprobe-hash lock.
    With that, if an NMI/FIQ occurred and 2nd kretprobe's kprobe
    is kicked (to modify the return address, a kprobe is kicked
    when the target function is called), the kprobe (and the 2nd
    kretprobe also) is skipped because it detects there is
    another kprobe is running.

    This reentrance detection and nested kprobe blocker had
    existed when the original kretprobe was implemented by
    using kprobe on trampoline code. This fix just revived it.

    Thank you,

    ---

    Masami Hiramatsu (3):
    kprobes/x86: Fix a possible deadlock case in kretprobe
    kprobes/arm64: Fix a possible deadlock case in kretprobe
    kprobes/arm: Fix a possible deadlock case in kretprobe


    arch/arm/probes/kprobes/core.c | 12 ++++++++++--
    arch/arm64/kernel/probes/kprobes.c | 12 ++++++++++--
    arch/x86/kernel/kprobes/core.c | 13 ++++++++++---
    3 files changed, 30 insertions(+), 7 deletions(-)

    --
    Masami Hiramatsu

    \
     
     \ /
      Last update: 2017-02-09 17:30    [W:6.315 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site