Re: [PATCH] LoongArch: kprobes: Avoid preempt count underflow without probe

From: Huacai Chen

Date: Sat Sep 05 2026 - 11:07:25 EST


Applied, thanks.


Huacai

On Mon, Aug 24, 2026 at 5:19 AM Jérémy Jean
<Jeremy.Jean@xxxxxxxxxxxxxxxxx> wrote:
>
> LoongArch uses break 11 for the breakpoint placed after an instruction
> that Kprobes executes out of line. Since userspace can issue the same
> break instruction, do_bp() can reach kprobe_singlestep_handler() when
> there is no current probe.
>
> The handler returns false in this case, but first calls
> preempt_enable_no_resched(). The corresponding preempt_disable() is done
> by kprobe_breakpoint_handler() on a real Kprobe hit, so it has not run
> here. As a result, an ordinary userspace breakpoint underflows the
> current task's preempt count.
>
> This also makes in_interrupt() return true until the task schedules. One
> visible consequence is socket cgroup attribution: cgroup_sk_alloc()
> treats the allocation as interrupt context and assigns the socket to the
> root cgroup. A socket opened from the SIGTRAP handler can then avoid a
> BPF_CGROUP_INET_SOCK_CREATE policy attached to the task's own cgroup.
>
> Return as soon as kprobe_running() reports no active probe.
>
> The same check appeared in [PATCH v10 2/4] of the original LoongArch
> Kprobes series, but was dropped before the feature reached mainline.
>
> Link: https://patchew.org/linux/1670575981-14389-1-git-send-email-yangtiezhu%40loongson.cn/1670575981-14389-3-git-send-email-yangtiezhu%40loongson.cn/
> Fixes: 6d4cc40fb5f5 ("LoongArch: Add kprobes support")
> Assisted-by: Codex:gpt-5
> Signed-off-by: Jérémy Jean <Jeremy.Jean@xxxxxxxxxxxxxxxxx>
> ---
> arch/loongarch/kernel/kprobes.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/loongarch/kernel/kprobes.c b/arch/loongarch/kernel/kprobes.c
> index 1985ed30dd16f..ddfefea174727 100644
> --- a/arch/loongarch/kernel/kprobes.c
> +++ b/arch/loongarch/kernel/kprobes.c
> @@ -275,6 +275,9 @@ bool kprobe_singlestep_handler(struct pt_regs *regs)
> struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
> unsigned long addr = instruction_pointer(regs);
>
> + if (!cur)
> + return false;
> +
> if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) &&
> ((unsigned long)&cur->ainsn.insn[1] == addr)) {
> restore_local_irqflag(kcb, regs);
> --
> 2.47.3
>