From patchwork Wed Apr 15 19:27:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221141 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F160EC2BA19 for ; Wed, 15 Apr 2020 19:32:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CE12220732 for ; Wed, 15 Apr 2020 19:32:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="AK5/ZCib" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2633091AbgDOTcR (ORCPT ); Wed, 15 Apr 2020 15:32:17 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:58822 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2411729AbgDOT2P (ORCPT ); Wed, 15 Apr 2020 15:28:15 -0400 Received: from pps.filterd (m0001303.ppops.net [127.0.0.1]) by m0001303.ppops.net (8.16.0.42/8.16.0.42) with SMTP id 03FJSCn0007656 for ; Wed, 15 Apr 2020 12:28:14 -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-transfer-encoding : content-type; s=facebook; bh=ZbsCGaCv9Gsm85mgP5XUnKAzAoNTMbL2upv04wMKm5c=; b=AK5/ZCib4aeceMToaf33Wc8U1jlmW6QSEgEDrP789kAV/IiOSJS1T08f8PVvv1G/v5uA ee65iu9/tcpgRaRY79N9kaGQhyox27x0zeQRQCi+mBrQIWb58txKWPb93npwoHtEx4wH tD7n5drhueisJoveFwEd+wvokbESuEJtgTQ= Received: from mail.thefacebook.com ([163.114.132.120]) by m0001303.ppops.net with ESMTP id 30dn7fymkx-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:14 -0700 Received: from intmgw001.03.ash8.facebook.com (2620:10d:c085:208::11) by mail.thefacebook.com (2620:10d:c085:21d::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:27:42 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 07AF43700AF5; Wed, 15 Apr 2020 12:27:42 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 02/17] bpf: create /sys/kernel/bpfdump mount file system Date: Wed, 15 Apr 2020 12:27:41 -0700 Message-ID: <20200415192741.4082788-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 lowpriorityscore=0 suspectscore=2 phishscore=0 mlxscore=0 spamscore=0 adultscore=0 impostorscore=0 mlxlogscore=999 priorityscore=1501 bulkscore=0 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch creates a mount point "bpfdump" under /sys/kernel. The file system has a single user mode, i.e., all mount points will be identical. The magic number I picked for the new file system is "dump". Signed-off-by: Yonghong Song --- include/uapi/linux/magic.h | 1 + kernel/bpf/Makefile | 1 + kernel/bpf/dump.c | 79 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 kernel/bpf/dump.c diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index d78064007b17..4ce3d8882315 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -88,6 +88,7 @@ #define BPF_FS_MAGIC 0xcafe4a11 #define AAFS_MAGIC 0x5a3c69f0 #define ZONEFS_MAGIC 0x5a4f4653 +#define DUMPFS_MAGIC 0x64756d70 /* Since UDF 2.01 is ISO 13346 based... */ #define UDF_SUPER_MAGIC 0x15013346 diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index f2d7be596966..4a1376ab2bea 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_BPF_SYSCALL) += reuseport_array.o endif ifeq ($(CONFIG_SYSFS),y) obj-$(CONFIG_DEBUG_INFO_BTF) += sysfs_btf.o +obj-$(CONFIG_BPF_SYSCALL) += dump.o endif ifeq ($(CONFIG_BPF_JIT),y) obj-$(CONFIG_BPF_SYSCALL) += bpf_struct_ops.o diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c new file mode 100644 index 000000000000..e0c33486e0e7 --- /dev/null +++ b/kernel/bpf/dump.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2020 Facebook */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void bpfdump_free_inode(struct inode *inode) +{ + kfree(inode->i_private); + free_inode_nonrcu(inode); +} + +static const struct super_operations bpfdump_super_operations = { + .statfs = simple_statfs, + .free_inode = bpfdump_free_inode, +}; + +static int bpfdump_fill_super(struct super_block *sb, struct fs_context *fc) +{ + static const struct tree_descr files[] = { { "" } }; + int err; + + err = simple_fill_super(sb, DUMPFS_MAGIC, files); + if (err) + return err; + + sb->s_op = &bpfdump_super_operations; + return 0; +} + +static int bpfdump_get_tree(struct fs_context *fc) +{ + return get_tree_single(fc, bpfdump_fill_super); +} + +static const struct fs_context_operations bpfdump_context_ops = { + .get_tree = bpfdump_get_tree, +}; + +static int bpfdump_init_fs_context(struct fs_context *fc) +{ + fc->ops = &bpfdump_context_ops; + return 0; +} + +static struct file_system_type fs_type = { + .owner = THIS_MODULE, + .name = "bpfdump", + .init_fs_context = bpfdump_init_fs_context, + .kill_sb = kill_litter_super, +}; + +static int __init bpfdump_init(void) +{ + int ret; + + ret = sysfs_create_mount_point(kernel_kobj, "bpfdump"); + if (ret) + return ret; + + ret = register_filesystem(&fs_type); + if (ret) + goto remove_mount; + + return 0; + +remove_mount: + sysfs_remove_mount_point(kernel_kobj, "bpfdump"); + return ret; +} +core_initcall(bpfdump_init); From patchwork Wed Apr 15 19:27:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221140 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 133D5C2BA19 for ; Wed, 15 Apr 2020 19:32:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E462820732 for ; Wed, 15 Apr 2020 19:32:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="TAJOfQRo" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2633375AbgDOTc1 (ORCPT ); Wed, 15 Apr 2020 15:32:27 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:46238 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2407077AbgDOT2O (ORCPT ); Wed, 15 Apr 2020 15:28:14 -0400 Received: from pps.filterd (m0001303.ppops.net [127.0.0.1]) by m0001303.ppops.net (8.16.0.42/8.16.0.42) with SMTP id 03FJSCir007612 for ; Wed, 15 Apr 2020 12:28:12 -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-transfer-encoding : content-type; s=facebook; bh=csV7CddIlvWoRtIWqh3RbrfW9v/5I//mbv5nrjj/WN8=; b=TAJOfQRo7RmfW/sMIKCpJpsArYcLOgrrrYVHeFwtdgdEAc6qwywMsQE1vlzoj7wD6xEM Kvm9aMFI1RpSXaHP75p6PtT4/oa35Viz92rHHfjQeYnV+RkPQApJkwvQde/Mm2zdHOLW Kw0k3o3CvLk5YStUhVwjTR+N8TyDUeafy4E= Received: from mail.thefacebook.com ([163.114.132.120]) by m0001303.ppops.net with ESMTP id 30dn7fymmm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:12 -0700 Received: from intmgw002.03.ash8.facebook.com (2620:10d:c085:208::f) by mail.thefacebook.com (2620:10d:c085:11d::4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:27:46 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 7B5F33700AF5; Wed, 15 Apr 2020 12:27:44 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 04/17] bpf: allow loading of a dumper program Date: Wed, 15 Apr 2020 12:27:44 -0700 Message-ID: <20200415192744.4082950-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 lowpriorityscore=0 suspectscore=2 phishscore=0 mlxscore=0 spamscore=0 adultscore=0 impostorscore=0 mlxlogscore=999 priorityscore=1501 bulkscore=0 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org A dumper bpf program is a tracing program with attach type BPF_TRACE_DUMP. During bpf program load, the load attribute attach_prog_fd carries the target directory fd. The program will be verified against btf_id of the target_proto. If the program is loaded successfully, the dump target, as represented as a relative path to /sys/kernel/bpfdump, will be remembered in prog->aux->dump_target, which will be used later to create dumpers. Signed-off-by: Yonghong Song --- include/linux/bpf.h | 2 ++ include/uapi/linux/bpf.h | 6 ++++- kernel/bpf/dump.c | 42 ++++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 8 ++++++- kernel/bpf/verifier.c | 15 ++++++++++++ tools/include/uapi/linux/bpf.h | 6 ++++- 6 files changed, 76 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 84c7eb40d7bc..068552c2d2cf 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -674,6 +674,7 @@ struct bpf_prog_aux { struct bpf_map **used_maps; struct bpf_prog *prog; struct user_struct *user; + const char *dump_target; u64 load_time; /* ns since boottime */ struct bpf_map *cgroup_storage[MAX_BPF_CGROUP_STORAGE_TYPE]; char name[BPF_OBJ_NAME_LEN]; @@ -1120,6 +1121,7 @@ struct bpf_dump_reg { }; int bpf_dump_reg_target(struct bpf_dump_reg *reg_info); +int bpf_dump_set_target_info(u32 target_fd, struct bpf_prog *prog); int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value); int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2e29a671d67e..f92b919c723e 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -215,6 +215,7 @@ enum bpf_attach_type { BPF_TRACE_FEXIT, BPF_MODIFY_RETURN, BPF_LSM_MAC, + BPF_TRACE_DUMP, __MAX_BPF_ATTACH_TYPE }; @@ -476,7 +477,10 @@ union bpf_attr { __aligned_u64 line_info; /* line info */ __u32 line_info_cnt; /* number of bpf_line_info records */ __u32 attach_btf_id; /* in-kernel BTF type id to attach to */ - __u32 attach_prog_fd; /* 0 to attach to vmlinux */ + union { + __u32 attach_prog_fd; /* 0 to attach to vmlinux */ + __u32 attach_target_fd; + }; }; struct { /* anonymous struct used by BPF_OBJ_* commands */ diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index e8b46f9e0ee0..8c7a89800312 100644 --- a/kernel/bpf/dump.c +++ b/kernel/bpf/dump.c @@ -11,6 +11,9 @@ #include #include #include +#include + +extern struct btf *btf_vmlinux; struct bpfdump_target_info { struct list_head list; @@ -51,6 +54,45 @@ static const struct inode_operations bpfdump_dir_iops = { .unlink = dumper_unlink, }; +int bpf_dump_set_target_info(u32 target_fd, struct bpf_prog *prog) +{ + struct bpfdump_target_info *tinfo; + const char *target_proto; + struct file *target_file; + struct fd tfd; + int err = 0, btf_id; + + if (!btf_vmlinux) + return -EINVAL; + + tfd = fdget(target_fd); + target_file = tfd.file; + if (!target_file) + return -EBADF; + + if (target_file->f_inode->i_op != &bpfdump_dir_iops) { + err = -EINVAL; + goto done; + } + + tinfo = target_file->f_inode->i_private; + target_proto = tinfo->target_proto; + btf_id = btf_find_by_name_kind(btf_vmlinux, target_proto, + BTF_KIND_FUNC); + + if (btf_id < 0) { + err = btf_id; + goto done; + } + + prog->aux->dump_target = tinfo->target; + prog->aux->attach_btf_id = btf_id; + +done: + fdput(tfd); + return err; +} + int bpf_dump_reg_target(struct bpf_dump_reg *reg_info) { struct bpfdump_target_info *tinfo, *ptinfo; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 64783da34202..1ce2f74f8efc 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2060,7 +2060,12 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) prog->expected_attach_type = attr->expected_attach_type; prog->aux->attach_btf_id = attr->attach_btf_id; - if (attr->attach_prog_fd) { + if (type == BPF_PROG_TYPE_TRACING && + attr->expected_attach_type == BPF_TRACE_DUMP) { + err = bpf_dump_set_target_info(attr->attach_target_fd, prog); + if (err) + goto free_prog_nouncharge; + } else if (attr->attach_prog_fd) { struct bpf_prog *tgt_prog; tgt_prog = bpf_prog_get(attr->attach_prog_fd); @@ -2145,6 +2150,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) err = bpf_prog_new_fd(prog); if (err < 0) bpf_prog_put(prog); + return err; free_used_maps: diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 04c6630cc18f..f531cee24fc5 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10426,6 +10426,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) struct bpf_prog *tgt_prog = prog->aux->linked_prog; u32 btf_id = prog->aux->attach_btf_id; const char prefix[] = "btf_trace_"; + struct btf_func_model fmodel; int ret = 0, subprog = -1, i; struct bpf_trampoline *tr; const struct btf_type *t; @@ -10566,6 +10567,20 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) prog->aux->attach_func_proto = t; prog->aux->attach_btf_trace = true; return 0; + case BPF_TRACE_DUMP: + if (!btf_type_is_func(t)) { + verbose(env, "attach_btf_id %u is not a function\n", + btf_id); + return -EINVAL; + } + t = btf_type_by_id(btf, t->type); + if (!btf_type_is_func_proto(t)) + return -EINVAL; + prog->aux->attach_func_name = tname; + prog->aux->attach_func_proto = t; + ret = btf_distill_func_proto(&env->log, btf, t, + tname, &fmodel); + return ret; default: if (!prog_extension) return -EINVAL; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 2e29a671d67e..f92b919c723e 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -215,6 +215,7 @@ enum bpf_attach_type { BPF_TRACE_FEXIT, BPF_MODIFY_RETURN, BPF_LSM_MAC, + BPF_TRACE_DUMP, __MAX_BPF_ATTACH_TYPE }; @@ -476,7 +477,10 @@ union bpf_attr { __aligned_u64 line_info; /* line info */ __u32 line_info_cnt; /* number of bpf_line_info records */ __u32 attach_btf_id; /* in-kernel BTF type id to attach to */ - __u32 attach_prog_fd; /* 0 to attach to vmlinux */ + union { + __u32 attach_prog_fd; /* 0 to attach to vmlinux */ + __u32 attach_target_fd; + }; }; struct { /* anonymous struct used by BPF_OBJ_* commands */ From patchwork Wed Apr 15 19:27:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221139 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DC768C2BB85 for ; Wed, 15 Apr 2020 19:32:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AE22220784 for ; Wed, 15 Apr 2020 19:32:46 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="HRK2ePCr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2633816AbgDOTck (ORCPT ); Wed, 15 Apr 2020 15:32:40 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:49934 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406837AbgDOT2F (ORCPT ); Wed, 15 Apr 2020 15:28:05 -0400 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03FJPWtk012507 for ; Wed, 15 Apr 2020 12:28:04 -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-transfer-encoding : content-type; s=facebook; bh=JWAzTd+P58psYE7ONSEpWZ26DbHYU9vCEH/x2x6Kkzo=; b=HRK2ePCrQv6IA7TEeX8HI7GEN6x85FNDlOg5fsIR0qtjrOFUVTTWiNwwHmceerb4OfyU S8xYIcWuPxcPekZu4YdtehIf3dxUCIf1BFHOGuqKD8aSo/746SSBcvZmSlKkXif+K94U cZ8F6nCF5j1eTW1TqdkiU77AQzVeO/uVZY0= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 30dn82qtc1-8 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:04 -0700 Received: from intmgw004.08.frc2.facebook.com (2620:10d:c085:208::11) by mail.thefacebook.com (2620:10d:c085:11d::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:27:49 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id F00173700AF5; Wed, 15 Apr 2020 12:27:46 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 06/17] bpf: add PTR_TO_BTF_ID_OR_NULL support Date: Wed, 15 Apr 2020 12:27:46 -0700 Message-ID: <20200415192746.4083161-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 clxscore=1015 impostorscore=0 phishscore=0 bulkscore=0 suspectscore=0 spamscore=0 mlxlogscore=962 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add bpf_reg_type PTR_TO_BTF_ID_OR_NULL support. For tracing/dump program, the bpf program context definition, e.g., for ipv6_route target, looks like struct bpfdump__ipv6_route { struct bpf_dump_meta *meta; struct fib6_info *rt; }; The kernel guarantees that meta is not NULL, but rt maybe NULL. The NULL rt indicates the data structure traversal has done. So bpf program can take proper action. Add btf_id_or_null_non0_off to prog->aux structure, to indicate that for tracing programs, if the context access offset is not 0, set to PTR_TO_BTF_ID_OR_NULL instead of PTR_TO_BTF_ID. This bit is set for tracing/dump program. --- include/linux/bpf.h | 2 ++ kernel/bpf/btf.c | 5 ++++- kernel/bpf/dump.c | 1 + kernel/bpf/verifier.c | 18 +++++++++++++----- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 3cc16991c287..1179ca3d0230 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -320,6 +320,7 @@ enum bpf_reg_type { PTR_TO_TP_BUFFER, /* reg points to a writable raw tp's buffer */ PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */ PTR_TO_BTF_ID, /* reg points to kernel struct */ + PTR_TO_BTF_ID_OR_NULL, /* reg points to kernel struct or NULL */ }; /* The information passed from prog-specific *_is_valid_access @@ -658,6 +659,7 @@ struct bpf_prog_aux { bool offload_requested; bool attach_btf_trace; /* true if attaching to BTF-enabled raw tp */ bool func_proto_unreliable; + bool btf_id_or_null_non0_off; enum bpf_tramp_prog_type trampoline_prog_type; struct bpf_trampoline *trampoline; struct hlist_node tramp_hlist; diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index d65c6912bdaf..2c098e6b1acc 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -3788,7 +3788,10 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, return true; /* this is a pointer to another type */ - info->reg_type = PTR_TO_BTF_ID; + if (off != 0 && prog->aux->btf_id_or_null_non0_off) + info->reg_type = PTR_TO_BTF_ID_OR_NULL; + else + info->reg_type = PTR_TO_BTF_ID; if (tgt_prog) { ret = btf_translate_to_vmlinux(log, btf, t, tgt_prog->type, arg); diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index f39b82430977..c6d4d64aaa8e 100644 --- a/kernel/bpf/dump.c +++ b/kernel/bpf/dump.c @@ -244,6 +244,7 @@ int bpf_dump_set_target_info(u32 target_fd, struct bpf_prog *prog) prog->aux->dump_target = tinfo->target; prog->aux->attach_btf_id = btf_id; + prog->aux->btf_id_or_null_non0_off = true; done: fdput(tfd); diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index f531cee24fc5..af711dd15e08 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -382,7 +382,8 @@ static bool reg_type_may_be_null(enum bpf_reg_type type) return type == PTR_TO_MAP_VALUE_OR_NULL || type == PTR_TO_SOCKET_OR_NULL || type == PTR_TO_SOCK_COMMON_OR_NULL || - type == PTR_TO_TCP_SOCK_OR_NULL; + type == PTR_TO_TCP_SOCK_OR_NULL || + type == PTR_TO_BTF_ID_OR_NULL; } static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) @@ -396,7 +397,8 @@ static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type) return type == PTR_TO_SOCKET || type == PTR_TO_SOCKET_OR_NULL || type == PTR_TO_TCP_SOCK || - type == PTR_TO_TCP_SOCK_OR_NULL; + type == PTR_TO_TCP_SOCK_OR_NULL || + type == PTR_TO_BTF_ID_OR_NULL; } static bool arg_type_may_be_refcounted(enum bpf_arg_type type) @@ -448,6 +450,7 @@ static const char * const reg_type_str[] = { [PTR_TO_TP_BUFFER] = "tp_buffer", [PTR_TO_XDP_SOCK] = "xdp_sock", [PTR_TO_BTF_ID] = "ptr_", + [PTR_TO_BTF_ID_OR_NULL] = "null_or_ptr_", }; static char slot_type_char[] = { @@ -508,7 +511,7 @@ static void print_verifier_state(struct bpf_verifier_env *env, /* reg->off should be 0 for SCALAR_VALUE */ verbose(env, "%lld", reg->var_off.value + reg->off); } else { - if (t == PTR_TO_BTF_ID) + if (t == PTR_TO_BTF_ID || t == PTR_TO_BTF_ID_OR_NULL) verbose(env, "%s", kernel_type_name(reg->btf_id)); verbose(env, "(id=%d", reg->id); if (reg_type_may_be_refcounted_or_null(t)) @@ -2102,6 +2105,7 @@ static bool is_spillable_regtype(enum bpf_reg_type type) case PTR_TO_TCP_SOCK_OR_NULL: case PTR_TO_XDP_SOCK: case PTR_TO_BTF_ID: + case PTR_TO_BTF_ID_OR_NULL: return true; default: return false; @@ -2603,7 +2607,7 @@ static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, */ *reg_type = info.reg_type; - if (*reg_type == PTR_TO_BTF_ID) + if (*reg_type == PTR_TO_BTF_ID || *reg_type == PTR_TO_BTF_ID_OR_NULL) *btf_id = info.btf_id; else env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size; @@ -3196,7 +3200,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn * a sub-register. */ regs[value_regno].subreg_def = DEF_NOT_SUBREG; - if (reg_type == PTR_TO_BTF_ID) + if (reg_type == PTR_TO_BTF_ID || + reg_type == PTR_TO_BTF_ID_OR_NULL) regs[value_regno].btf_id = btf_id; } regs[value_regno].type = reg_type; @@ -6521,6 +6526,8 @@ static void mark_ptr_or_null_reg(struct bpf_func_state *state, reg->type = PTR_TO_SOCK_COMMON; } else if (reg->type == PTR_TO_TCP_SOCK_OR_NULL) { reg->type = PTR_TO_TCP_SOCK; + } else if (reg->type == PTR_TO_BTF_ID_OR_NULL) { + reg->type = PTR_TO_BTF_ID; } if (is_null) { /* We don't need id and ref_obj_id from this point @@ -8374,6 +8381,7 @@ static bool reg_type_mismatch_ok(enum bpf_reg_type type) case PTR_TO_TCP_SOCK_OR_NULL: case PTR_TO_XDP_SOCK: case PTR_TO_BTF_ID: + case PTR_TO_BTF_ID_OR_NULL: return false; default: return true; From patchwork Wed Apr 15 19:27:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221144 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E182C2BA19 for ; Wed, 15 Apr 2020 19:29:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0862920774 for ; Wed, 15 Apr 2020 19:29:48 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="I59Yp5ur" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2437569AbgDOT3p (ORCPT ); Wed, 15 Apr 2020 15:29:45 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:30016 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2411824AbgDOT23 (ORCPT ); Wed, 15 Apr 2020 15:28:29 -0400 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03FJSNVA024724 for ; Wed, 15 Apr 2020 12:28:27 -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-transfer-encoding : content-type; s=facebook; bh=gnrWsuQzGwdz6NH/Zp1T0ov1gMBeNN41luPHdjqNYYo=; b=I59Yp5urd+dUUkHs7QAYP8ZKspkrXSIttcpQMVlWMMNIO7V06TBmb+fin2cBQUwzPplw TvK3E7uAwC/Bd9DBb7SKwJVRtJXg2lsT8uQoqlCwmXwXxgRtnI79mqhjDP+l+iacXo08 LD8oOZjNdwpvzOCLMipRkkZye0Fs6S29utY= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 30dn7gqkrj-8 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:27 -0700 Received: from intmgw003.03.ash8.facebook.com (2620:10d:c085:208::f) by mail.thefacebook.com (2620:10d:c085:11d::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:28:01 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 351353700AF5; Wed, 15 Apr 2020 12:27:48 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 07/17] bpf: add netlink and ipv6_route targets Date: Wed, 15 Apr 2020 12:27:48 -0700 Message-ID: <20200415192748.4083243-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 bulkscore=0 phishscore=0 adultscore=0 spamscore=0 mlxscore=0 mlxlogscore=937 lowpriorityscore=0 suspectscore=0 clxscore=1015 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch added netlink and ipv6_route targets, using the same seq_ops (except show()) for /proc/net/{netlink,ipv6_route}. Since module is not supported for now, ipv6_route is supported only if the IPV6 is built-in, i.e., not compiled as a module. The restriction can be lifted once module is properly supported for bpfdump. Signed-off-by: Yonghong Song --- include/linux/bpf.h | 8 +++- kernel/bpf/dump.c | 13 ++++++ net/ipv6/ip6_fib.c | 71 +++++++++++++++++++++++++++++- net/ipv6/route.c | 29 +++++++++++++ net/netlink/af_netlink.c | 94 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 210 insertions(+), 5 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 1179ca3d0230..401e5bf921a2 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1124,6 +1124,12 @@ struct bpf_dump_reg { u32 target_feature; }; +struct bpf_dump_meta { + struct seq_file *seq; + u64 session_id; + u64 seq_num; +}; + int bpf_dump_reg_target(struct bpf_dump_reg *reg_info); int bpf_dump_set_target_info(u32 target_fd, struct bpf_prog *prog); int bpf_fd_dump_create(u32 prog_fd, const char __user *dumper_name, @@ -1131,7 +1137,7 @@ int bpf_fd_dump_create(u32 prog_fd, const char __user *dumper_name, int bpf_prog_dump_create(struct bpf_prog *prog); struct bpf_prog *bpf_dump_get_prog(struct seq_file *seq, u32 priv_data_size, u64 *session_id, u64 *seq_num, bool is_last); - +int bpf_dump_run_prog(struct bpf_prog *prog, void *ctx); int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value); int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value); int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value, diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index c6d4d64aaa8e..789b35772a81 100644 --- a/kernel/bpf/dump.c +++ b/kernel/bpf/dump.c @@ -487,6 +487,19 @@ struct bpf_prog *bpf_dump_get_prog(struct seq_file *seq, u32 priv_data_size, return extra_data->prog; } +int bpf_dump_run_prog(struct bpf_prog *prog, void *ctx) +{ + int ret; + + migrate_disable(); + rcu_read_lock(); + ret = BPF_PROG_RUN(prog, ctx); + rcu_read_unlock(); + migrate_enable(); + + return ret; +} + int bpf_dump_reg_target(struct bpf_dump_reg *reg_info) { struct bpfdump_target_info *tinfo, *ptinfo; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 46ed56719476..f5a48511d233 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -2467,7 +2467,7 @@ void fib6_gc_cleanup(void) } #ifdef CONFIG_PROC_FS -static int ipv6_route_seq_show(struct seq_file *seq, void *v) +static int ipv6_route_native_seq_show(struct seq_file *seq, void *v) { struct fib6_info *rt = v; struct ipv6_route_iter *iter = seq->private; @@ -2625,7 +2625,7 @@ static bool ipv6_route_iter_active(struct ipv6_route_iter *iter) return w->node && !(w->state == FWS_U && w->node == w->root); } -static void ipv6_route_seq_stop(struct seq_file *seq, void *v) +static void ipv6_route_native_seq_stop(struct seq_file *seq, void *v) __releases(RCU_BH) { struct net *net = seq_file_net(seq); @@ -2637,6 +2637,73 @@ static void ipv6_route_seq_stop(struct seq_file *seq, void *v) rcu_read_unlock_bh(); } +#if IS_BUILTIN(CONFIG_IPV6) && defined(CONFIG_BPF_SYSCALL) +struct bpfdump__ipv6_route { + struct bpf_dump_meta *meta; + struct fib6_info *rt; +}; + +static int ipv6_route_prog_seq_show(struct bpf_prog *prog, struct seq_file *seq, + u64 session_id, u64 seq_num, void *v) +{ + struct bpfdump__ipv6_route ctx; + struct bpf_dump_meta meta; + int ret; + + meta.seq = seq; + meta.session_id = session_id; + meta.seq_num = seq_num; + ctx.meta = &meta; + ctx.rt = v; + ret = bpf_dump_run_prog(prog, &ctx); + return ret == 0 ? 0 : -EINVAL; +} + +static int ipv6_route_seq_show(struct seq_file *seq, void *v) +{ + struct ipv6_route_iter *iter = seq->private; + u64 session_id, seq_num; + struct bpf_prog *prog; + int ret; + + prog = bpf_dump_get_prog(seq, sizeof(struct ipv6_route_iter), + &session_id, &seq_num, false); + if (!prog) + return ipv6_route_native_seq_show(seq, v); + + ret = ipv6_route_prog_seq_show(prog, seq, session_id, seq_num, v); + iter->w.leaf = NULL; + + return ret; +} + +static void ipv6_route_seq_stop(struct seq_file *seq, void *v) +{ + u64 session_id, seq_num; + struct bpf_prog *prog; + + if (!v) { + prog = bpf_dump_get_prog(seq, sizeof(struct ipv6_route_iter), + &session_id, &seq_num, true); + if (prog) + ipv6_route_prog_seq_show(prog, seq, session_id, + seq_num, v); + } + + ipv6_route_native_seq_stop(seq, v); +} +#else +static int ipv6_route_seq_show(struct seq_file *seq, void *v) +{ + return ipv6_route_native_seq_show(seq, v); +} + +static void ipv6_route_seq_stop(struct seq_file *seq, void *v) +{ + ipv6_route_native_seq_stop(seq, v); +} +#endif + const struct seq_operations ipv6_route_seq_ops = { .start = ipv6_route_seq_start, .next = ipv6_route_seq_next, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 310cbddaa533..ea87d3f2c363 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -6390,10 +6390,31 @@ void __init ip6_route_init_special_entries(void) #endif } +#if IS_BUILTIN(CONFIG_IPV6) +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) +int __init __bpfdump__ipv6_route(struct bpf_dump_meta *meta, struct fib6_info *rt) +{ + return 0; +} +#endif +#endif + int __init ip6_route_init(void) { int ret; int cpu; +#if IS_BUILTIN(CONFIG_IPV6) +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) + struct bpf_dump_reg reg_info = { + .target = "ipv6_route", + .target_proto = "__bpfdump__ipv6_route", + .prog_ctx_type_name = "bpfdump__ipv6_route", + .seq_ops = &ipv6_route_seq_ops, + .seq_priv_size = sizeof(struct ipv6_route_iter), + .target_feature = BPF_DUMP_SEQ_NET_PRIVATE, + }; +#endif +#endif ret = -ENOMEM; ip6_dst_ops_template.kmem_cachep = @@ -6452,6 +6473,14 @@ int __init ip6_route_init(void) if (ret) goto out_register_late_subsys; +#if IS_BUILTIN(CONFIG_IPV6) +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) + ret = bpf_dump_reg_target(®_info); + if (ret) + goto out_register_late_subsys; +#endif +#endif + for_each_possible_cpu(cpu) { struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu); diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 5ded01ca8b20..fe9a10642c39 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2596,7 +2596,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) return __netlink_seq_next(seq); } -static void netlink_seq_stop(struct seq_file *seq, void *v) +static void netlink_native_seq_stop(struct seq_file *seq, void *v) { struct nl_seq_iter *iter = seq->private; @@ -2607,7 +2607,7 @@ static void netlink_seq_stop(struct seq_file *seq, void *v) } -static int netlink_seq_show(struct seq_file *seq, void *v) +static int netlink_native_seq_show(struct seq_file *seq, void *v) { if (v == SEQ_START_TOKEN) { seq_puts(seq, @@ -2634,6 +2634,80 @@ static int netlink_seq_show(struct seq_file *seq, void *v) return 0; } +#ifdef CONFIG_BPF_SYSCALL +struct bpfdump__netlink { + struct bpf_dump_meta *meta; + struct netlink_sock *sk; +}; + +int __init __bpfdump__netlink(struct bpf_dump_meta *meta, struct netlink_sock *sk) +{ + return 0; +} + +static int netlink_prog_seq_show(struct bpf_prog *prog, struct seq_file *seq, + u64 session_id, u64 seq_num, void *v) +{ + struct bpfdump__netlink ctx; + struct bpf_dump_meta meta; + int ret = 0; + + meta.seq = seq; + meta.session_id = session_id; + meta.seq_num = seq_num; + ctx.meta = &meta; + ctx.sk = nlk_sk((struct sock *)v); + ret = bpf_dump_run_prog(prog, &ctx); + + return ret == 0 ? 0 : -EINVAL; +} + +static int netlink_seq_show(struct seq_file *seq, void *v) +{ + u64 session_id, seq_num; + struct bpf_prog *prog; + + prog = bpf_dump_get_prog(seq, sizeof(struct nl_seq_iter), + &session_id, &seq_num, false); + if (!prog) + return netlink_native_seq_show(seq, v); + + if (v == SEQ_START_TOKEN) + return 0; + + return netlink_prog_seq_show(prog, seq, session_id, + seq_num - 1, v); +} + +static void netlink_seq_stop(struct seq_file *seq, void *v) +{ + u64 session_id, seq_num; + struct bpf_prog *prog; + + if (!v) { + prog = bpf_dump_get_prog(seq, sizeof(struct nl_seq_iter), + &session_id, &seq_num, true); + if (prog) { + if (seq_num) + seq_num = seq_num - 1; + netlink_prog_seq_show(prog, seq, session_id, + seq_num, v); + } + } + + netlink_native_seq_stop(seq, v); +} +#else +static int netlink_seq_show(struct seq_file *seq, void *v) +{ + return netlink_native_seq_show(seq, v); +} +static void netlink_seq_stop(struct seq_file *seq, void *v) +{ + netlink_native_seq_stop(seq, v); +} +#endif + static const struct seq_operations netlink_seq_ops = { .start = netlink_seq_start, .next = netlink_seq_next, @@ -2744,6 +2818,16 @@ static int __init netlink_proto_init(void) { int i; int err = proto_register(&netlink_proto, 0); +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) + struct bpf_dump_reg reg_info = { + .target = "netlink", + .target_proto = "__bpfdump__netlink", + .prog_ctx_type_name = "bpfdump_netlink", + .seq_ops = &netlink_seq_ops, + .seq_priv_size = sizeof(struct nl_seq_iter), + .target_feature = BPF_DUMP_SEQ_NET_PRIVATE, + }; +#endif if (err != 0) goto out; @@ -2764,6 +2848,12 @@ static int __init netlink_proto_init(void) } } +#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS) + err = bpf_dump_reg_target(®_info); + if (err) + goto out; +#endif + netlink_add_usersock_entry(); sock_register(&netlink_family_ops); From patchwork Wed Apr 15 19:27:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221147 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04D35C2BA19 for ; Wed, 15 Apr 2020 19:28:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D47E1206F9 for ; Wed, 15 Apr 2020 19:28:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="qS8AqqA4" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2407114AbgDOT2k (ORCPT ); Wed, 15 Apr 2020 15:28:40 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:29642 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406898AbgDOT2G (ORCPT ); Wed, 15 Apr 2020 15:28:06 -0400 Received: from pps.filterd (m0044010.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03FJPWtt012507 for ; Wed, 15 Apr 2020 12:28:06 -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-transfer-encoding : content-type; s=facebook; bh=Bp1JvAoneQFgmc/ToLghy03QvBN5qs0mDU8YKzOglBY=; b=qS8AqqA4x2KzflYge7Puz3EY/7rJozAgERnYEmCZKXaRqVe+Lb5F5EjtZzklk9oLFzvG gIylMoxLzJ9zFm0o9cUW/rnApWAmaQqYzATnnrN6+Wpu+TrsRlZFMQaXZFWguG1jambj lKDvP5aB1oNjNaB0ybizq+/bkE+AUgcAupY= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 30dn82qtc1-17 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:06 -0700 Received: from intmgw004.03.ash8.facebook.com (2620:10d:c085:108::8) by mail.thefacebook.com (2620:10d:c085:11d::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:27:55 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 276A73700AF5; Wed, 15 Apr 2020 12:27:53 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 11/17] bpf: support variable length array in tracing programs Date: Wed, 15 Apr 2020 12:27:53 -0700 Message-ID: <20200415192753.4083637-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 mlxscore=0 lowpriorityscore=0 adultscore=0 clxscore=1015 impostorscore=0 phishscore=0 bulkscore=0 suspectscore=0 spamscore=0 mlxlogscore=736 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In /proc/net/ipv6_route, we have struct fib6_info { struct fib6_table *fib6_table; ... struct fib6_nh fib6_nh[0]; } struct fib6_nh { struct fib_nh_common nh_common; struct rt6_info **rt6i_pcpu; struct rt6_exception_bucket *rt6i_exception_bucket; }; struct fib_nh_common { ... u8 nhc_gw_family; ... } The access: struct fib6_nh *fib6_nh = &rt->fib6_nh; ... fib6_nh->nh_common.nhc_gw_family ... This patch ensures such an access is handled properly. Signed-off-by: Yonghong Song --- kernel/bpf/btf.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 2c098e6b1acc..dcee5ca0d501 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -3840,6 +3840,31 @@ int btf_struct_access(struct bpf_verifier_log *log, } if (off + size > t->size) { + /* If the last element is a variable size array, we may + * need to relax the rule. + */ + struct btf_array *array_elem; + u32 vlen = btf_type_vlen(t); + u32 last_member_type; + + member = btf_type_member(t); + last_member_type = member[vlen - 1].type; + mtype = btf_type_by_id(btf_vmlinux, last_member_type); + if (!btf_type_is_array(mtype)) + goto error; + + array_elem = (struct btf_array *)(mtype + 1); + if (array_elem->nelems != 0) + goto error; + + elem_type = btf_type_by_id(btf_vmlinux, array_elem->type); + if (!btf_type_is_struct(elem_type)) + goto error; + + off = (off - t->size) % elem_type->size; + return btf_struct_access(log, elem_type, off, size, atype, next_btf_id); + +error: bpf_log(log, "access beyond struct %s at off %u size %u\n", tname, off, size); return -EACCES; From patchwork Wed Apr 15 19:27:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221142 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 58993C3815B for ; Wed, 15 Apr 2020 19:32:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3410B20784 for ; Wed, 15 Apr 2020 19:32:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="IepUGivx" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2411897AbgDOTah (ORCPT ); Wed, 15 Apr 2020 15:30:37 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:37252 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2411817AbgDOT2X (ORCPT ); Wed, 15 Apr 2020 15:28:23 -0400 Received: from pps.filterd (m0001303.ppops.net [127.0.0.1]) by m0001303.ppops.net (8.16.0.42/8.16.0.42) with SMTP id 03FJSC9S007588 for ; Wed, 15 Apr 2020 12:28:20 -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-transfer-encoding : content-type; s=facebook; bh=yd6omChVWlKDAQ+4CsV2D1kT8tOgiYp8DJQFULum+mo=; b=IepUGivxnqarnUXSBc7KbX2nThQ1NC5XkZgb0MchcVSWvpJ6xiXHZZ0pi9HVH5Ub9nAP X7R7LuQF+Z6tLZLORpnY/es6mONDmnr3m8IxMv3ANwkFRWfgDshrSzjU+o3drOov85+o gaBG62Dt+3B8mPj3G06N1Y496SX1qA+6QBA= Received: from mail.thefacebook.com ([163.114.132.120]) by m0001303.ppops.net with ESMTP id 30dn7fymmh-14 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:20 -0700 Received: from intmgw001.03.ash8.facebook.com (2620:10d:c085:108::4) by mail.thefacebook.com (2620:10d:c085:21d::4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:28:06 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 607433700AF5; Wed, 15 Apr 2020 12:27:54 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 12/17] bpf: implement query for target_proto and file dumper prog_id Date: Wed, 15 Apr 2020 12:27:54 -0700 Message-ID: <20200415192754.4083756-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 lowpriorityscore=0 suspectscore=4 phishscore=0 mlxscore=0 spamscore=0 adultscore=0 impostorscore=0 mlxlogscore=999 priorityscore=1501 bulkscore=0 malwarescore=0 clxscore=1015 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Given a fd representing a bpfdump target, user can retrieve the target_proto name which represents the bpf program prototype. Given a fd representing a file dumper, user can retrieve the bpf_prog id associated with that dumper. Signed-off-by: Yonghong Song --- include/linux/bpf.h | 2 + include/uapi/linux/bpf.h | 11 +++++- kernel/bpf/dump.c | 72 ++++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 2 +- tools/include/uapi/linux/bpf.h | 11 +++++- 5 files changed, 95 insertions(+), 3 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 401e5bf921a2..a1ae8509e735 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1138,6 +1138,8 @@ int bpf_prog_dump_create(struct bpf_prog *prog); struct bpf_prog *bpf_dump_get_prog(struct seq_file *seq, u32 priv_data_size, u64 *session_id, u64 *seq_num, bool is_last); int bpf_dump_run_prog(struct bpf_prog *prog, void *ctx); +int bpf_dump_query(const union bpf_attr *attr, union bpf_attr __user *uattr); + int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value); int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value); int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value, diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 75f3657d526c..856e3f8a63b8 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -533,7 +533,10 @@ union bpf_attr { }; struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */ - __u32 bpf_fd; + union { + __u32 bpf_fd; + __u32 dump_query_fd; + }; __u32 info_len; __aligned_u64 info; } info; @@ -3618,6 +3621,12 @@ struct bpf_btf_info { __u32 id; } __attribute__((aligned(8))); +struct bpf_dump_info { + __aligned_u64 prog_ctx_type_name; + __u32 type_name_buf_len; + __u32 prog_id; +} __attribute__((aligned(8))); + /* User bpf_sock_addr struct to access socket fields and sockaddr struct passed * by user and intended to be used by socket (e.g. to bind to, depends on * attach attach type). diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index 789b35772a81..643591bf5aea 100644 --- a/kernel/bpf/dump.c +++ b/kernel/bpf/dump.c @@ -93,6 +93,78 @@ static void *get_extra_priv_dptr(void *old_ptr, u32 old_size) return old_ptr + roundup(old_size, 8); } +int bpf_dump_query(const union bpf_attr *attr, union bpf_attr __user *uattr) +{ + struct bpf_dump_info __user *ubpf_dinfo; + struct bpfdump_target_info *tinfo; + struct dumper_inode_info *i_info; + struct bpf_dump_info bpf_dinfo; + const char *prog_ctx_type_name; + void * __user tname_buf; + u32 tname_len, info_len; + struct file *filp; + struct fd qfd; + int err = 0; + + qfd = fdget(attr->info.dump_query_fd); + filp = qfd.file; + if (!filp) + return -EBADF; + + if (filp->f_op != &bpf_dumper_ops && + filp->f_inode->i_op != &bpfdump_dir_iops) { + err = -EINVAL; + goto done; + } + + info_len = attr->info.info_len; + ubpf_dinfo = u64_to_user_ptr(attr->info.info); + err = bpf_check_uarg_tail_zero(ubpf_dinfo, sizeof(bpf_dinfo), + info_len); + if (err) + goto done; + info_len = min_t(u32, sizeof(bpf_dinfo), info_len); + + memset(&bpf_dinfo, 0, sizeof(bpf_dinfo)); + if (copy_from_user(&bpf_dinfo, ubpf_dinfo, info_len)) { + err = -EFAULT; + goto done; + } + + /* copy prog_id for dumpers */ + if (filp->f_op == &bpf_dumper_ops) { + i_info = filp->f_inode->i_private; + bpf_dinfo.prog_id = i_info->prog->aux->id; + tinfo = i_info->tinfo; + } else { + tinfo = filp->f_inode->i_private; + } + + prog_ctx_type_name = tinfo->prog_ctx_type_name; + + tname_len = strlen(prog_ctx_type_name) + 1; + if (bpf_dinfo.type_name_buf_len < tname_len) { + err = -ENOSPC; + goto done; + } + + /* copy prog_ctx_type_name */ + tname_buf = u64_to_user_ptr(bpf_dinfo.prog_ctx_type_name); + if (copy_to_user(tname_buf, prog_ctx_type_name, tname_len)) { + err = -EFAULT; + goto done; + } + + /* copy potentially updated bpf_dinfo and info_len */ + if (copy_to_user(ubpf_dinfo, &bpf_dinfo, info_len) || + put_user(info_len, &uattr->info.info_len)) + return -EFAULT; + +done: + fdput(qfd); + return err; +} + #ifdef CONFIG_PROC_FS static void dumper_show_fdinfo(struct seq_file *m, struct file *filp) { diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index e6a4514435c4..1cde78e53a17 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3358,7 +3358,7 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, else if (f.file->f_op == &btf_fops) err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr); else - err = -EINVAL; + err = bpf_dump_query(attr, uattr); fdput(f); return err; diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 75f3657d526c..856e3f8a63b8 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -533,7 +533,10 @@ union bpf_attr { }; struct { /* anonymous struct used by BPF_OBJ_GET_INFO_BY_FD */ - __u32 bpf_fd; + union { + __u32 bpf_fd; + __u32 dump_query_fd; + }; __u32 info_len; __aligned_u64 info; } info; @@ -3618,6 +3621,12 @@ struct bpf_btf_info { __u32 id; } __attribute__((aligned(8))); +struct bpf_dump_info { + __aligned_u64 prog_ctx_type_name; + __u32 type_name_buf_len; + __u32 prog_id; +} __attribute__((aligned(8))); + /* User bpf_sock_addr struct to access socket fields and sockaddr struct passed * by user and intended to be used by socket (e.g. to bind to, depends on * attach attach type). From patchwork Wed Apr 15 19:27:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221145 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9AD1FC3815B for ; Wed, 15 Apr 2020 19:29:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 75EA520784 for ; Wed, 15 Apr 2020 19:29:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="jYAcn1DS" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2436609AbgDOT3U (ORCPT ); Wed, 15 Apr 2020 15:29:20 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:20646 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2411842AbgDOT23 (ORCPT ); Wed, 15 Apr 2020 15:28:29 -0400 Received: from pps.filterd (m0109332.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03FJPM7p008538 for ; Wed, 15 Apr 2020 12:28: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-transfer-encoding : content-type; s=facebook; bh=yKfP/7ju0dRYFRdfnVBsgmpyxRc4+rvgre4fkivzezM=; b=jYAcn1DSA/Te2FpBsHgtLKog50HZhxOShumbcFIWqh5quOJUW1yeKrRgdG5Q9Si0+TGB 9oHC2alooBMqgkE5tAH5Ws1qtOmU/dr9hW4rT7FVm8ziiAfm+2oj1y2L8jdfTT6W40sM ZfS8Dlf4Hqul/UA4KPa2ePhV3U/i93hliTs= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 30dn7t7m78-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:26 -0700 Received: from intmgw004.03.ash8.facebook.com (2620:10d:c085:108::4) by mail.thefacebook.com (2620:10d:c085:21d::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:27:56 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 98E1C3700AF5; Wed, 15 Apr 2020 12:27:55 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 13/17] tools/libbpf: libbpf support for bpfdump Date: Wed, 15 Apr 2020 12:27:55 -0700 Message-ID: <20200415192755.4083842-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 clxscore=1015 adultscore=0 phishscore=0 malwarescore=0 impostorscore=0 mlxlogscore=999 bulkscore=0 spamscore=0 priorityscore=1501 suspectscore=2 lowpriorityscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150143 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a few libbpf APIs for bpfdump pin. Also, parse the dump program section name, retrieve the dump target path and open the path to get a fd and assignment to prog->attach_target_fd. The implementation is absolutely minimum and hacky now. Signed-off-by: Yonghong Song --- tools/lib/bpf/bpf.c | 9 +++- tools/lib/bpf/bpf.h | 1 + tools/lib/bpf/libbpf.c | 88 +++++++++++++++++++++++++++++++++++++--- tools/lib/bpf/libbpf.h | 3 ++ tools/lib/bpf/libbpf.map | 2 + 5 files changed, 95 insertions(+), 8 deletions(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 5cc1b0785d18..b23f11c53109 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -238,10 +238,15 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, if (attr.prog_type == BPF_PROG_TYPE_STRUCT_OPS || attr.prog_type == BPF_PROG_TYPE_LSM) { attr.attach_btf_id = load_attr->attach_btf_id; - } else if (attr.prog_type == BPF_PROG_TYPE_TRACING || - attr.prog_type == BPF_PROG_TYPE_EXT) { + } else if (attr.prog_type == BPF_PROG_TYPE_EXT) { attr.attach_btf_id = load_attr->attach_btf_id; attr.attach_prog_fd = load_attr->attach_prog_fd; + } else if (attr.prog_type == BPF_PROG_TYPE_TRACING) { + attr.attach_btf_id = load_attr->attach_btf_id; + if (attr.expected_attach_type == BPF_TRACE_DUMP) + attr.attach_target_fd = load_attr->attach_target_fd; + else + attr.attach_prog_fd = load_attr->attach_prog_fd; } else { attr.prog_ifindex = load_attr->prog_ifindex; attr.kern_version = load_attr->kern_version; diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 46d47afdd887..7f8d740afde9 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -81,6 +81,7 @@ struct bpf_load_program_attr { union { __u32 kern_version; __u32 attach_prog_fd; + __u32 attach_target_fd; }; union { __u32 prog_ifindex; diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index ff9174282a8c..ad7726c0c1dc 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -79,6 +79,7 @@ static struct bpf_program *bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx); static const struct btf_type * skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id); +static int fill_dumper_info(struct bpf_program *prog); static int __base_pr(enum libbpf_print_level level, const char *format, va_list args) @@ -229,6 +230,7 @@ struct bpf_program { enum bpf_attach_type expected_attach_type; __u32 attach_btf_id; __u32 attach_prog_fd; + __u32 attach_target_fd; void *func_info; __u32 func_info_rec_size; __u32 func_info_cnt; @@ -2365,8 +2367,12 @@ static inline bool libbpf_prog_needs_vmlinux_btf(struct bpf_program *prog) /* BPF_PROG_TYPE_TRACING programs which do not attach to other programs * also need vmlinux BTF */ - if (prog->type == BPF_PROG_TYPE_TRACING && !prog->attach_prog_fd) - return true; + if (prog->type == BPF_PROG_TYPE_TRACING) { + if (prog->expected_attach_type == BPF_TRACE_DUMP) + return false; + if (!prog->attach_prog_fd) + return true; + } return false; } @@ -4870,10 +4876,15 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, if (prog->type == BPF_PROG_TYPE_STRUCT_OPS || prog->type == BPF_PROG_TYPE_LSM) { load_attr.attach_btf_id = prog->attach_btf_id; - } else if (prog->type == BPF_PROG_TYPE_TRACING || - prog->type == BPF_PROG_TYPE_EXT) { + } else if (prog->type == BPF_PROG_TYPE_EXT) { load_attr.attach_prog_fd = prog->attach_prog_fd; load_attr.attach_btf_id = prog->attach_btf_id; + } else if (prog->type == BPF_PROG_TYPE_TRACING) { + load_attr.attach_btf_id = prog->attach_btf_id; + if (load_attr.expected_attach_type == BPF_TRACE_DUMP) + load_attr.attach_target_fd = prog->attach_target_fd; + else + load_attr.attach_prog_fd = prog->attach_prog_fd; } else { load_attr.kern_version = kern_version; load_attr.prog_ifindex = prog->prog_ifindex; @@ -4958,7 +4969,7 @@ int bpf_program__load(struct bpf_program *prog, char *license, __u32 kern_ver) { int err = 0, fd, i, btf_id; - if ((prog->type == BPF_PROG_TYPE_TRACING || + if (((prog->type == BPF_PROG_TYPE_TRACING && prog->expected_attach_type != BPF_TRACE_DUMP) || prog->type == BPF_PROG_TYPE_LSM || prog->type == BPF_PROG_TYPE_EXT) && !prog->attach_btf_id) { btf_id = libbpf_find_attach_btf_id(prog); @@ -5319,6 +5330,7 @@ static int bpf_object__resolve_externs(struct bpf_object *obj, int bpf_object__load_xattr(struct bpf_object_load_attr *attr) { + struct bpf_program *prog; struct bpf_object *obj; int err, i; @@ -5335,7 +5347,17 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr) obj->loaded = true; - err = bpf_object__probe_caps(obj); + err = 0; + bpf_object__for_each_program(prog, obj) { + if (prog->type == BPF_PROG_TYPE_TRACING && + prog->expected_attach_type == BPF_TRACE_DUMP) { + err = fill_dumper_info(prog); + if (err) + break; + } + } + + err = err ? : bpf_object__probe_caps(obj); err = err ? : bpf_object__resolve_externs(obj, obj->kconfig); err = err ? : bpf_object__sanitize_and_load_btf(obj); err = err ? : bpf_object__sanitize_maps(obj); @@ -6322,6 +6344,8 @@ static const struct bpf_sec_def section_defs[] = { .is_attach_btf = true, .expected_attach_type = BPF_LSM_MAC, .attach_fn = attach_lsm), + SEC_DEF("dump/", TRACING, + .expected_attach_type = BPF_TRACE_DUMP), BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP), BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT), BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN), @@ -6401,6 +6425,58 @@ static const struct bpf_sec_def *find_sec_def(const char *sec_name) return NULL; } +static int fill_dumper_info(struct bpf_program *prog) +{ + const struct bpf_sec_def *sec; + const char *dump_target; + int fd; + + sec = find_sec_def(bpf_program__title(prog, false)); + if (sec) { + dump_target = bpf_program__title(prog, false) + sec->len; + fd = open(dump_target, O_RDONLY); + if (fd < 0) + return fd; + prog->attach_target_fd = fd; + } + return 0; +} + +int bpf_dump__pin(struct bpf_program *prog, const char *dname) +{ + int len, prog_fd = bpf_program__fd(prog); + const struct bpf_sec_def *sec; + const char *dump_target; + char *name_buf; + int err; + + if (dname[0] == '/') + return bpf_obj_pin(prog_fd, dname); + + sec = find_sec_def(bpf_program__title(prog, false)); + if (!sec) + return bpf_obj_pin(prog_fd, dname); + + dump_target = bpf_program__title(prog, false) + sec->len; + len = strlen(dump_target) + strlen(dname) + 2; + name_buf = malloc(len); + if (!name_buf) + return -ENOMEM; + + strcpy(name_buf, dump_target); + strcat(name_buf, "/"); + strcat(name_buf, dname); + + err = bpf_obj_pin(prog_fd, name_buf); + free(name_buf); + return err; +} + +int bpf_dump__unpin(struct bpf_program *prog, const char *dname) +{ + return -EINVAL; +} + static char *libbpf_get_type_names(bool attach_type) { int i, len = ARRAY_SIZE(section_defs) * MAX_TYPE_NAME_SIZE; diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 44df1d3e7287..e0d31e93d21c 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -217,6 +217,9 @@ LIBBPF_API int bpf_program__pin(struct bpf_program *prog, const char *path); LIBBPF_API int bpf_program__unpin(struct bpf_program *prog, const char *path); LIBBPF_API void bpf_program__unload(struct bpf_program *prog); +LIBBPF_API int bpf_dump__pin(struct bpf_program *prog, const char *dname); +LIBBPF_API int bpf_dump__unpin(struct bpf_program *prog, const char *dname); + struct bpf_link; LIBBPF_API struct bpf_link *bpf_link__open(const char *path); diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index bb8831605b25..0beb70bfe65a 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -238,6 +238,8 @@ LIBBPF_0.0.7 { LIBBPF_0.0.8 { global: + bpf_dump__pin; + bpf_dump__unpin; bpf_link__fd; bpf_link__open; bpf_link__pin; From patchwork Wed Apr 15 19:27:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221143 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5C97EC2BA19 for ; Wed, 15 Apr 2020 19:30:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3276C20732 for ; Wed, 15 Apr 2020 19:30:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="Qh7bl8eg" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2436659AbgDOT3a (ORCPT ); Wed, 15 Apr 2020 15:29:30 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:32640 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2411864AbgDOT23 (ORCPT ); Wed, 15 Apr 2020 15:28:29 -0400 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03FJSNVB024724 for ; Wed, 15 Apr 2020 12:28:27 -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-transfer-encoding : content-type; s=facebook; bh=h6xOUe1xExobaAv34ghOQ+fX0xY5qRBwmBhSlt1y7+k=; b=Qh7bl8egwa4/is6XEP5fK1rldPNjt4kVsEfJmBQRVfT5V4/eFGk3P1arLfSD7MqZRBfd 9b66b4M1byZJtFUwZNoVbgePk555GQolQ4Z9WWdWX0EfwhOjWXUe9KhTv1BUOryjNrHi 1a01UpneHSbm+tlZzOf15kT5c/1CTl5oh7Q= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 30dn7gqkrj-9 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:27 -0700 Received: from intmgw001.03.ash8.facebook.com (2620:10d:c085:108::4) by mail.thefacebook.com (2620:10d:c085:11d::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:28:06 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id D4E853700AF5; Wed, 15 Apr 2020 12:27:56 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 14/17] tools/bpftool: add bpf dumper support Date: Wed, 15 Apr 2020 12:27:56 -0700 Message-ID: <20200415192756.4083931-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 bulkscore=0 phishscore=0 adultscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 lowpriorityscore=0 suspectscore=0 clxscore=1015 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implemented "bpftool dumper" command. Two subcommands now: bpftool dumper pin bpftool dumper show {target|dumper} The "pin" subcommand will create a dumper with under the dump target (specified in .o). The "show" subcommand will show bpf prog ctx type name , which will be useful on how to write the bpf program, and the "dumper" subcommand will further show the corresponding prog_id for each dumper. For example, with some of later selftest dumpers are pinned in the kernel, we can do inspection like below: $ bpftool dumper show target target prog_ctx_type task bpfdump__task task/file bpfdump__task_file bpf_map bpfdump__bpf_map ipv6_route bpfdump__ipv6_route netlink bpfdump__netlink $ bpftool dumper show dumper dumper prog_id prog_ctx_type task/my1 8 bpfdump__task task/file/my1 12 bpfdump__task_file bpf_map/my1 4 bpfdump__bpf_map ipv6_route/my2 16 bpfdump__ipv6_route netlink/my2 24 bpfdump__ipv6_route netlink/my3 20 bpfdump__netlink Signed-off-by: Yonghong Song --- tools/bpf/bpftool/dumper.c | 135 +++++++++++++++++++++++++++++++++++++ tools/bpf/bpftool/main.c | 3 +- tools/bpf/bpftool/main.h | 1 + 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 tools/bpf/bpftool/dumper.c diff --git a/tools/bpf/bpftool/dumper.c b/tools/bpf/bpftool/dumper.c new file mode 100644 index 000000000000..46ca9d1d9a67 --- /dev/null +++ b/tools/bpf/bpftool/dumper.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +// Copyright (C) 2020 Facebook +// Author: Yonghong Song + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "main.h" + +static int do_pin(int argc, char **argv) +{ + struct bpf_program *prog; + struct bpf_object *obj; + const char *objfile, *dname; + int err; + + if (!REQ_ARGS(2)) { + usage(); + return -1; + } + + objfile = GET_ARG(); + dname = GET_ARG(); + + obj = bpf_object__open(objfile); + if (IS_ERR_OR_NULL(obj)) + return -1; + + err = bpf_object__load(obj); + if (err < 0) + return -1; + + prog = bpf_program__next(NULL, obj); + return bpf_dump__pin(prog, dname); +} + +static bool for_targets; +static const char *bpfdump_root = "/sys/kernel/bpfdump"; + +static int check_file(const char *fpath, const struct stat *sb, + int typeflag, struct FTW *ftwbuf) +{ + char prog_ctx_cname_buf[64]; + struct bpf_dump_info info; + unsigned info_len; + const char *name; + int ret, fd; + + if ((for_targets && typeflag == FTW_F) || + (!for_targets && typeflag == FTW_D)) + return 0; + + if (for_targets && strcmp(fpath, bpfdump_root) == 0) + return 0; + + fd = open(fpath, O_RDONLY); + if (fd < 0) + return fd; + + info_len = sizeof(info); + memset(&info, 0, info_len); + info.prog_ctx_type_name = ptr_to_u64(prog_ctx_cname_buf); + info.type_name_buf_len = sizeof(prog_ctx_cname_buf); + ret = bpf_obj_get_info_by_fd(fd, &info, &info_len); + if (ret < 0) + goto done; + + name = fpath + strlen(bpfdump_root) + 1; + if (for_targets) + fprintf(stdout, "%-24s%-24s\n", name, prog_ctx_cname_buf); + else + fprintf(stdout, "%-24s%-10d%-24s\n", name, info.prog_id, + prog_ctx_cname_buf); + +done: + close(fd); + return ret; +} + +static int do_show(int argc, char **argv) +{ + int flags = FTW_PHYS; + int nopenfd = 16; + const char *spec; + + if (!REQ_ARGS(1)) { + usage(); + return -1; + } + + spec = GET_ARG(); + if (strcmp(spec, "target") == 0) { + for_targets = true; + fprintf(stdout, "target prog_ctx_type\n"); + } else if (strcmp(spec, "dumper") == 0) { + fprintf(stdout, "dumper prog_id prog_ctx_type\n"); + for_targets = false; + } else { + return -1; + } + + if (nftw(bpfdump_root, check_file, nopenfd, flags) == -1) + return -1; + + return 0; +} + +static int do_help(int argc, char **argv) +{ + return 0; +} + +static const struct cmd cmds[] = { + { "help", do_help }, + { "show", do_show }, + { "pin", do_pin }, + { 0 } +}; + +int do_dumper(int argc, char **argv) +{ + return cmd_select(cmds, argc, argv, do_help); +} diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index 466c269eabdd..8489aba6543d 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -58,7 +58,7 @@ static int do_help(int argc, char **argv) " %s batch file FILE\n" " %s version\n" "\n" - " OBJECT := { prog | map | cgroup | perf | net | feature | btf | gen | struct_ops }\n" + " OBJECT := { prog | map | cgroup | perf | net | feature | btf | gen | struct_ops | dumper}\n" " " HELP_SPEC_OPTIONS "\n" "", bin_name, bin_name, bin_name); @@ -222,6 +222,7 @@ static const struct cmd cmds[] = { { "btf", do_btf }, { "gen", do_gen }, { "struct_ops", do_struct_ops }, + { "dumper", do_dumper }, { "version", do_version }, { 0 } }; diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 86f14ce26fd7..2c59f319bbe9 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -162,6 +162,7 @@ int do_feature(int argc, char **argv); int do_btf(int argc, char **argv); int do_gen(int argc, char **argv); int do_struct_ops(int argc, char **argv); +int do_dumper(int argc, char **arg); int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what); int prog_parse_fd(int *argc, char ***argv); From patchwork Wed Apr 15 19:28:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221146 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CAA69C38A2B for ; Wed, 15 Apr 2020 19:29:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A7E85206F9 for ; Wed, 15 Apr 2020 19:29:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="OAXCYRAe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2411886AbgDOT3D (ORCPT ); Wed, 15 Apr 2020 15:29:03 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:61424 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2411869AbgDOT2c (ORCPT ); Wed, 15 Apr 2020 15:28:32 -0400 Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 03FJSMjo024691 for ; Wed, 15 Apr 2020 12:28:31 -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-transfer-encoding : content-type; s=facebook; bh=ZuHVPcaW1pLeyf56TL2TTP6NLj4DSjqUkw74KGNT07k=; b=OAXCYRAev2h5ETgqEu6ADvV0J0gQRgR4Ko837wfE1GMGnUWHMhcDZ90AEbMN/z/kiYFW 5hXqRnTTB/6YdBy8l+OREi0DLTXaPupZVYN20ouAnFOTSHAL86KTADS0ZQaXZHRQ+jtU g0smYh9rPxZnmSrT0uMr1wbIJ6L/UdhzS6Q= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 30dn7gqkqw-17 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 15 Apr 2020 12:28:31 -0700 Received: from intmgw002.08.frc2.facebook.com (2620:10d:c085:108::4) by mail.thefacebook.com (2620:10d:c085:11d::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 15 Apr 2020 12:28:02 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 8D13A3700AF5; Wed, 15 Apr 2020 12:28:00 -0700 (PDT) Smtp-Origin-Hostprefix: devbig From: Yonghong Song Smtp-Origin-Hostname: devbig003.ftw2.facebook.com To: Andrii Nakryiko , , Martin KaFai Lau , CC: Alexei Starovoitov , Daniel Borkmann , Smtp-Origin-Cluster: ftw2c04 Subject: [RFC PATCH bpf-next v2 17/17] tools/bpf: selftests: add a selftest for anonymous dumper Date: Wed, 15 Apr 2020 12:28:00 -0700 Message-ID: <20200415192800.4084266-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200415192740.4082659-1-yhs@fb.com> References: <20200415192740.4082659-1-yhs@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676 definitions=2020-04-15_07:2020-04-14,2020-04-15 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 bulkscore=0 phishscore=0 adultscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 lowpriorityscore=0 suspectscore=0 clxscore=1015 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004150144 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The selftest creates a anonymous dumper for the /sys/kernel/bpfdump/task/ target and ensure the user space got the expected contents. Both bpf_seq_printf() and bpf_seq_write() helpers are tested in this selftest. $ test_progs -n 2 #2 bpfdump_test:OK Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Yonghong Song --- .../selftests/bpf/prog_tests/bpfdump_test.c | 42 +++++++++++++++++++ .../selftests/bpf/progs/bpfdump_test_kern.c | 31 ++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/bpfdump_test.c create mode 100644 tools/testing/selftests/bpf/progs/bpfdump_test_kern.c diff --git a/tools/testing/selftests/bpf/prog_tests/bpfdump_test.c b/tools/testing/selftests/bpf/prog_tests/bpfdump_test.c new file mode 100644 index 000000000000..8978e04c3ca9 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/bpfdump_test.c @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "bpfdump_test_kern.skel.h" + +void test_bpfdump_test(void) +{ + int err, prog_fd, dumper_fd, duration = 0; + struct bpfdump_test_kern *skel; + char buf[16] = {}; + const char *expected = "0A1B2C3D"; + + skel = bpfdump_test_kern__open_and_load(); + if (CHECK(!skel, "skel_open_and_load", + "skeleton open_and_load failed\n")) + return; + + prog_fd = bpf_program__fd(skel->progs.dump_tasks); + dumper_fd = bpf_raw_tracepoint_open(NULL, prog_fd); + if (CHECK(dumper_fd < 0, "bpf_raw_tracepoint_open", + "anonymous dumper creation failed\n")) + goto destroy_skel; + + err = -EINVAL; + while (read(dumper_fd, buf, sizeof(buf)) > 0) { + if (CHECK(!err, "read", "unexpected extra read\n")) + goto close_fd; + + err = strcmp(buf, expected) != 0; + if (CHECK(err, "read", + "read failed: buf %s, expected %s\n", buf, + expected)) + goto close_fd; + } + + CHECK(err, "read", "real failed: no read, expected %s\n", + expected); + +close_fd: + close(dumper_fd); +destroy_skel: + bpfdump_test_kern__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/bpfdump_test_kern.c b/tools/testing/selftests/bpf/progs/bpfdump_test_kern.c new file mode 100644 index 000000000000..f6bd61a75a22 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bpfdump_test_kern.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Facebook */ +#include "vmlinux.h" +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +int count = 0; + +SEC("dump//sys/kernel/bpfdump/task") +int dump_tasks(struct bpfdump__task *ctx) +{ + struct seq_file *seq = ctx->meta->seq; + struct task_struct *task = ctx->task; + static char fmt[] = "%d"; + char c; + + if (task == (void *)0) + return 0; + + if (count < 4) { + bpf_seq_printf(seq, fmt, sizeof(fmt), count); + c = 'A' + count; + bpf_seq_write(seq, &c, sizeof(c)); + count++; + } + + return 0; +}