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

Jérémy Jean posted 1 patch 1 month ago
arch/loongarch/kernel/kprobes.c | 3 +++
1 file changed, 3 insertions(+)
[PATCH] LoongArch: kprobes: Avoid preempt count underflow without probe
Posted by Jérémy Jean 1 month ago
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@oss.cyber.gouv.fr>
---
 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

Re: [PATCH] LoongArch: kprobes: Avoid preempt count underflow without probe
Posted by Huacai Chen 3 weeks, 1 day ago
Applied, thanks.


Huacai

On Mon, Aug 24, 2026 at 5:19 AM Jérémy Jean
<Jeremy.Jean@oss.cyber.gouv.fr> 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@oss.cyber.gouv.fr>
> ---
>  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
>
Re: [PATCH] LoongArch: kprobes: Avoid preempt count underflow without probe
Posted by Wentao Guan 1 month ago
Hello,

> @@ -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;
> +
This patch looks good to me.

BRs
Wentao Guan
Re: [PATCH] LoongArch: kprobes: Avoid preempt count underflow without probe
Posted by Bradley Morgan 1 month ago
On 23 August 2026 22:18:23 BST, "Jérémy Jean"
<Jeremy.Jean@oss.cyber.gouv.fr> 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.
>

Intresting

>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.
>

checked. Guess that's true

>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.
>

Ideal.

>The same check appeared in [PATCH v10 2/4] of the original LoongArch
>Kprobes series, but was dropped before the feature reached mainline.
>

wonder why.

>Link: https://patchew.org/linux/1670575981-14389-1-git-send-email-yangtiezhu%40loongson.cn/1670575981-14389-3-git-send-email-yangtiezhu%40loongson.cn/

Lore please.

>Fixes: 6d4cc40fb5f5 ("LoongArch: Add kprobes support")
>Assisted-by: Codex:gpt-5

5.6-sol? Or normal GPT 5?

>Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
>---
> 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;


comment?

/* do_bp() can reach
 * kprobe_singlestep_handler() when
 * there is no current probe, which
 * may cause issues.
 */

My one isn't perfect, but feel free to bikeshed


Well, I'm not a loongarch expert, but I am good with kprobes, hence this
review.


>+
> 	if (cur && (kcb->kprobe_status & (KPROBE_HIT_SS | KPROBE_REENTER)) &&
> 	    ((unsigned long)&cur->ainsn.insn[1] == addr)) {
> 		restore_local_irqflag(kcb, regs);
>

Thanks!