History

bpf: Add bpf_send_signal_thread() helper

Commit 8b401f9ed244 ("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.

Yonghong Song committed 6 years ago

Commit 84829411 parent d3a56933 files · +58 −7Browse files

Unified · Split

3 files
  1. include/uapi/linux/bpf.h +17 −2
  2. kernel/trace/bpf_trace.c +24 −3
  3. tools/include/uapi/linux/bpf.h +17 −2
include/uapi/linux/bpf.h+17−2
@@ -2714,7 +2714,8 @@ union bpf_attr { · 2713 unmodified lines
2714 *2714 *
2715 * int bpf_send_signal(u32 sig)2715 * int bpf_send_signal(u32 sig)
2716 * Description2716 * 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.
2718 * Return2719 * Return
2719 * 0 on success or successfully queued.2720 * 0 on success or successfully queued.
2720 *2721 *
@@ -2850,6 +2851,19 @@ union bpf_attr { · 129 unmodified lines
2850 * Return2851 * Return
2851 * 0 on success, or a negative error in case of failure.2852 * 0 on success, or a negative error in case of failure.
2852 *2853 *
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.
2853 */2867 */
2854#define __BPF_FUNC_MAPPER(FN) \2868#define __BPF_FUNC_MAPPER(FN) \
2855 FN(unspec), \2869 FN(unspec), \
@@ -2968,7 +2982,8 @@ union bpf_attr { · 112 unmodified lines
2968 FN(probe_read_kernel), \2982 FN(probe_read_kernel), \
2969 FN(probe_read_user_str), \2983 FN(probe_read_user_str), \
2970 FN(probe_read_kernel_str), \2984 FN(probe_read_kernel_str), \
2971 FN(tcp_send_ack),2985 FN(tcp_send_ack), \
2986 FN(send_signal_thread),
2972 2987
2973/* integer value in 'imm' field of BPF_CALL instruction selects which helper2988/* integer value in 'imm' field of BPF_CALL instruction selects which helper
2974 * function eBPF program intends to call2989 * function eBPF program intends to call
kernel/trace/bpf_trace.c+24−3
@@ -703,6 +703,7 @@ struct send_signal_irq_work { · 702 unmodified lines
703 struct irq_work irq_work;703 struct irq_work irq_work;
704 struct task_struct *task;704 struct task_struct *task;
705 u32 sig;705 u32 sig;
706 enum pid_type type;
706};707};
707 708
708static DEFINE_PER_CPU(struct send_signal_irq_work, send_signal_work);709static 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) · 3 unmodified lines
712 struct send_signal_irq_work *work;713 struct send_signal_irq_work *work;
713 714
714 work = container_of(entry, struct send_signal_irq_work, irq_work);715 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);
716}717}
717 718
718BPF_CALL_1(bpf_send_signal, u32, sig)719static int bpf_send_signal_common(u32 sig, enum pid_type type)
719{720{
720 struct send_signal_irq_work *work = NULL;721 struct send_signal_irq_work *work = NULL;
721 722
@@ -748,11 +749,17 @@ BPF_CALL_1(bpf_send_signal, u32, sig) · 26 unmodified lines
748 */749 */
749 work->task = current;750 work->task = current;
750 work->sig = sig;751 work->sig = sig;
752 work->type = type;
751 irq_work_queue(&work->irq_work);753 irq_work_queue(&work->irq_work);
752 return 0;754 return 0;
753 }755 }
754 756
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
760BPF_CALL_1(bpf_send_signal, u32, sig)
761{
762 return bpf_send_signal_common(sig, PIDTYPE_TGID);
756}763}
757 764
758static const struct bpf_func_proto bpf_send_signal_proto = {765static const struct bpf_func_proto bpf_send_signal_proto = {
@@ -762,6 +769,18 @@ static const struct bpf_func_proto bpf_send_signal_proto = { · 3 unmodified lines
762 .arg1_type = ARG_ANYTHING,769 .arg1_type = ARG_ANYTHING,
763};770};
764 771
772BPF_CALL_1(bpf_send_signal_thread, u32, sig)
773{
774 return bpf_send_signal_common(sig, PIDTYPE_PID);
775}
776
777static 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
765static const struct bpf_func_proto *784static const struct bpf_func_proto *
766tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)785tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
767{786{
@@ -822,6 +841,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) · 54 unmodified lines
822#endif841#endif
823 case BPF_FUNC_send_signal:842 case BPF_FUNC_send_signal:
824 return &bpf_send_signal_proto;843 return &bpf_send_signal_proto;
844 case BPF_FUNC_send_signal_thread:
845 return &bpf_send_signal_thread_proto;
825 default:846 default:
826 return NULL;847 return NULL;
827 }848 }
tools/include/uapi/linux/bpf.h+17−2
@@ -2714,7 +2714,8 @@ union bpf_attr { · 2713 unmodified lines
2714 *2714 *
2715 * int bpf_send_signal(u32 sig)2715 * int bpf_send_signal(u32 sig)
2716 * Description2716 * 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.
2718 * Return2719 * Return
2719 * 0 on success or successfully queued.2720 * 0 on success or successfully queued.
2720 *2721 *
@@ -2850,6 +2851,19 @@ union bpf_attr { · 129 unmodified lines
2850 * Return2851 * Return
2851 * 0 on success, or a negative error in case of failure.2852 * 0 on success, or a negative error in case of failure.
2852 *2853 *
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.
2853 */2867 */
2854#define __BPF_FUNC_MAPPER(FN) \2868#define __BPF_FUNC_MAPPER(FN) \
2855 FN(unspec), \2869 FN(unspec), \
@@ -2968,7 +2982,8 @@ union bpf_attr { · 112 unmodified lines
2968 FN(probe_read_kernel), \2982 FN(probe_read_kernel), \
2969 FN(probe_read_user_str), \2983 FN(probe_read_user_str), \
2970 FN(probe_read_kernel_str), \2984 FN(probe_read_kernel_str), \
2971 FN(tcp_send_ack),2985 FN(tcp_send_ack), \
2986 FN(send_signal_thread),
2972 2987
2973/* integer value in 'imm' field of BPF_CALL instruction selects which helper2988/* integer value in 'imm' field of BPF_CALL instruction selects which helper
2974 * function eBPF program intends to call2989 * function eBPF program intends to call

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t