kprobes and uprobes on sparc64 single-step a copy of the probed instruction, and each has a relbranch_fixup() that moves a taken branch's target from the copy back to the probed code. Both only recognize call, BPcc and Bicc. A taken BPr, FBfcc or FBPfcc therefore continues next to the copy, which crashes the kernel for a kprobe and kills the task with SIGILL for a uprobe. BPr is a common first instruction (a brz,pn on an argument), so a probe on a function's entry is enough to hit it.
Patch 1 fixes kprobes, where the check dates back to the start of git history. Patch 2 fixes the uprobes copy of it. They are independent of each other, and of my pending uprobes kmap_local_page() patch. Testing, in QEMU sun4u with sparc64_defconfig plus PREEMPT, DEBUG_PREEMPT, PROVE_LOCKING and DEBUG_ATOMIC_SLEEP. A static init puts uprobes on seven branches in its own code: brz,pn at a function's entry, brgz,pt, fbe,pt %fcc0 (FBPfcc) and fbe (FBfcc), plus be (Bicc), be,pt %xcc (BPcc) and call as controls. Each function runs 200 times in a child, alternating taken and not taken, and the delay slot's effect and the path taken are both checked. It then puts a kprobe on __se_sys_getcpu(), which starts with "brz,pn %o0", and calls getcpu() 200 times, half of them with a NULL cpu pointer. - fe2ec83746e5 (v7.3-rc4+): the four new uprobe cases die with SIGILL on their first taken branch, the controls pass, and the first taken getcpu() under the kprobe crashes the kernel. - Patch 1 only: the kprobe case passes with 200 hits; uprobes as before. - Both patches: everything passes, with no new kernel warnings. Boot has three DEBUG_PREEMPT "__this_cpu_read() in preemptible" reports from iommu_tbl_range_alloc(), with or without these patches. W=1 and sparse are clean for both files. Danish Khateeb (2): sparc64: kprobes: fix relbranch_fixup() for BPr, FBfcc and FBPfcc sparc64: uprobes: fix relbranch_fixup() for BPr, FBfcc and FBPfcc arch/sparc/kernel/kprobes.c | 13 ++++++++----- arch/sparc/kernel/uprobes.c | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) base-commit: fe2ec83746e501645709761605c2464a44fd2929 -- 2.55.0
