From: Yonghong Song <yonghong.song@linux.dev>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
Aditya Sharma <adi.sharma@zohomail.in>
Cc: bpf@vger.kernel.org, song@kernel.org, ast@kernel.org,
daniel@iogearbox.net, andrii@kernel.org, puranjay@kernel.org,
jolsa@kernel.org
Subject: Re: bpf: Is the nmi_uaccess_okay() check needed for bpf_send_signal_task()?
Date: Sun, 30 Aug 2026 20:40:16 -0700 [thread overview]
Message-ID: <a3314523-7ab6-4f1d-b411-be980b964079@linux.dev> (raw)
In-Reply-To: <CAEf4BzZY6uWdobXVyS1WrdtmRw_SLJsodm7d_c+Bhsw=chpJ+A@mail.gmail.com>
On 8/21/26 11:21 AM, Andrii Nakryiko wrote:
> On Wed, Aug 19, 2026 at 5:44 AM Aditya Sharma <adi.sharma@zohomail.in> wrote:
>> 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.
> Yeah, this is weird, at the very least it should be checking it for
> the provided task. But I also am not sure why we have to check this...
>
> Yonghong, do you remember why this was necessary? Can we just drop this?
I went through the history.
In 5.3: we have bpf_send_signal() helper:
BPF_CALL_1(bpf_send_signal, u32, sig)
{
...
/* Similar to bpf_probe_write_user, task needs to be
* in a sound condition and kernel memory access be
* permitted in order to send signal to the current
* task.
*/
if (unlikely(current->flags & (PF_KTHREAD | PF_EXITING)))
return -EPERM;
if (unlikely(uaccess_kernel()))
return -EPERM;
if (unlikely(!nmi_uaccess_okay()))
return -EPERM;
...
}
nmi_uaccess_okay() is needed for *current* task.
In 5.6, bpf_send_signal_thread() is added, but still for the same task,
so we still have:
static int bpf_send_signal_common(u32 sig, enum pid_type type)
{
...
/* Similar to bpf_probe_write_user, task needs to be
* in a sound condition and kernel memory access be
* permitted in order to send signal to the current
* task.
*/
if (unlikely(current->flags & (PF_KTHREAD | PF_EXITING)))
return -EPERM;
if (unlikely(uaccess_kernel()))
return -EPERM;
if (unlikely(!nmi_uaccess_okay()))
return -EPERM;
...
}
In the current master:
__bpf_kfunc int bpf_send_signal_task(struct task_struct *task, int sig, enum pid_type type,
u64 value)
{
if (type != PIDTYPE_PID && type != PIDTYPE_TGID)
return -EINVAL;
return bpf_send_signal_common(sig, type, task, value);
}
static int bpf_send_signal_common(u32 sig, enum pid_type type, struct task_struct *task, u64 value)
{
...
/* Similar to bpf_probe_write_user, task needs to be
* in a sound condition and kernel memory access be
* permitted in order to send signal to the current
* task.
*/
if (unlikely(task->flags & (PF_KTHREAD | PF_EXITING)))
return -EPERM;
if (unlikely(!nmi_uaccess_okay()))
return -EPERM;
/* Task should not be pid=1 to avoid kernel panic. */
if (unlikely(is_global_init(task)))
return -EPERM;
...
}
We probably cannot remove
if (unlikely(!nmi_uaccess_okay()))
return -EPERM;
unconditionally. The above 'if' statement should be guarded
with *current* task if it is different from parameter "task"
since nmi_uaccess_okay() is only for the *current* task.
>
>> 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
next prev parent reply other threads:[~2026-08-31 3:40 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
2026-09-08 23:20 ` Andrii Nakryiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a3314523-7ab6-4f1d-b411-be980b964079@linux.dev \
--to=yonghong.song@linux.dev \
--cc=adi.sharma@zohomail.in \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=jolsa@kernel.org \
--cc=puranjay@kernel.org \
--cc=song@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.