All of lore.kernel.org
 help / color / mirror / Atom feed
* bpf: Is the nmi_uaccess_okay() check needed for bpf_send_signal_task()?
@ 2026-08-19 12:43 Aditya Sharma
  2026-08-21 18:21 ` Andrii Nakryiko
  0 siblings, 1 reply; 4+ messages in thread
From: Aditya Sharma @ 2026-08-19 12:43 UTC (permalink / raw)
  To: bpf, song; +Cc: ast, daniel, andrii, puranjay, yonghong.song, jolsa

Hi,

I hit this from a bpf_timer callback that signals a userspace task: the
signal was not delivered some of the time. It turned out that
bpf_send_signal_task() was returning -EPERM depending on which task the
softirq happened to interrupt, and the source is this check in
bpf_send_signal_common():

bpf_trace.c:872:	if (unlikely(task->flags & (PF_KTHREAD | PF_EXITING)))
bpf_trace.c:873:		return -EPERM;
bpf_trace.c:874:	if (unlikely(!nmi_uaccess_okay()))
bpf_trace.c:875:		return -EPERM;

Is the nmi_uaccess_okay() check necessary in the bpf_send_signal_task()
case?

When commit 6280cf7 ("bpf: Implement bpf_send_signal_task() kfunc")
made the function take a task, the PF_KTHREAD and is_global_init()
started testing task, while nmi_uaccess_okay() kept testing current.

As far as I can tell the path here does no user memory access, so
there is nothing for the check to guard.

Also, it compiles to true outside x86 (include/asm-generic/tlb.h:26),
so if it were necessary here the kfunc would be broken on every other
architecture.

Thus, whether a signal can be sent depends on the caller's context,
rather than the task it is to be sent to. And at the bpf_timer callback,
we never know deterministically whether the signal would go through,
or it would get rejected here.

A quick reproducibility test by Claude Opus 5 (the issue I was facing
from the timer callback context was not reproducible deterministically):

SEC("tp_btf/workqueue_execute_start")   /* current is a kworker   */
SEC("tp_btf/sys_enter")                 /* current is a user task */

static __always_inline int probe(void)
{
struct task_struct *t;
int ret;

t = bpf_task_from_pid(target_pid);
if (!t)
  return -ESRCH;
/* sig == 0: permission check only, nothing is delivered */
ret = bpf_send_signal_task(t, 0, PIDTYPE_TGID, 0);
bpf_task_release(t);
return ret;
}

On bpf-next commit f79066c7 (selftests/bpf: Add tests for a store
on a fault prone qdisc pointer), x86_64 under qemu:

bpf_send_signal_task() from kworker context : -1  (-EPERM)
bpf_send_signal_task() from syscall context :  0

Same result on v6.18.29, x86_64, bare metal.

I may be missing the reason for it to be there as well. If this check
is intentional, what is it protecting in the _task case?

Thanks,
Aditya Sharma

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-09-08 23:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-19 12:43 bpf: Is the nmi_uaccess_okay() check needed for bpf_send_signal_task()? Aditya Sharma
2026-08-21 18:21 ` Andrii Nakryiko
2026-08-31  3:40   ` Yonghong Song
2026-09-08 23:20     ` Andrii Nakryiko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.