• Vasily Gorbik's avatar
    s390/kprobes: fix irq mask clobbering on kprobe reenter from post_handler · 42e19e6f
    Vasily Gorbik authored
    Recent test_kprobe_missed kprobes kunit test uncovers the following error
    (reported when CONFIG_DEBUG_ATOMIC_SLEEP is enabled):
    
    BUG: sleeping function called from invalid context at kernel/locking/mutex.c:580
    in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 662, name: kunit_try_catch
    preempt_count: 0, expected: 0
    RCU nest depth: 0, expected: 0
    no locks held by kunit_try_catch/662.
    irq event stamp: 280
    hardirqs last  enabled at (279): [<00000003e60a3d42>] __do_pgm_check+0x17a/0x1c0
    hardirqs last disabled at (280): [<00000003e3bd774a>] kprobe_exceptions_notify+0x27a/0x318
    softirqs last  enabled at (0): [<00000003e3c5c890>] copy_process+0x14a8/0x4c80
    softirqs last disabled at (0): [<0000000000000000>] 0x0
    CPU: 46 PID: 662 Comm: kunit_try_catch Tainted: G                 N 6.2.0-173644-g44c18d77f0c0 #2
    Hardware name: IBM 3931 A01 704 (LPAR)
    Call Trace:
     [<00000003e60a3a00>] dump_stack_lvl+0x120/0x198
     [<00000003e3d02e82>] __might_resched+0x60a/0x668
     [<00000003e60b9908>] __mutex_lock+0xc0/0x14e0
     [<00000003e60bad5a>] mutex_lock_nested+0x32/0x40
     [<00000003e3f7b460>] unregister_kprobe+0x30/0xd8
     [<00000003e51b2602>] test_kprobe_missed+0xf2/0x268
     [<00000003e51b5406>] kunit_try_run_case+0x10e/0x290
     [<00000003e51b7dfa>] kunit_generic_run_threadfn_adapter+0x62/0xb8
     [<00000003e3ce30f8>] kthread+0x2d0/0x398
     [<00000003e3b96afa>] __ret_from_fork+0x8a/0xe8
     [<00000003e60ccada>] ret_from_fork+0xa/0x40
    
    The reason for this error report is that kprobes handling code failed
    to restore irqs.
    
    The problem is that when kprobe is triggered from another kprobe
    post_handler current sequence of enable_singlestep / disable_singlestep
    is the following:
    enable_singlestep  <- original kprobe (saves kprobe_saved_imask)
    enable_singlestep  <- kprobe triggered from post_handler (clobbers kprobe_saved_imask)
    disable_singlestep <- kprobe triggered from post_handler (restores kprobe_saved_imask)
    disable_singlestep <- original kprobe (restores wrong clobbered kprobe_saved_imask)
    
    There is just one kprobe_ctlblk per cpu and both calls saves and
    loads irq mask to kprobe_saved_imask. To fix the problem simply move
    resume_execution (which calls disable_singlestep) before calling
    post_handler. This also fixes the problem that post_handler is called
    with pt_regs which were not yet adjusted after single-stepping.
    
    Cc: stable@vger.kernel.org
    Fixes: 4ba069b8 ("[S390] add kprobes support.")
    Reviewed-by: default avatarHeiko Carstens <hca@linux.ibm.com>
    Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
    Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
    42e19e6f
kprobes.c 13.5 KB