From mboxrd@z Thu Jan 1 00:00:00 1970 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.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_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 E88B6C43381 for ; Tue, 26 Feb 2019 22:36:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AC686218E0 for ; Tue, 26 Feb 2019 22:36:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=fb.com header.i=@fb.com header.b="FR4FIDb+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729291AbfBZWgz (ORCPT ); Tue, 26 Feb 2019 17:36:55 -0500 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:57352 "EHLO mx0b-00082601.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729030AbfBZWgz (ORCPT ); Tue, 26 Feb 2019 17:36:55 -0500 Received: from pps.filterd (m0148460.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x1QMYBop015375 for ; Tue, 26 Feb 2019 14:36:53 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=facebook; bh=4KU1ncA5bEB4NMaEEvXTd0meZa+mR3wH6zfHIS+wta8=; b=FR4FIDb+VZgzUdXtMTcIaUXIFyqjF0mOhTIeb+eeYXBOZTYHSAp221BWfRoX8LWSF0NV kZzpmbmM3VhE8MEGLVuuKsRErtYyL4C3XscXintG1p8fyxhn7hwYPgFMhhS3I94FBs2v iCrxl3XgF5M4Rmi13jKMLpNOMs/bjf/GII0= Received: from maileast.thefacebook.com ([199.201.65.23]) by mx0a-00082601.pphosted.com with ESMTP id 2qwcffgesk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Feb 2019 14:36:53 -0800 Received: from mx-out.facebook.com (2620:10d:c0a1:3::13) by mail.thefacebook.com (2620:10d:c021:18::172) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA) id 15.1.1531.3; Tue, 26 Feb 2019 14:36:53 -0800 Received: by devvm424.lla2.facebook.com (Postfix, from userid 134475) id F0825D1D410C; Tue, 26 Feb 2019 14:36:51 -0800 (PST) Smtp-Origin-Hostprefix: devvm From: Javier Honduvilla Coto Smtp-Origin-Hostname: devvm424.lla2.facebook.com To: CC: , Smtp-Origin-Cluster: lla2c09 Subject: [PATCH bpf-next 1/3] bpf: add bpf_progenyof helper Date: Tue, 26 Feb 2019 14:36:49 -0800 Message-ID: <20190226223651.3166820-2-javierhonduco@fb.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190226223651.3166820-1-javierhonduco@fb.com> References: <20190226223651.3166820-1-javierhonduco@fb.com> X-FB-Internal: Safe MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2019-02-26_11:,, signatures=0 X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds the bpf_progenyof helper which receives a PID and returns 1 if the process currently being executed is in the process hierarchy including itself or 0 if not. This is very useful in tracing programs when we want to filter by a given PID and all the children it might spawn. The current workarounds most people implement for this purpose have issues: - Attaching to process spawning syscalls and dynamically add those PIDs to some bpf map that would be used to filter is cumbersome and potentially racy. - Unrolling some loop to perform what this helper is doing consumes lots of instructions. That and the impossibility to jump backwards makes it really hard to be correct in really large process chains. Signed-off-by: Javier Honduvilla Coto --- include/linux/bpf.h | 1 + include/uapi/linux/bpf.h | 3 ++- kernel/bpf/core.c | 1 + kernel/bpf/helpers.c | 29 +++++++++++++++++++++++++++++ kernel/trace/bpf_trace.c | 2 ++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index de18227b3d95..447395ba202b 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -921,6 +921,7 @@ extern const struct bpf_func_proto bpf_sk_redirect_map_proto; extern const struct bpf_func_proto bpf_spin_lock_proto; extern const struct bpf_func_proto bpf_spin_unlock_proto; extern const struct bpf_func_proto bpf_get_local_storage_proto; +extern const struct bpf_func_proto bpf_progenyof_proto; /* Shared helpers among cBPF and eBPF. */ void bpf_user_rnd_init_once(void); diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index bcdd2474eee7..804e4218eb28 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2457,7 +2457,8 @@ union bpf_attr { FN(spin_lock), \ FN(spin_unlock), \ FN(sk_fullsock), \ - FN(tcp_sock), + FN(tcp_sock), \ + FN(progenyof), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index ef88b167959d..69e209fbd128 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2015,6 +2015,7 @@ const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; const struct bpf_func_proto bpf_get_current_comm_proto __weak; const struct bpf_func_proto bpf_get_current_cgroup_id_proto __weak; const struct bpf_func_proto bpf_get_local_storage_proto __weak; +const struct bpf_func_proto bpf_progenyof_proto __weak; const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void) { diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index a411fc17d265..3899787e8dbf 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -18,6 +18,7 @@ #include #include #include +#include /* If kernel subsystem is allowing eBPF programs to call this function, * inside its own verifier_ops->get_func_proto() callback it should return @@ -364,3 +365,31 @@ const struct bpf_func_proto bpf_get_local_storage_proto = { }; #endif #endif + +BPF_CALL_1(bpf_progenyof, int, pid) +{ + int result = 0; + struct task_struct *task = current; + + if (unlikely(!task)) + return -EINVAL; + + rcu_read_lock(); + while (task != &init_task) { + if (task->pid == pid) { + result = 1; + break; + } + task = rcu_dereference(task->real_parent); + } + rcu_read_unlock(); + + return result; +} + +const struct bpf_func_proto bpf_progenyof_proto = { + .func = bpf_progenyof, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_ANYTHING, +}; diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index f1a86a0d881d..8602ae83c799 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -600,6 +600,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_get_prandom_u32_proto; case BPF_FUNC_probe_read_str: return &bpf_probe_read_str_proto; + case BPF_FUNC_progenyof: + return &bpf_progenyof_proto; #ifdef CONFIG_CGROUPS case BPF_FUNC_get_current_cgroup_id: return &bpf_get_current_cgroup_id_proto; -- 2.17.1