> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index 195f78db9bda..e60b4fdf2923 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -823,6 +823,8 @@ const struct bpf_func_proto bpf_task_pt_regs_proto = {
>
>  struct send_signal_irq_work {
>       struct irq_work irq_work;
> +     /* Covers the fill-to-run span which irq_work_is_busy() cannot see. */
> +     atomic_t claimed;
>       struct task_struct *task;
>       u32 sig;
>       enum pid_type type;
> @@ -842,6 +844,8 @@ static void do_bpf_send_signal(struct irq_work *entry)
>
>       group_send_sig_info(work->sig, siginfo, work->task, work->type);
>       put_task_struct(work->task);
> +     /* Release once the fields are consumed. */
> +     atomic_set_release(&work->claimed, 0);
>  }
>
>  static int bpf_send_signal_common(u32 sig, enum pid_type type, struct 
> task_struct *task, u64 value)
> @@ -885,7 +889,7 @@ static int bpf_send_signal_common(u32 sig, enum pid_type 
> type, struct task_struc
>                       return -EINVAL;
>
>               work = this_cpu_ptr(&send_signal_work);
> -             if (irq_work_is_busy(&work->irq_work))
> +             if (atomic_xchg(&work->claimed, 1))
>                       return -EBUSY;
>
>               /* Add the current task, which is the target of sending signal,
> @@ -898,7 +902,12 @@ static int bpf_send_signal_common(u32 sig, enum pid_type 
> type, struct task_struc
>                       copy_siginfo(&work->info, &info);
>               work->sig = sig;
>               work->type = type;
> -             irq_work_queue(&work->irq_work);
> +             if (unlikely(!irq_work_queue(&work->irq_work))) {
> +                     /* Unreachable while the claim is held. */
> +                     put_task_struct(task);
> +                     atomic_set_release(&work->claimed, 0);
> +                     return -EBUSY;
> +             }

This isn't a bug, but since the comment says this cannot happen while the
claim is held, would it be clearer to drop the branch or reduce it to a
WARN_ON_ONCE(!irq_work_queue(...))? As written it looks like a recovery
path, but it wouldn't actually undo the overwritten fields if it ever ran.

>               return 0;
>       }
>

---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/36398456272

Reply via email to