From patchwork Wed Apr 8 23:25:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221332 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.9 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, 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 2D904C2BB1D for ; Wed, 8 Apr 2020 23:25:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F1D9920857 for ; Wed, 8 Apr 2020 23:25:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="BQItS+UJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726539AbgDHXZ2 (ORCPT ); Wed, 8 Apr 2020 19:25:28 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:9076 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726521AbgDHXZ2 (ORCPT ); Wed, 8 Apr 2020 19:25:28 -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 038NNEqc032603 for ; Wed, 8 Apr 2020 16:25: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=ZbsCGaCv9Gsm85mgP5XUnKAzAoNTMbL2upv04wMKm5c=; b=BQItS+UJuaCEHJiKi1ww+dTuT4Y+A+uoAigfvcrFim0PBWvCbZhThjYrBCOFjK4lv1Sv Q3v9jG9tCJilg86WkQNR7zbACOPUG1EGHFynzTkGC3NflCBVHVlKAzT+XdpFyFAsFgkn HX4MqK8fsV78P7/4srFD3Dlf5aviJuqfblI= Received: from mail.thefacebook.com ([163.114.132.120]) by m0001303.ppops.net with ESMTP id 3091mvy6x2-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:27 -0700 Received: from intmgw001.03.ash8.facebook.com (2620:10d:c085:108::8) 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, 8 Apr 2020 16:25:25 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 8B5A33700D98; Wed, 8 Apr 2020 16:25:22 -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 02/16] bpf: create /sys/kernel/bpfdump mount file system Date: Wed, 8 Apr 2020 16:25:22 -0700 Message-ID: <20200408232522.2675492-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 priorityscore=1501 spamscore=0 mlxscore=0 suspectscore=2 clxscore=1015 bulkscore=0 phishscore=0 adultscore=0 mlxlogscore=999 lowpriorityscore=0 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080163 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 8 23:25:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221326 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.9 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, 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 5A5E6C2BB1D for ; Wed, 8 Apr 2020 23:26:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3030B2087E for ; Wed, 8 Apr 2020 23:26:01 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="ExFYxBkI" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726716AbgDHX0A (ORCPT ); Wed, 8 Apr 2020 19:26:00 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:14460 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726699AbgDHXZz (ORCPT ); Wed, 8 Apr 2020 19:25:55 -0400 Received: from pps.filterd (m0089730.ppops.net [127.0.0.1]) by m0089730.ppops.net (8.16.0.42/8.16.0.42) with SMTP id 038NPjHl019373 for ; Wed, 8 Apr 2020 16:25:55 -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=xAQDZIfES9Gj1GnCxGUljbWcEITqX2/G8lxVxqvIGH8=; b=ExFYxBkIHTRDQ0EgYxP39sZ67maaUwWXPMYab0hJN0pkL5o48+RI3nNI9Qczk/tIc9Pv TB9nYXvknKDxB+0R+NXvhwdE4R39rZ3Bu8hY+R5btDuiLNm1a3bAYORD8O4a44oQzll3 sV2/HY1p3BRYzv8f9nY5BMDhgn+5wwgGyzo= Received: from mail.thefacebook.com ([163.114.132.120]) by m0089730.ppops.net with ESMTP id 3091m37bp8-17 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:55 -0700 Received: from intmgw002.08.frc2.facebook.com (2620:10d:c085:108::8) 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, 8 Apr 2020 16:25:35 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 06ABF3700D98; Wed, 8 Apr 2020 16:25:25 -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 04/16] bpf: allow loading of a dumper program Date: Wed, 8 Apr 2020 16:25:24 -0700 Message-ID: <20200408232524.2675603-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 adultscore=0 spamscore=0 suspectscore=2 mlxscore=0 mlxlogscore=999 bulkscore=0 lowpriorityscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 clxscore=1015 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080164 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 | 1 + kernel/bpf/dump.c | 40 ++++++++++++++++++++++++++++++++++ kernel/bpf/syscall.c | 8 ++++++- kernel/bpf/verifier.c | 15 +++++++++++++ tools/include/uapi/linux/bpf.h | 1 + 6 files changed, 66 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 53914bec7590..44268d36d901 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -673,6 +673,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]; @@ -1112,6 +1113,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags); int bpf_dump_reg_target(const char *target, const char *target_proto, const struct seq_operations *seq_ops, u32 seq_priv_size, u32 target_feature); +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..0f1cbed446c1 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 }; diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index 45528846557f..1091affe8b3f 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; @@ -48,6 +51,43 @@ static const struct inode_operations bpf_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 != &bpf_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) { + prog->aux->dump_target = tinfo->target; + prog->aux->attach_btf_id = btf_id; + } + + err = min(btf_id, 0); +done: + fdput(tfd); + return err; +} + int bpf_dump_reg_target(const char *target, const char *target_proto, const struct seq_operations *seq_ops, diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 64783da34202..41005dee8957 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_prog_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..0f1cbed446c1 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 }; From patchwork Wed Apr 8 23:25:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221331 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.9 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, 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 C4A9BC2BA2B for ; Wed, 8 Apr 2020 23:25:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8678C20857 for ; Wed, 8 Apr 2020 23:25:34 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="ILlysoym" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726512AbgDHXZd (ORCPT ); Wed, 8 Apr 2020 19:25:33 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:54806 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726504AbgDHXZc (ORCPT ); Wed, 8 Apr 2020 19:25:32 -0400 Received: from pps.filterd (m0148461.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 038NJN1c028674 for ; Wed, 8 Apr 2020 16:25:30 -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=reV9zRE9CsGSG6Liq8/GjBGN0gKMKdSlI/v0Wk7iIyE=; b=ILlysoymQgmitZppLBlSeQ+RI7dXbl/SZzeizUKMFkJmuQCYtRJAo7eTzp5rlq/z065V hD0Q+jHk2FVX6eX+uXPFw74ywUV7r0OCp22ZIxlVdp3uaEaGOXH399sxNG8OvOsSUgX0 b6HLJ1rvVTgNqN6DizhjOJaMdKnGx/d3Vyo= Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com with ESMTP id 3091kwfktg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:30 -0700 Received: from intmgw005.03.ash8.facebook.com (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:82::d) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 8 Apr 2020 16:25:29 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 4212C3700D98; Wed, 8 Apr 2020 16:25:26 -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 05/16] bpf: create file or anonymous dumpers Date: Wed, 8 Apr 2020 16:25:26 -0700 Message-ID: <20200408232526.2675664-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 adultscore=0 mlxlogscore=999 mlxscore=0 clxscore=1015 priorityscore=1501 bulkscore=0 malwarescore=0 phishscore=0 spamscore=0 suspectscore=2 lowpriorityscore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080163 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Given a loaded dumper bpf program, which already knows which target it should bind to, there two ways to create a dumper: - a file based dumper under hierarchy of /sys/kernel/bpfdump/ which uses can "cat" to print out the output. - an anonymous dumper which user application can "read" the dumping output. For file based dumper, BPF_OBJ_PIN syscall interface is used. For anonymous dumper, BPF_PROG_ATTACH syscall interface is used. To facilitate target seq_ops->show() to get the bpf program easily, dumper creation increased the target-provided seq_file private data size so bpf program pointer is also stored in seq_file private data. Further, a seq_num which represents how many bpf_dump_get_prog() has been called is also available to the target seq_ops->show(). Such information can be used to e.g., print banner before printing out actual data. Note the seq_num does not represent the num of unique kernel objects the bpf program has seen. But it should be a good approximate. A target feature BPF_DUMP_SEQ_NET_PRIVATE is implemented specifically useful for net based dumpers. It sets net namespace as the current process net namespace. This avoids changing existing net seq_ops in order to retrieve net namespace from the seq_file pointer. For open dumper files, anonymous or not, the fdinfo will show the target and prog_id associated with that file descriptor. For dumper file itself, a kernel interface will be provided to retrieve the prog_id in one of the later patches. Signed-off-by: Yonghong Song --- include/linux/bpf.h | 5 + include/uapi/linux/bpf.h | 6 +- kernel/bpf/dump.c | 338 ++++++++++++++++++++++++++++++++- kernel/bpf/syscall.c | 11 +- tools/include/uapi/linux/bpf.h | 6 +- 5 files changed, 362 insertions(+), 4 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 44268d36d901..8171e01ff4be 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1110,10 +1110,15 @@ struct bpf_link *bpf_link_get_from_fd(u32 ufd); int bpf_obj_pin_user(u32 ufd, const char __user *pathname); int bpf_obj_get_user(const char __user *pathname, int flags); +#define BPF_DUMP_SEQ_NET_PRIVATE BIT(0) + int bpf_dump_reg_target(const char *target, const char *target_proto, const struct seq_operations *seq_ops, u32 seq_priv_size, u32 target_feature); int bpf_dump_set_target_info(u32 target_fd, struct bpf_prog *prog); +int bpf_dump_create(u32 prog_fd, const char __user *dumper_name); +struct bpf_prog *bpf_dump_get_prog(struct seq_file *seq, u32 priv_data_size, + u64 *seq_num); 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 0f1cbed446c1..b51d56fc77f9 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -354,6 +354,7 @@ enum { /* Flags for accessing BPF object from syscall side. */ BPF_F_RDONLY = (1U << 3), BPF_F_WRONLY = (1U << 4), + BPF_F_DUMP = (1U << 5), /* Flag for stack_map, store build_id+offset instead of pointer */ BPF_F_STACK_BUILD_ID = (1U << 5), @@ -481,7 +482,10 @@ union bpf_attr { }; struct { /* anonymous struct used by BPF_OBJ_* commands */ - __aligned_u64 pathname; + union { + __aligned_u64 pathname; + __aligned_u64 dumper_name; + }; __u32 bpf_fd; __u32 file_flags; }; diff --git a/kernel/bpf/dump.c b/kernel/bpf/dump.c index 1091affe8b3f..ac6856abb711 100644 --- a/kernel/bpf/dump.c +++ b/kernel/bpf/dump.c @@ -30,22 +30,173 @@ struct bpfdump_targets { struct mutex dumper_mutex; }; +struct dumper_inode_info { + struct bpfdump_target_info *tinfo; + struct bpf_prog *prog; +}; + +struct dumper_info { + struct list_head list; + /* file to identify an anon dumper, + * dentry to identify a file dumper. + */ + union { + struct file *file; + struct dentry *dentry; + }; + struct bpfdump_target_info *tinfo; + struct bpf_prog *prog; +}; + +struct dumpers { + struct list_head dumpers; + struct mutex dumper_mutex; +}; + +struct extra_priv_data { + struct bpf_prog *prog; + u64 seq_num; +}; + /* registered dump targets */ static struct bpfdump_targets dump_targets; static struct dentry *bpfdump_dentry; +static struct dumpers anon_dumpers, file_dumpers; + +static const struct file_operations bpf_dumper_ops; +static const struct inode_operations bpf_dir_iops; + +static struct dentry *bpfdump_add_file(const char *name, struct dentry *parent, + const struct file_operations *f_ops, + void *data); static struct dentry *bpfdump_add_dir(const char *name, struct dentry *parent, const struct inode_operations *i_ops, void *data); static int __bpfdump_init(void); +static u32 get_total_priv_dsize(u32 old_size) +{ + return roundup(old_size, 8) + sizeof(struct extra_priv_data); +} + +static void *get_extra_priv_dptr(void *old_ptr, u32 old_size) +{ + return old_ptr + roundup(old_size, 8); +} + +#ifdef CONFIG_PROC_FS +static void dumper_show_fdinfo(struct seq_file *m, struct file *filp) +{ + struct dumper_inode_info *i_info = filp->f_inode->i_private; + + seq_printf(m, "target:\t%s\n" + "prog_id:\t%u\n", + i_info->tinfo->target, + i_info->prog->aux->id); +} + +static void anon_dumper_show_fdinfo(struct seq_file *m, struct file *filp) +{ + struct dumper_info *dinfo; + + mutex_lock(&anon_dumpers.dumper_mutex); + list_for_each_entry(dinfo, &anon_dumpers.dumpers, list) { + if (dinfo->file == filp) { + seq_printf(m, "target:\t%s\n" + "prog_id:\t%u\n", + dinfo->tinfo->target, + dinfo->prog->aux->id); + break; + } + } + mutex_unlock(&anon_dumpers.dumper_mutex); +} + +#endif + +static void process_target_feature(u32 feature, void *priv_data) +{ + /* use the current net namespace */ + if (feature & BPF_DUMP_SEQ_NET_PRIVATE) + set_seq_net_private((struct seq_net_private *)priv_data, + current->nsproxy->net_ns); +} + +static int dumper_open(struct inode *inode, struct file *file) +{ + struct dumper_inode_info *i_info = inode->i_private; + struct extra_priv_data *extra_data; + u32 old_priv_size, total_priv_size; + void *priv_data; + + old_priv_size = i_info->tinfo->seq_priv_size; + total_priv_size = get_total_priv_dsize(old_priv_size); + priv_data = __seq_open_private(file, i_info->tinfo->seq_ops, + total_priv_size); + if (!priv_data) + return -ENOMEM; + + process_target_feature(i_info->tinfo->target_feature, priv_data); + + extra_data = get_extra_priv_dptr(priv_data, old_priv_size); + extra_data->prog = i_info->prog; + extra_data->seq_num = 0; + + return 0; +} + +static int anon_dumper_release(struct inode *inode, struct file *file) +{ + struct dumper_info *dinfo; + + /* release the bpf program */ + mutex_lock(&anon_dumpers.dumper_mutex); + list_for_each_entry(dinfo, &anon_dumpers.dumpers, list) { + if (dinfo->file == file) { + bpf_prog_put(dinfo->prog); + list_del(&dinfo->list); + break; + } + } + mutex_unlock(&anon_dumpers.dumper_mutex); + + return seq_release_private(inode, file); +} + +static int dumper_release(struct inode *inode, struct file *file) +{ + return seq_release_private(inode, file); +} + static int dumper_unlink(struct inode *dir, struct dentry *dentry) { - kfree(d_inode(dentry)->i_private); + struct dumper_inode_info *i_info = d_inode(dentry)->i_private; + + bpf_prog_put(i_info->prog); + kfree(i_info); + return simple_unlink(dir, dentry); } +static const struct file_operations bpf_dumper_ops = { +#ifdef CONFIG_PROC_FS + .show_fdinfo = dumper_show_fdinfo, +#endif + .open = dumper_open, + .read = seq_read, + .release = dumper_release, +}; + +static const struct file_operations anon_bpf_dumper_ops = { +#ifdef CONFIG_PROC_FS + .show_fdinfo = anon_dumper_show_fdinfo, +#endif + .read = seq_read, + .release = anon_dumper_release, +}; + static const struct inode_operations bpf_dir_iops = { .lookup = simple_lookup, .unlink = dumper_unlink, @@ -88,6 +239,179 @@ int bpf_dump_set_target_info(u32 target_fd, struct bpf_prog *prog) return err; } +static int create_anon_dumper(struct bpfdump_target_info *tinfo, + struct bpf_prog *prog) +{ + struct extra_priv_data *extra_data; + u32 old_priv_size, total_priv_size; + struct dumper_info *dinfo; + struct file *file; + int err, anon_fd; + void *priv_data; + struct fd fd; + + anon_fd = anon_inode_getfd("bpf-dumper", &anon_bpf_dumper_ops, + NULL, O_CLOEXEC); + if (anon_fd < 0) + return anon_fd; + + /* setup seq_file for anon dumper */ + fd = fdget(anon_fd); + file = fd.file; + + dinfo = kmalloc(sizeof(*dinfo), GFP_KERNEL); + if (!dinfo) { + err = -ENOMEM; + goto free_fd; + } + + old_priv_size = tinfo->seq_priv_size; + total_priv_size = get_total_priv_dsize(old_priv_size); + + priv_data = __seq_open_private(file, tinfo->seq_ops, + total_priv_size); + if (!priv_data) { + err = -ENOMEM; + goto free_dinfo; + } + + dinfo->file = file; + dinfo->tinfo = tinfo; + dinfo->prog = prog; + + mutex_lock(&anon_dumpers.dumper_mutex); + list_add(&dinfo->list, &anon_dumpers.dumpers); + mutex_unlock(&anon_dumpers.dumper_mutex); + + process_target_feature(tinfo->target_feature, priv_data); + + extra_data = get_extra_priv_dptr(priv_data, old_priv_size); + extra_data->prog = prog; + extra_data->seq_num = 0; + + fdput(fd); + return anon_fd; + +free_dinfo: + kfree(dinfo); +free_fd: + fdput(fd); + return err; +} + +static int create_dumper(struct bpfdump_target_info *tinfo, + const char __user *dumper_name, + struct bpf_prog *prog) +{ + struct dumper_inode_info *i_info; + struct dumper_info *dinfo; + struct dentry *dentry; + const char *dname; + int err = 0; + + i_info = kmalloc(sizeof(*i_info), GFP_KERNEL); + if (!i_info) + return -ENOMEM; + + i_info->tinfo = tinfo; + i_info->prog = prog; + + dinfo = kmalloc(sizeof(*dinfo), GFP_KERNEL); + if (!dinfo) { + err = -ENOMEM; + goto free_i_info; + } + + dname = strndup_user(dumper_name, PATH_MAX); + if (!dname) { + err = -ENOMEM; + goto free_dinfo; + } + + dentry = bpfdump_add_file(dname, tinfo->dir_dentry, + &bpf_dumper_ops, i_info); + kfree(dname); + if (IS_ERR(dentry)) { + err = PTR_ERR(dentry); + goto free_dinfo; + } + + dinfo->dentry = dentry; + dinfo->tinfo = tinfo; + dinfo->prog = prog; + + mutex_lock(&file_dumpers.dumper_mutex); + list_add(&dinfo->list, &file_dumpers.dumpers); + mutex_unlock(&file_dumpers.dumper_mutex); + + return 0; + +free_dinfo: + kfree(dinfo); +free_i_info: + kfree(i_info); + return err; +} + +int bpf_dump_create(u32 prog_fd, const char __user *dumper_name) +{ + struct bpfdump_target_info *tinfo; + const char *target; + struct bpf_prog *prog; + bool existed = false; + int err = 0; + + prog = bpf_prog_get(prog_fd); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + target = prog->aux->dump_target; + if (!target) { + err = -EINVAL; + goto free_prog; + } + + mutex_lock(&dump_targets.dumper_mutex); + list_for_each_entry(tinfo, &dump_targets.dumpers, list) { + if (strcmp(tinfo->target, target) == 0) { + existed = true; + break; + } + } + mutex_unlock(&dump_targets.dumper_mutex); + + if (!existed) { + err = -EINVAL; + goto free_prog; + } + + err = dumper_name ? create_dumper(tinfo, dumper_name, prog) + : create_anon_dumper(tinfo, prog); + if (err < 0) + goto free_prog; + + return err; + +free_prog: + bpf_prog_put(prog); + return err; +} + +struct bpf_prog *bpf_dump_get_prog(struct seq_file *seq, u32 priv_data_size, + u64 *seq_num) +{ + struct extra_priv_data *extra_data; + + if (seq->file->f_op != &bpf_dumper_ops && + seq->file->f_op != &anon_bpf_dumper_ops) + return NULL; + + extra_data = get_extra_priv_dptr(seq->private, priv_data_size); + *seq_num = extra_data->seq_num++; + + return extra_data->prog; +} + int bpf_dump_reg_target(const char *target, const char *target_proto, const struct seq_operations *seq_ops, @@ -211,6 +535,14 @@ bpfdump_create_dentry(const char *name, umode_t mode, struct dentry *parent, return dentry; } +static struct dentry * +bpfdump_add_file(const char *name, struct dentry *parent, + const struct file_operations *f_ops, void *data) +{ + return bpfdump_create_dentry(name, S_IFREG | 0444, parent, + data, NULL, f_ops); +} + static struct dentry * bpfdump_add_dir(const char *name, struct dentry *parent, const struct inode_operations *i_ops, void *data) @@ -290,6 +622,10 @@ static int __bpfdump_init(void) INIT_LIST_HEAD(&dump_targets.dumpers); mutex_init(&dump_targets.dumper_mutex); + INIT_LIST_HEAD(&anon_dumpers.dumpers); + mutex_init(&anon_dumpers.dumper_mutex); + INIT_LIST_HEAD(&file_dumpers.dumpers); + mutex_init(&file_dumpers.dumper_mutex); return 0; remove_mount: diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 41005dee8957..b5e4f18cc633 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2173,9 +2173,13 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) static int bpf_obj_pin(const union bpf_attr *attr) { - if (CHECK_ATTR(BPF_OBJ) || attr->file_flags != 0) + if (CHECK_ATTR(BPF_OBJ) || attr->file_flags & ~BPF_F_DUMP) return -EINVAL; + if (attr->file_flags == BPF_F_DUMP) + return bpf_dump_create(attr->bpf_fd, + u64_to_user_ptr(attr->dumper_name)); + return bpf_obj_pin_user(attr->bpf_fd, u64_to_user_ptr(attr->pathname)); } @@ -2605,6 +2609,8 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type) case BPF_CGROUP_GETSOCKOPT: case BPF_CGROUP_SETSOCKOPT: return BPF_PROG_TYPE_CGROUP_SOCKOPT; + case BPF_TRACE_DUMP: + return BPF_PROG_TYPE_TRACING; default: return BPF_PROG_TYPE_UNSPEC; } @@ -2663,6 +2669,9 @@ static int bpf_prog_attach(const union bpf_attr *attr) case BPF_PROG_TYPE_SOCK_OPS: ret = cgroup_bpf_prog_attach(attr, ptype, prog); break; + case BPF_PROG_TYPE_TRACING: + ret = bpf_dump_create(attr->attach_bpf_fd, (void __user *)NULL); + break; default: ret = -EINVAL; } diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 0f1cbed446c1..b51d56fc77f9 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -354,6 +354,7 @@ enum { /* Flags for accessing BPF object from syscall side. */ BPF_F_RDONLY = (1U << 3), BPF_F_WRONLY = (1U << 4), + BPF_F_DUMP = (1U << 5), /* Flag for stack_map, store build_id+offset instead of pointer */ BPF_F_STACK_BUILD_ID = (1U << 5), @@ -481,7 +482,10 @@ union bpf_attr { }; struct { /* anonymous struct used by BPF_OBJ_* commands */ - __aligned_u64 pathname; + union { + __aligned_u64 pathname; + __aligned_u64 dumper_name; + }; __u32 bpf_fd; __u32 file_flags; }; From patchwork Wed Apr 8 23:25:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221330 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.9 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, 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 82696C2BB54 for ; Wed, 8 Apr 2020 23:25:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 59A3020857 for ; Wed, 8 Apr 2020 23:25:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="FfACUAxl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726597AbgDHXZg (ORCPT ); Wed, 8 Apr 2020 19:25:36 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:43278 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726504AbgDHXZe (ORCPT ); Wed, 8 Apr 2020 19:25:34 -0400 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 038NODYC025755 for ; Wed, 8 Apr 2020 16:25:33 -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=bMHph6GvtAI2lVXYP7KfFodEFgqg55TiGWyhtZe5jOE=; b=FfACUAxloiUjYyqqM9zx9WOuPi9RrP2+twj1fjzPBw3F8nFam3bXD60YbrytoihtL24F ExX5i4JZBLvjaq7eu39AcL5SbOaTHtc1gEHdLGkPzgLc15j5GXJHI0IyGEnXHnNuCa2+ VbDrzUjEip0zwacFIJFwYZiOrlSoo2i7yQQ= Received: from maileast.thefacebook.com ([163.114.130.16]) by mx0a-00082601.pphosted.com with ESMTP id 3091r0e35n-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:33 -0700 Received: from intmgw003.03.ash8.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.1847.3; Wed, 8 Apr 2020 16:25:33 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id B19073700D98; Wed, 8 Apr 2020 16:25:28 -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 07/16] bpf: add bpf_map target Date: Wed, 8 Apr 2020 16:25:28 -0700 Message-ID: <20200408232528.2675856-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 clxscore=1015 mlxscore=0 bulkscore=0 suspectscore=0 spamscore=0 lowpriorityscore=0 adultscore=0 priorityscore=1501 mlxlogscore=932 impostorscore=0 phishscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080164 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch added bpf_map target. Traversing all bpf_maps through map_idr. A reference is held for the map during the show() to ensure safety and correctness for field accesses. Signed-off-by: Yonghong Song --- kernel/bpf/syscall.c | 104 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index b5e4f18cc633..62a872a406ca 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -3797,3 +3797,107 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz return err; } + +struct bpfdump_seq_map_info { + struct bpf_map *map; + u32 id; +}; + +static struct bpf_map *bpf_map_seq_get_next(u32 *id) +{ + struct bpf_map *map; + + spin_lock_bh(&map_idr_lock); + map = idr_get_next(&map_idr, id); + if (map) + map = __bpf_map_inc_not_zero(map, false); + spin_unlock_bh(&map_idr_lock); + + return map; +} + +static void *bpf_map_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct bpfdump_seq_map_info *info = seq->private; + struct bpf_map *map; + u32 id = info->id + 1; + + map = bpf_map_seq_get_next(&id); + if (!map) + return NULL; + + ++*pos; + info->map = map; + info->id = id; + return map; +} + +static void *bpf_map_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct bpfdump_seq_map_info *info = seq->private; + struct bpf_map *map; + u32 id = info->id + 1; + + ++*pos; + map = bpf_map_seq_get_next(&id); + if (!map) + return NULL; + + __bpf_map_put(info->map, true); + info->map = map; + info->id = id; + return map; +} + +static void bpf_map_seq_stop(struct seq_file *seq, void *v) +{ + struct bpfdump_seq_map_info *info = seq->private; + + if (info->map) { + __bpf_map_put(info->map, true); + info->map = NULL; + } +} + +static int bpf_map_seq_show(struct seq_file *seq, void *v) +{ + struct { + struct bpf_map *map; + struct seq_file *seq; + u64 seq_num; + } ctx = { + .map = v, + .seq = seq, + }; + struct bpf_prog *prog; + int ret; + + prog = bpf_dump_get_prog(seq, sizeof(struct bpfdump_seq_map_info), + &ctx.seq_num); + ret = bpf_dump_run_prog(prog, &ctx); + + return ret == 0 ? 0 : -EINVAL; +} + +static const struct seq_operations bpf_map_seq_ops = { + .start = bpf_map_seq_start, + .next = bpf_map_seq_next, + .stop = bpf_map_seq_stop, + .show = bpf_map_seq_show, +}; + +int __init bpfdump__bpf_map(struct bpf_map *map, struct seq_file *seq, + u64 seq_num) +{ + return 0; +} + +static int __init bpf_map_dump_init(void) +{ + return bpf_dump_reg_target("bpf_map", + "bpfdump__bpf_map", + &bpf_map_seq_ops, + sizeof(struct bpfdump_seq_map_info), 0); +} + +late_initcall(bpf_map_dump_init); From patchwork Wed Apr 8 23:25:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221325 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.9 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, 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 60D28C2BA2B for ; Wed, 8 Apr 2020 23:26:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 38B2020857 for ; Wed, 8 Apr 2020 23:26:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="P458p4z0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726647AbgDHX0E (ORCPT ); Wed, 8 Apr 2020 19:26:04 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:16644 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726651AbgDHXZt (ORCPT ); Wed, 8 Apr 2020 19:25:49 -0400 Received: from pps.filterd (m0044012.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 038NPkrb015030 for ; Wed, 8 Apr 2020 16:25:49 -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=hhSDLhksnFQwWDo9xGvziq4KSONqdprdX6aZrtmDNNg=; b=P458p4z0sa4Cs74OOSrgOUOMC4XAYTau7rkfBW0HuPG/q919Q/rB+Au00W8mMEhPl3ZE 0RGdAtWoEEswkDAGISYuFIfGp/C1ODD+xtIWhVtEcM+WKGHidBNOQZQLHv5x9lsq/qm1 T+R0p5SLduRbUQfNHcfn8eq9+yK1svGuPC0= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 3091m5fkux-4 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:49 -0700 Received: from intmgw004.08.frc2.facebook.com (2620:10d:c085:208::f) 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, 8 Apr 2020 16:25:33 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 6DA973700D98; Wed, 8 Apr 2020 16:25:32 -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 10/16] bpf: support variable length array in tracing programs Date: Wed, 8 Apr 2020 16:25:32 -0700 Message-ID: <20200408232532.2676247-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 priorityscore=1501 spamscore=0 suspectscore=0 phishscore=0 adultscore=0 clxscore=1015 bulkscore=0 mlxlogscore=726 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080164 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 d65c6912bdaf..89a0d983b169 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -3837,6 +3837,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 8 23:25:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221327 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.9 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, 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 6C573C2BA80 for ; Wed, 8 Apr 2020 23:25:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 39C7420857 for ; Wed, 8 Apr 2020 23:25:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="SuCfeFV1" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726681AbgDHXZu (ORCPT ); Wed, 8 Apr 2020 19:25:50 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:44332 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726609AbgDHXZt (ORCPT ); Wed, 8 Apr 2020 19:25:49 -0400 Received: from pps.filterd (m0089730.ppops.net [127.0.0.1]) by m0089730.ppops.net (8.16.0.42/8.16.0.42) with SMTP id 038NPktG019414 for ; Wed, 8 Apr 2020 16:25:48 -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=iY/N6EyknMM8ykkZlA2aWrMlYJg1LKgpcNsAiirlEvA=; b=SuCfeFV1buL45opqHmzKIOznPBIzJHYQmx2Ar0V9rFe+PyacQ6SF/zq6D3kmG972T88d Avr6xKhxypX9X+oCO5dxBA9PIDgYMg33yZ0L9aZ496qyjFAjoDNjbHXLwurrMqYngcIO 3BqelpI0UvAJ84MCcH+Qf2LkW4GN62JmL/4= Received: from mail.thefacebook.com ([163.114.132.120]) by m0089730.ppops.net with ESMTP id 3091m37bq5-5 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:48 -0700 Received: from intmgw004.03.ash8.facebook.com (2620:10d:c085:208::f) by mail.thefacebook.com (2620:10d:c085:21d::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 8 Apr 2020 16:25:36 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id E15AE3700D98; Wed, 8 Apr 2020 16:25:34 -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 12/16] tools/libbpf: libbpf support for bpfdump Date: Wed, 8 Apr 2020 16:25:34 -0700 Message-ID: <20200408232534.2676393-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 adultscore=0 spamscore=0 suspectscore=0 mlxscore=0 mlxlogscore=999 bulkscore=0 lowpriorityscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 clxscore=1015 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080164 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 and query. 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_prog_fd. This is not really desirable, and need to think more how to have equally better user interface and cope with libbpf well. Signed-off-by: Yonghong Song --- tools/lib/bpf/bpf.c | 33 +++++++++++++++++++++++++++ tools/lib/bpf/bpf.h | 5 +++++ tools/lib/bpf/libbpf.c | 48 ++++++++++++++++++++++++++++++++++++---- tools/lib/bpf/libbpf.h | 1 + tools/lib/bpf/libbpf.map | 3 +++ 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 5cc1b0785d18..e8d4304fcc98 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -533,6 +533,39 @@ int bpf_obj_get(const char *pathname) return sys_bpf(BPF_OBJ_GET, &attr, sizeof(attr)); } +int bpf_obj_pin_dumper(int fd, const char *dname) +{ + union bpf_attr attr; + + memset(&attr, 0, sizeof(attr)); + attr.dumper_name = ptr_to_u64((void *)dname); + attr.bpf_fd = fd; + attr.file_flags = BPF_F_DUMP; + + return sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr)); +} + +int bpf_dump_query(int query_fd, __u32 flags, void *target_proto_buf, + __u32 buf_len, __u32 *prog_id) +{ + union bpf_attr attr; + int ret; + + memset(&attr, 0, sizeof(attr)); + attr.dump_query.query_fd = query_fd; + attr.dump_query.flags = flags; + if (target_proto_buf) { + attr.dump_query.target_proto = ptr_to_u64((void *)target_proto_buf); + attr.dump_query.proto_buf_len = buf_len; + } + + ret = sys_bpf(BPF_DUMP_QUERY, &attr, sizeof(attr)); + if (!ret && prog_id) + *prog_id = attr.dump_query.prog_id; + + return ret; +} + int bpf_prog_attach(int prog_fd, int target_fd, enum bpf_attach_type type, unsigned int flags) { diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 46d47afdd887..2f89f8445962 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -149,8 +149,13 @@ LIBBPF_API int bpf_map_update_batch(int fd, void *keys, void *values, __u32 *count, const struct bpf_map_batch_opts *opts); +LIBBPF_API int bpf_dump_query(int query_fd, __u32 flags, + void *target_proto_buf, __u32 buf_len, + __u32 *prog_id); + LIBBPF_API int bpf_obj_pin(int fd, const char *pathname); LIBBPF_API int bpf_obj_get(const char *pathname); +LIBBPF_API int bpf_obj_pin_dumper(int fd, const char *dname); struct bpf_prog_attach_opts { size_t sz; /* size of this struct for forward/backward compatibility */ diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index ff9174282a8c..c7a81ede56ce 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) @@ -2365,8 +2366,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; } @@ -4958,7 +4963,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 +5324,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 +5341,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); @@ -5459,6 +5475,11 @@ int bpf_program__pin_instance(struct bpf_program *prog, const char *path, return 0; } +int bpf_program__pin_dumper(struct bpf_program *prog, const char *dname) +{ + return bpf_obj_pin_dumper(bpf_program__fd(prog), dname); +} + int bpf_program__unpin_instance(struct bpf_program *prog, const char *path, int instance) { @@ -6322,6 +6343,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 +6424,23 @@ 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_prog_fd = fd; + } + return 0; +} + 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..ccb5d30fff4a 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -216,6 +216,7 @@ LIBBPF_API int bpf_program__unpin_instance(struct bpf_program *prog, 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_program__pin_dumper(struct bpf_program *prog, const char *dname); struct bpf_link; diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index bb8831605b25..ed6234bb199f 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -238,6 +238,7 @@ LIBBPF_0.0.7 { LIBBPF_0.0.8 { global: + bpf_dump_query; bpf_link__fd; bpf_link__open; bpf_link__pin; @@ -248,8 +249,10 @@ LIBBPF_0.0.8 { bpf_link_update; bpf_map__set_initial_value; bpf_program__attach_cgroup; + bpf_obj_pin_dumper; bpf_program__attach_lsm; bpf_program__is_lsm; + bpf_program__pin_dumper; bpf_program__set_attach_target; bpf_program__set_lsm; bpf_set_link_xdp_fd_opts; From patchwork Wed Apr 8 23:25:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221329 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=-7.1 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, UNWANTED_LANGUAGE_BODY, 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 69A44C2BA80 for ; Wed, 8 Apr 2020 23:25:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 40A3120857 for ; Wed, 8 Apr 2020 23:25:43 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="DNq9QX8b" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726620AbgDHXZm (ORCPT ); Wed, 8 Apr 2020 19:25:42 -0400 Received: from mx0a-00082601.pphosted.com ([67.231.145.42]:44806 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726609AbgDHXZl (ORCPT ); Wed, 8 Apr 2020 19:25:41 -0400 Received: from pps.filterd (m0109334.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 038NJKTa018375 for ; Wed, 8 Apr 2020 16:25:41 -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=5F2Z4iqSTnHgo+Cx/qOQEe6NpjiSHpelhxgORxYYlvA=; b=DNq9QX8bBbsUqVfR+sW5hdhQpoEdyGujx9kP7v0RRvkGn/hqi3UbrTKtQxxVy1lQJO15 /jUEruVEjgQONajwF4lnS/KgsEIVDm2A/aKBHIFAu2BNON652kANXMcofmJIJ10EU3uX UI1RuTSY14yK/TmXpOF2gg57998++EDAwZU= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com with ESMTP id 3091jtypsh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:41 -0700 Received: from intmgw004.08.frc2.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, 8 Apr 2020 16:25:40 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id 977403700D98; Wed, 8 Apr 2020 16:25:38 -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 15/16] tools/bpf: selftests: add dumper progs for bpf_map/task/task_file Date: Wed, 8 Apr 2020 16:25:38 -0700 Message-ID: <20200408232538.2676626-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 clxscore=1015 phishscore=0 impostorscore=0 lowpriorityscore=0 priorityscore=1501 malwarescore=0 suspectscore=0 adultscore=0 mlxlogscore=999 spamscore=0 bulkscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080163 X-FB-Internal: deliver Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The implementation is arbitrary, just to show how the bpf programs can be written for bpf_map/task/task_file. They can be costomized for specific needs. For example, for bpf_map, the dumper prints out: $ cat /sys/kernel/bpfdump/bpf_map/my1 id refcnt usercnt locked_vm 3 2 0 20 6 2 0 20 9 2 0 20 12 2 0 20 13 2 0 20 16 2 0 20 19 2 0 20 For task, the dumper prints out: $ cat /sys/kernel/bpfdump/task/my1 tgid gid 1 1 2 2 .... 1944 1944 1948 1948 1949 1949 1953 1953 For task/file, the dumper prints out: $ cat /sys/kernel/bpfdump/task/file/my1 tgid gid fd file 1 1 0 ffffffff95c97600 1 1 1 ffffffff95c97600 1 1 2 ffffffff95c97600 .... 1895 1895 255 ffffffff95c8fe00 1932 1932 0 ffffffff95c8fe00 1932 1932 1 ffffffff95c8fe00 1932 1932 2 ffffffff95c8fe00 1932 1932 3 ffffffff95c185c0 This is able to print out all open files (fd and file->f_op), so user can compare f_op against a particular kernel file operations to find what it is. For example, from /proc/kallsyms, we can find ffffffff95c185c0 r eventfd_fops so we will know tgid 1932 fd 3 is an eventfd file descriptor. Signed-off-by: Yonghong Song --- .../selftests/bpf/progs/bpfdump_bpf_map.c | 24 +++++++++++++++++++ .../selftests/bpf/progs/bpfdump_task.c | 21 ++++++++++++++++ .../selftests/bpf/progs/bpfdump_task_file.c | 24 +++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/bpfdump_bpf_map.c create mode 100644 tools/testing/selftests/bpf/progs/bpfdump_task.c create mode 100644 tools/testing/selftests/bpf/progs/bpfdump_task_file.c diff --git a/tools/testing/selftests/bpf/progs/bpfdump_bpf_map.c b/tools/testing/selftests/bpf/progs/bpfdump_bpf_map.c new file mode 100644 index 000000000000..c85f5a330010 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bpfdump_bpf_map.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Facebook */ +#include "vmlinux.h" +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +SEC("dump//sys/kernel/bpfdump/bpf_map") +int BPF_PROG(dump_bpf_map, struct bpf_map *map, struct seq_file *seq, u64 seq_num) +{ + static const char banner[] = " id refcnt usercnt locked_vm\n"; + static const char fmt1[] = "%8u %8ld "; + static const char fmt2[] = "%8ld %10lu\n"; + + if (seq_num == 0) + bpf_seq_printf(seq, banner, sizeof(banner)); + + bpf_seq_printf(seq, fmt1, sizeof(fmt1), map->id, map->refcnt.counter); + bpf_seq_printf(seq, fmt2, sizeof(fmt2), map->usercnt.counter, + map->memory.user->locked_vm.counter); + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/bpfdump_task.c b/tools/testing/selftests/bpf/progs/bpfdump_task.c new file mode 100644 index 000000000000..4d90ba97fbda --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bpfdump_task.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Facebook */ +#include "vmlinux.h" +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +SEC("dump//sys/kernel/bpfdump/task") +int BPF_PROG(dump_tasks, struct task_struct *task, struct seq_file *seq, u64 seq_num) +{ + static char const banner[] = " tgid gid\n"; + static char const fmt[] = "%8d %8d\n"; + + if (seq_num == 0) + bpf_seq_printf(seq, banner, sizeof(banner)); + + bpf_seq_printf(seq, fmt, sizeof(fmt), task->tgid, task->pid); + return 0; +} diff --git a/tools/testing/selftests/bpf/progs/bpfdump_task_file.c b/tools/testing/selftests/bpf/progs/bpfdump_task_file.c new file mode 100644 index 000000000000..5cf02c050e1f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bpfdump_task_file.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2020 Facebook */ +#include "vmlinux.h" +#include +#include +#include + +char _license[] SEC("license") = "GPL"; + +SEC("dump//sys/kernel/bpfdump/task/file") +int BPF_PROG(dump_tasks, struct task_struct *task, __u32 fd, struct file *file, + struct seq_file *seq, u64 seq_num) +{ + static char const banner[] = " tgid gid fd file\n"; + static char const fmt1[] = "%8d %8d"; + static char const fmt2[] = " %8d %lx\n"; + + if (seq_num == 0) + bpf_seq_printf(seq, banner, sizeof(banner)); + + bpf_seq_printf(seq, fmt1, sizeof(fmt1), task->tgid, task->pid); + bpf_seq_printf(seq, fmt2, sizeof(fmt2), fd, (long)file->f_op); + return 0; +} From patchwork Wed Apr 8 23:25:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yonghong Song X-Patchwork-Id: 221328 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.9 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, 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 1CC0BC2BA80 for ; Wed, 8 Apr 2020 23:25:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E732920857 for ; Wed, 8 Apr 2020 23:25:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="dFf6D+NB" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726638AbgDHXZu (ORCPT ); Wed, 8 Apr 2020 19:25:50 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:40692 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726632AbgDHXZs (ORCPT ); Wed, 8 Apr 2020 19:25:48 -0400 Received: from pps.filterd (m0089730.ppops.net [127.0.0.1]) by m0089730.ppops.net (8.16.0.42/8.16.0.42) with SMTP id 038NPkuQ019433 for ; Wed, 8 Apr 2020 16:25:47 -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=T5gLjKrXex1+wfvDooG7fzGOcWB825ac5uDuX1d6xpY=; b=dFf6D+NB4tBeRoK83m2ya3HNXpkVRgw0j/IcHfY7+HCK68rcm8URAw2wRmjPdz0xiVL0 nrM7G1+VcjvXsa3bMRS8M8OePUrPpalG+JY26kgSHeaeSK+/TBuBYmSXtbzL7lnsu1pQ inMcFomNpmGJYHVkQ2Qk6chC9m70L0tyYEg= Received: from maileast.thefacebook.com ([163.114.130.16]) by m0089730.ppops.net with ESMTP id 3091m37bqa-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Wed, 08 Apr 2020 16:25:47 -0700 Received: from intmgw005.03.ash8.facebook.com (2620:10d:c0a8:1b::d) by mail.thefacebook.com (2620:10d:c0a8:82::d) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1847.3; Wed, 8 Apr 2020 16:25:46 -0700 Received: by devbig003.ftw2.facebook.com (Postfix, from userid 128203) id D002D3700D98; Wed, 8 Apr 2020 16:25:39 -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 16/16] tools/bpf: selftests: add a selftest for anonymous dumper Date: Wed, 8 Apr 2020 16:25:39 -0700 Message-ID: <20200408232539.2676695-1-yhs@fb.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200408232520.2675265-1-yhs@fb.com> References: <20200408232520.2675265-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-08_09:2020-04-07,2020-04-08 signatures=0 X-Proofpoint-Spam-Details: rule=fb_default_notspam policy=fb_default score=0 adultscore=0 spamscore=0 suspectscore=0 mlxscore=0 mlxlogscore=999 bulkscore=0 lowpriorityscore=0 malwarescore=0 impostorscore=0 priorityscore=1501 clxscore=1015 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2004080164 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 | 41 +++++++++++++++++++ .../selftests/bpf/progs/bpfdump_test_kern.c | 26 ++++++++++++ 2 files changed, 67 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..a04fae7f1e3d --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/bpfdump_test.c @@ -0,0 +1,41 @@ +// 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_prog_attach(prog_fd, 0, BPF_TRACE_DUMP, 0); + if (CHECK(dumper_fd < 0, "bpf_prog_attach", "attach dumper 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..4758f5d11d9c --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bpfdump_test_kern.c @@ -0,0 +1,26 @@ +// 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 BPF_PROG(dump_tasks, struct task_struct *task, struct seq_file *seq, u64 seq_num) +{ + static char fmt[] = "%d"; + char c; + + if (count < 4) { + bpf_seq_printf(seq, fmt, sizeof(fmt), count); + c = 'A' + count; + bpf_seq_write(seq, &c, sizeof(c)); + count++; + } + + return 0; +}