From patchwork Wed May 1 06:56:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 1093609 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="Xg2VXnLb"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44v8Ly23jRz9sNd for ; Wed, 1 May 2019 16:56:25 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726022AbfEAG4Z (ORCPT ); Wed, 1 May 2019 02:56:25 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:50780 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725973AbfEAG4Y (ORCPT ); Wed, 1 May 2019 02:56:24 -0400 Received: from pps.filterd (m0044008.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x416n4OD027110 for ; Tue, 30 Apr 2019 23:56:24 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=PmeAkAE06pMpRB/REAG1fnCdzjshvw6PgqQAob7U8kU=; b=Xg2VXnLb1oPl5ZUYRML46CG2pWDmZzRk1p0gxiM4WoZoHvKFDgI0Rl3GNNm4TxKoTviE CHJaefLZBAkDOUf7i6BO02TyfexzqFE3Tuo5isEQYAwzeJP6MS85v9sWIYE8IYW4Cvsr LZWMuJAePJV3xJYGSdc/aj2oaPCMXu68Qao= Received: from mail.thefacebook.com (mailout.thefacebook.com [199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2s6xhth6f1-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 30 Apr 2019 23:56:24 -0700 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::129) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 30 Apr 2019 23:56:22 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 230CB3702FBF; Tue, 30 Apr 2019 23:56:22 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: , CC: Alexei Starovoitov , Daniel Borkmann , , Peter Zijlstra , Yonghong Song Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next 1/3] bpf: implement bpf_send_signal() helper Date: Tue, 30 Apr 2019 23:56:22 -0700 Message-ID: <20190501065622.2599797-1-yhs@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190501065621.2599742-1-yhs@fb.com> References: <20190501065621.2599742-1-yhs@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-05-01_03:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: bpf-owner@vger.kernel.org Precedence: bulk List-Id: netdev.vger.kernel.org This patch tries to solve the following specific use case. Currently, bpf program can already collect stack traces when certain events happens (e.g., cache miss counter or cpu clock counter overflows). These stack traces can be used for performance analysis. For jitted programs, e.g., hhvm (jited php), it is very hard to get the true stack trace in the bpf program due to jit complexity. To resolve this issue, hhvm implements a signal handler, e.g. for SIGALARM, and a set of program locations which it can dump stack traces. When it receives a signal, it will dump the stack in next such program location. The following is the current way to handle this use case: . profiler installs a bpf program and polls on a map. When certain event happens, bpf program writes to a map. . Once receiving the information from the map, the profiler sends a signal to hhvm. This method could have large delays and cause profiling results skewed. This patch implements bpf_send_signal() helper to send a signal to hhvm in real time, resulting in intended stack traces. Signed-off-by: Yonghong Song --- include/uapi/linux/bpf.h | 15 ++++++- kernel/trace/bpf_trace.c | 85 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 72336bac7573..e3e824848335 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2667,6 +2667,18 @@ union bpf_attr { * 0 on success. * * **-ENOENT** if the bpf-local-storage cannot be found. + * + * int bpf_send_signal(u32 pid, u32 sig) + * Description + * Send signal *sig* to *pid*. + * Return + * 0 on success or successfully queued. + * + * **-ENOENT** if *pid* cannot be found. + * + * **-EBUSY** if work queue under nmi is full. + * + * Other negative values for actual signal sending errors. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2777,7 +2789,8 @@ union bpf_attr { FN(strtol), \ FN(strtoul), \ FN(sk_storage_get), \ - FN(sk_storage_delete), + FN(sk_storage_delete), \ + FN(send_signal), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 8607aba1d882..4f070c4d239e 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -559,6 +559,76 @@ static const struct bpf_func_proto bpf_probe_read_str_proto = { .arg3_type = ARG_ANYTHING, }; +struct send_signal_irq_work { + struct irq_work irq_work; + u32 pid; + u32 sig; +}; + +static DEFINE_PER_CPU(struct send_signal_irq_work, send_signal_work); + +static int do_bpf_send_signal_pid(u32 pid, u32 sig) +{ + struct task_struct *task; + struct pid *pidp; + + pidp = find_vpid(pid); + if (!pidp) + return -ENOENT; + + task = get_pid_task(pidp, PIDTYPE_PID); + if (!task) + return -ENOENT; + + kill_pid_info(sig, SEND_SIG_PRIV, pidp); + put_task_struct(task); + + return 0; +} + +static void do_bpf_send_signal(struct irq_work *entry) +{ + struct send_signal_irq_work *work; + + work = container_of(entry, struct send_signal_irq_work, irq_work); + do_bpf_send_signal_pid(work->pid, work->sig); +} + +BPF_CALL_2(bpf_send_signal, u32, pid, u32, sig) +{ + struct send_signal_irq_work *work = NULL; + + /* current may be in the middle of teardown and task_pid(current) + * becomes NULL. task_pid(current)) is needed to find pid namespace + * in order to locate proper pid structure for the target pid. + */ + if (!current || !task_pid(current)) + return; + + if (in_nmi()) { + work = this_cpu_ptr(&send_signal_work); + if (work->irq_work.flags & IRQ_WORK_BUSY) + return -EBUSY; + } + + if (!work) + return do_bpf_send_signal_pid(pid, sig); + + work->pid = pid; + work->sig = sig; + irq_work_queue(&work->irq_work); + + return 0; +} + +static const struct bpf_func_proto bpf_send_signal_proto = { + .func = bpf_send_signal, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_ANYTHING, + .arg2_type = ARG_ANYTHING, +}; + static const struct bpf_func_proto * tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { @@ -609,6 +679,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_get_current_cgroup_id: return &bpf_get_current_cgroup_id_proto; #endif + case BPF_FUNC_send_signal: + return &bpf_send_signal_proto; default: return NULL; } @@ -1334,5 +1406,18 @@ int __init bpf_event_init(void) return 0; } +static int __init send_signal_irq_work_init(void) +{ + int cpu; + struct send_signal_irq_work *work; + + for_each_possible_cpu(cpu) { + work = per_cpu_ptr(&send_signal_work, cpu); + init_irq_work(&work->irq_work, do_bpf_send_signal); + } + return 0; +} + fs_initcall(bpf_event_init); +subsys_initcall(send_signal_irq_work_init); #endif /* CONFIG_MODULES */ From patchwork Wed May 1 06:56:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 1093614 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="L7Idok9w"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44v8M22V3dz9sNd for ; Wed, 1 May 2019 16:56:30 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726125AbfEAG42 (ORCPT ); Wed, 1 May 2019 02:56:28 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:43912 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726005AbfEAG40 (ORCPT ); Wed, 1 May 2019 02:56:26 -0400 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x416mW8c023292 for ; Tue, 30 Apr 2019 23:56:26 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=USqjk3EJGRFLoec6O+/rFlqnlw84fmAE9AWomwTX9J0=; b=L7Idok9w7QrEKwo12wiW0vvwMGi3wfF7wXc0sHNdDJ8xpCaiitILSBs9uka6mspLvGfP xPuVHdQ77HufK2Gh+g6+mBlM+lbSyOvo/q/l0CE/YZnjFpUTxmNfItCmyWbBlBn09Udb kBiXXZbbiDu/UrWXumJJ5kUk4hgsIj9pxbk= Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com with ESMTP id 2s6xhnh71v-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 30 Apr 2019 23:56:25 -0700 Received: from mx-out.facebook.com (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:82::e) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Tue, 30 Apr 2019 23:56:24 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 51F9C3702FB8; Tue, 30 Apr 2019 23:56:23 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: , CC: Alexei Starovoitov , Daniel Borkmann , , Peter Zijlstra , Yonghong Song Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next 2/3] tools/bpf: sync bpf uapi header bpf.h Date: Tue, 30 Apr 2019 23:56:23 -0700 Message-ID: <20190501065623.2599923-1-yhs@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190501065621.2599742-1-yhs@fb.com> References: <20190501065621.2599742-1-yhs@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-05-01_03:, , signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 malwarescore=0 suspectscore=8 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=856 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1810050000 definitions=main-1905010048 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org sync bpf uapi header bpf.h to tools directory. Signed-off-by: Yonghong Song --- tools/include/uapi/linux/bpf.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 72336bac7573..e3e824848335 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -2667,6 +2667,18 @@ union bpf_attr { * 0 on success. * * **-ENOENT** if the bpf-local-storage cannot be found. + * + * int bpf_send_signal(u32 pid, u32 sig) + * Description + * Send signal *sig* to *pid*. + * Return + * 0 on success or successfully queued. + * + * **-ENOENT** if *pid* cannot be found. + * + * **-EBUSY** if work queue under nmi is full. + * + * Other negative values for actual signal sending errors. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2777,7 +2789,8 @@ union bpf_attr { FN(strtol), \ FN(strtoul), \ FN(sk_storage_get), \ - FN(sk_storage_delete), + FN(sk_storage_delete), \ + FN(send_signal), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call From patchwork Wed May 1 06:56:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 1093615 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=fb.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=fb.com header.i=@fb.com header.b="jCRkMQaq"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44v8M43M4Tz9sNm for ; Wed, 1 May 2019 16:56:32 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726150AbfEAG4a (ORCPT ); Wed, 1 May 2019 02:56:30 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:47818 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726005AbfEAG43 (ORCPT ); Wed, 1 May 2019 02:56:29 -0400 Received: from pps.filterd (m0109334.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x416qWVn017325 for ; Tue, 30 Apr 2019 23:56:28 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=UnnjVKA4o3llI1vxekgXOcSRB/T0mKqe0BaJWhnqp28=; b=jCRkMQaqkKFZsneOMgI0NZTWHls/w1Bnt9U2aEVHVzuKjp+p72wJKqYE7G2gaVFigtEI aJsAXAeqcdyd4m5x8ealn85W0hcHb5/6cmM18zmiagQzjabbhli14LVyl5R+DS+FOBDL KoZq7gxMVxi03/WbT26b7inIzqa6xw8aovQ= Received: from mail.thefacebook.com (mailout.thefacebook.com [199.201.64.23]) by mx0a-00082601.pphosted.com with ESMTP id 2s6xhp16u7-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 30 Apr 2019 23:56:28 -0700 Received: from mx-out.facebook.com (2620:10d:c081:10::13) by mail.thefacebook.com (2620:10d:c081:35::126) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5; Tue, 30 Apr 2019 23:56:26 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 8260E3702FB8; Tue, 30 Apr 2019 23:56:24 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: , CC: Alexei Starovoitov , Daniel Borkmann , , Peter Zijlstra , Yonghong Song Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next 3/3] tools/bpf: add a selftest for bpf_send_signal() helper Date: Tue, 30 Apr 2019 23:56:24 -0700 Message-ID: <20190501065624.2600001-1-yhs@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190501065621.2599742-1-yhs@fb.com> References: <20190501065621.2599742-1-yhs@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2019-05-01_03:, , signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The test covered both nmi and tracepoint perf events. $ ./test_send_signal_user test_send_signal (tracepoint): OK test_send_signal (perf_event): OK Signed-off-by: Yonghong Song --- tools/testing/selftests/bpf/Makefile | 5 +- tools/testing/selftests/bpf/bpf_helpers.h | 2 + .../bpf/progs/test_send_signal_kern.c | 50 +++++ .../selftests/bpf/test_send_signal_user.c | 186 ++++++++++++++++++ 4 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/test_send_signal_kern.c create mode 100644 tools/testing/selftests/bpf/test_send_signal_user.c diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 66f2dca1dee1..c3aa33dfae18 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -23,7 +23,8 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \ test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names \ - test_netcnt test_tcpnotify_user test_sock_fields test_sysctl + test_netcnt test_tcpnotify_user test_sock_fields test_sysctl \ + test_send_signal_user BPF_OBJ_FILES = $(patsubst %.c,%.o, $(notdir $(wildcard progs/*.c))) TEST_GEN_FILES = $(BPF_OBJ_FILES) @@ -124,7 +125,7 @@ endif CLANG_SYS_INCLUDES := $(shell $(CLANG) -v -E - &1 \ | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') -CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi \ +CLANG_FLAGS = -I. -I./include/uapi -I../../../include/uapi -I../../../include \ $(CLANG_SYS_INCLUDES) \ -Wno-compare-distinct-pointer-types diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 6e80b66d7fb1..4517bca4f9ed 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -216,6 +216,8 @@ static void *(*bpf_sk_storage_get)(void *map, struct bpf_sock *sk, (void *) BPF_FUNC_sk_storage_get; static int (*bpf_sk_storage_delete)(void *map, struct bpf_sock *sk) = (void *)BPF_FUNC_sk_storage_delete; +static int (*bpf_send_signal)(unsigned pid, unsigned sig) = + (void *)BPF_FUNC_send_signal; /* llvm builtin functions that eBPF C program may use to * emit BPF_LD_ABS and BPF_LD_IND instructions diff --git a/tools/testing/selftests/bpf/progs/test_send_signal_kern.c b/tools/testing/selftests/bpf/progs/test_send_signal_kern.c new file mode 100644 index 000000000000..b81dbbf60b3d --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_send_signal_kern.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook +#include +#include +#include +#include "bpf_helpers.h" + +struct bpf_map_def SEC("maps") info_map = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(__u32), + .value_size = sizeof(__u64), + .max_entries = 1, +}; + +BPF_ANNOTATE_KV_PAIR(info_map, __u32, __u64); + +struct bpf_map_def SEC("maps") status_map = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(__u32), + .value_size = sizeof(__u64), + .max_entries = 1, +}; + +BPF_ANNOTATE_KV_PAIR(status_map, __u32, __u64); + +SEC("send_signal_demo") +int bpf_send_signal_test(void *ctx) +{ + __u64 *info_val, *status_val; + __u32 key = 0, pid, sig; + int ret; + + status_val = bpf_map_lookup_elem(&status_map, &key); + if (!status_val || *status_val != 0) + return 0; + + info_val = bpf_map_lookup_elem(&info_map, &key); + if (!info_val || *info_val == 0) + return 0; + + sig = *info_val >> 32; + pid = *info_val & 0xffffFFFF; + + ret = bpf_send_signal(pid, sig); + if (ret == 0) + *status_val = 1; + + return 0; +} +char __license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/test_send_signal_user.c b/tools/testing/selftests/bpf/test_send_signal_user.c new file mode 100644 index 000000000000..38898c575bd2 --- /dev/null +++ b/tools/testing/selftests/bpf/test_send_signal_user.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "bpf_rlimit.h" + +static volatile int signal_received = 0; + +static void sigusr1_handler(int signum) +{ + signal_received++; +} + +static void test_common(struct perf_event_attr *attr, int prog_type, + const char *test_name, int trace_pid, int cpu) +{ + int pmu_fd, prog_fd, info_map_fd, status_map_fd; + const char *file = "./test_send_signal_kern.o"; + struct bpf_object *obj = NULL; + int pipe_c2p[2], pipe_p2c[2]; + char buf[256]; + int err = 0; + u32 key = 0; + pid_t pid; + u64 val; + + if (pipe(pipe_c2p) < 0) { + fprintf(stderr, "Creating pipe c2p error\n"); + return; + } + if (pipe(pipe_p2c) < 0) { + fprintf(stderr, "Creating pipe p2c error\n"); + return; + } + + pid = fork(); + if (pid == 0) { + /* install signal handler and notify parent */ + signal(SIGUSR1, sigusr1_handler); + + close(pipe_c2p[0]); /* close read */ + close(pipe_p2c[1]); /* close write */ + + /* notify parent signal handler is installed */ + write(pipe_c2p[1], buf, 1); + + /* make sense parent enabled bpf program to send_signal */ + read(pipe_p2c[0], buf, 1); + + /* wait a little for signal handler */ + sleep(1); + + if (signal_received) + write(pipe_c2p[1], "2", 1); + else + write(pipe_c2p[1], "0", 1); + + /* wait for parent notification and exit */ + read(pipe_p2c[0], buf, 1); + exit(0); + } + + close(pipe_c2p[1]); /* close write */ + close(pipe_p2c[0]); /* close read */ + + err = bpf_prog_load(file, prog_type, &obj, &prog_fd); + if (err) { + printf("test_send_signal:bpf_prog_load errno %d\n", errno); + goto close_prog; + } + + pmu_fd = syscall(__NR_perf_event_open, attr, trace_pid, cpu, + -1 /* group id */, 0 /* flags */); + if (pmu_fd < 0) + goto close_prog; + + err = ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0); + if (err) + goto disable_pmu; + + err = ioctl(pmu_fd, PERF_EVENT_IOC_SET_BPF, prog_fd); + if (err) + goto disable_pmu; + + info_map_fd = bpf_object__find_map_fd_by_name(obj, "info_map"); + if (info_map_fd < 0) + goto disable_pmu; + + status_map_fd = bpf_object__find_map_fd_by_name(obj, "status_map"); + if (status_map_fd < 0) + goto disable_pmu; + + /* wait until child signal handler installed */ + read(pipe_c2p[0], buf, 1); + + /* trigger the bpf send_signal */ + key = 0; + val = (((u64)(SIGUSR1)) << 32) | pid; + bpf_map_update_elem(info_map_fd, &key, &val, 0); + + /* notify child that bpf program can send_signal now */ + write(pipe_p2c[1], buf, 1); + + /* wait for result */ + read(pipe_c2p[0], buf, 1); + + if (buf[0] == '2') + printf("test_send_signal (%s): OK\n", test_name); + else + printf("test_send_signal (%s): FAIL\n", test_name); + + /* notify child safe to exit */ + write(pipe_p2c[1], buf, 1); + + goto close_prog_noerr; + +close_prog: +disable_pmu: + printf("test_send_signal (%s) :FAIL\n", test_name); +close_prog_noerr: + bpf_object__close(obj); + + wait(NULL); +} + +static void test_tracepoint(void) +{ + struct perf_event_attr attr = { + .type = PERF_TYPE_TRACEPOINT, + .sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CALLCHAIN, + .sample_period = 1, + .wakeup_events = 1, + }; + int bytes, efd; + char buf[256]; + + snprintf(buf, sizeof(buf), + "/sys/kernel/debug/tracing/events/syscalls/sys_enter_nanosleep/id"); + efd = open(buf, O_RDONLY, 0); + if (efd < 0) { + printf("test_send_signal:bpf_prog_load errno %d\n", errno); + return; + } + + bytes = read(efd, buf, sizeof(buf)); + close(efd); + if (bytes <= 0 || bytes >= sizeof(buf)) + return; + + attr.config = strtol(buf, NULL, 0); + + test_common(&attr, BPF_PROG_TYPE_TRACEPOINT, "tracepoint", -1, 0); +} + +static void test_nmi_perf_event(void) +{ + struct perf_event_attr attr = { + .sample_freq = 50, + .freq = 1, + .type = PERF_TYPE_HARDWARE, + .config = PERF_COUNT_HW_CPU_CYCLES, + }; + + test_common(&attr, BPF_PROG_TYPE_PERF_EVENT, "perf_event", -1, 0); +} + +int main(void) +{ + test_tracepoint(); + test_nmi_perf_event(); + return 0; +}