Skip to content

Commit 8482941

Browse files
yonghong-songAlexei Starovoitov
authored and
Alexei Starovoitov
committed
bpf: Add bpf_send_signal_thread() helper
Commit 8b401f9 ("bpf: implement bpf_send_signal() helper") added helper bpf_send_signal() which permits bpf program to send a signal to the current process. The signal may be delivered to any threads in the process. We found a use case where sending the signal to the current thread is more preferable. - A bpf program will collect the stack trace and then send signal to the user application. - The user application will add some thread specific information to the just collected stack trace for later analysis. If bpf_send_signal() is used, user application will need to check whether the thread receiving the signal matches the thread collecting the stack by checking thread id. If not, it will need to send signal to another thread through pthread_kill(). This patch proposed a new helper bpf_send_signal_thread(), which sends the signal to the thread corresponding to the current kernel task. This way, user space is guaranteed that bpf_program execution context and user space signal handling context are the same thread. Signed-off-by: Yonghong Song <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent d3a5693 commit 8482941

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

Diff for: include/uapi/linux/bpf.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -2714,7 +2714,8 @@ union bpf_attr {
27142714
*
27152715
* int bpf_send_signal(u32 sig)
27162716
* Description
2717-
* Send signal *sig* to the current task.
2717+
* Send signal *sig* to the process of the current task.
2718+
* The signal may be delivered to any of this process's threads.
27182719
* Return
27192720
* 0 on success or successfully queued.
27202721
*
@@ -2850,6 +2851,19 @@ union bpf_attr {
28502851
* Return
28512852
* 0 on success, or a negative error in case of failure.
28522853
*
2854+
* int bpf_send_signal_thread(u32 sig)
2855+
* Description
2856+
* Send signal *sig* to the thread corresponding to the current task.
2857+
* Return
2858+
* 0 on success or successfully queued.
2859+
*
2860+
* **-EBUSY** if work queue under nmi is full.
2861+
*
2862+
* **-EINVAL** if *sig* is invalid.
2863+
*
2864+
* **-EPERM** if no permission to send the *sig*.
2865+
*
2866+
* **-EAGAIN** if bpf program can try again.
28532867
*/
28542868
#define __BPF_FUNC_MAPPER(FN) \
28552869
FN(unspec), \
@@ -2968,7 +2982,8 @@ union bpf_attr {
29682982
FN(probe_read_kernel), \
29692983
FN(probe_read_user_str), \
29702984
FN(probe_read_kernel_str), \
2971-
FN(tcp_send_ack),
2985+
FN(tcp_send_ack), \
2986+
FN(send_signal_thread),
29722987

29732988
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
29742989
* function eBPF program intends to call

Diff for: kernel/trace/bpf_trace.c

+24-3
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ struct send_signal_irq_work {
703703
struct irq_work irq_work;
704704
struct task_struct *task;
705705
u32 sig;
706+
enum pid_type type;
706707
};
707708

708709
static DEFINE_PER_CPU(struct send_signal_irq_work, send_signal_work);
@@ -712,10 +713,10 @@ static void do_bpf_send_signal(struct irq_work *entry)
712713
struct send_signal_irq_work *work;
713714

714715
work = container_of(entry, struct send_signal_irq_work, irq_work);
715-
group_send_sig_info(work->sig, SEND_SIG_PRIV, work->task, PIDTYPE_TGID);
716+
group_send_sig_info(work->sig, SEND_SIG_PRIV, work->task, work->type);
716717
}
717718

718-
BPF_CALL_1(bpf_send_signal, u32, sig)
719+
static int bpf_send_signal_common(u32 sig, enum pid_type type)
719720
{
720721
struct send_signal_irq_work *work = NULL;
721722

@@ -748,11 +749,17 @@ BPF_CALL_1(bpf_send_signal, u32, sig)
748749
*/
749750
work->task = current;
750751
work->sig = sig;
752+
work->type = type;
751753
irq_work_queue(&work->irq_work);
752754
return 0;
753755
}
754756

755-
return group_send_sig_info(sig, SEND_SIG_PRIV, current, PIDTYPE_TGID);
757+
return group_send_sig_info(sig, SEND_SIG_PRIV, current, type);
758+
}
759+
760+
BPF_CALL_1(bpf_send_signal, u32, sig)
761+
{
762+
return bpf_send_signal_common(sig, PIDTYPE_TGID);
756763
}
757764

758765
static const struct bpf_func_proto bpf_send_signal_proto = {
@@ -762,6 +769,18 @@ static const struct bpf_func_proto bpf_send_signal_proto = {
762769
.arg1_type = ARG_ANYTHING,
763770
};
764771

772+
BPF_CALL_1(bpf_send_signal_thread, u32, sig)
773+
{
774+
return bpf_send_signal_common(sig, PIDTYPE_PID);
775+
}
776+
777+
static const struct bpf_func_proto bpf_send_signal_thread_proto = {
778+
.func = bpf_send_signal_thread,
779+
.gpl_only = false,
780+
.ret_type = RET_INTEGER,
781+
.arg1_type = ARG_ANYTHING,
782+
};
783+
765784
static const struct bpf_func_proto *
766785
tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
767786
{
@@ -822,6 +841,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
822841
#endif
823842
case BPF_FUNC_send_signal:
824843
return &bpf_send_signal_proto;
844+
case BPF_FUNC_send_signal_thread:
845+
return &bpf_send_signal_thread_proto;
825846
default:
826847
return NULL;
827848
}

Diff for: tools/include/uapi/linux/bpf.h

+17-2
Original file line numberDiff line numberDiff line change
@@ -2714,7 +2714,8 @@ union bpf_attr {
27142714
*
27152715
* int bpf_send_signal(u32 sig)
27162716
* Description
2717-
* Send signal *sig* to the current task.
2717+
* Send signal *sig* to the process of the current task.
2718+
* The signal may be delivered to any of this process's threads.
27182719
* Return
27192720
* 0 on success or successfully queued.
27202721
*
@@ -2850,6 +2851,19 @@ union bpf_attr {
28502851
* Return
28512852
* 0 on success, or a negative error in case of failure.
28522853
*
2854+
* int bpf_send_signal_thread(u32 sig)
2855+
* Description
2856+
* Send signal *sig* to the thread corresponding to the current task.
2857+
* Return
2858+
* 0 on success or successfully queued.
2859+
*
2860+
* **-EBUSY** if work queue under nmi is full.
2861+
*
2862+
* **-EINVAL** if *sig* is invalid.
2863+
*
2864+
* **-EPERM** if no permission to send the *sig*.
2865+
*
2866+
* **-EAGAIN** if bpf program can try again.
28532867
*/
28542868
#define __BPF_FUNC_MAPPER(FN) \
28552869
FN(unspec), \
@@ -2968,7 +2982,8 @@ union bpf_attr {
29682982
FN(probe_read_kernel), \
29692983
FN(probe_read_user_str), \
29702984
FN(probe_read_kernel_str), \
2971-
FN(tcp_send_ack),
2985+
FN(tcp_send_ack), \
2986+
FN(send_signal_thread),
29722987

29732988
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
29742989
* function eBPF program intends to call

0 commit comments

Comments
 (0)