From patchwork Wed Jan 8 22:51:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Song Liu X-Patchwork-Id: 13931684 X-Patchwork-Delegate: bpf@iogearbox.net Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23169204F7E; Wed, 8 Jan 2025 22:52:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736376740; cv=none; b=MBvkd7g/fMKmksPJFNfOi+nstXKwj35hIfA2BZiy24yN5UVGEM3zNuJogOH2mSc1IHIVNV3sFKA2GtqtnQC8A4zvra1PIMRkLAIUI5QUwknX3f7Avs6NJc7549qFm7PLVkZimVKlCp6EV7VATFlRPiSt2nshMuvtCUyD++moQVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736376740; c=relaxed/simple; bh=9k3A2UgokQD1j14JroYk2224UwYIKDAhlrKEvRH8mT0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KuZOEpFNZCDEjj+6qgybgJELMl30YGbOKAHrMLrTHzS9fLF6Tifeuq31vRDWXta89ZToBnAZONhB7GsLryZWxPjk6Yg1iidUtndUSXGh4eS2Yl+3DG8lfiH5PVNqFqFUJdf/K/zWGH6Jpw+6AOG8f3Zhz96PzLFiuFazqfLsA5U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fqOtIgvc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fqOtIgvc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9D29AC4CEE3; Wed, 8 Jan 2025 22:52:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1736376740; bh=9k3A2UgokQD1j14JroYk2224UwYIKDAhlrKEvRH8mT0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fqOtIgvcqjfOore8chsz2fmUoWY2Bkj6xetsZYRiprvnvZhmjJpCGS2Zr2BsKnMW/ g7R1i3X3RS1lTo9nYheNz5yunG8Ekd7e7ihPjizVgMJnz1x0yOqh6ltufQmCQwPuyT x6Rknsm/tZchJOUhI/e1SpEL6C1Aeg/E6ykTIZAVMxuFRtDXZj0fKTFVg7/KxvyOd/ YUgCARgNuCFTAFxzRtID+Zb9qTOFD/6uU+6MSTn0yQw1CyUNA/BBHbdfdqCse90dol eMQN78UsT/jWbwdfF1WzorHRMnT+sREbg+5oOIUCMAY09vd+p2KAy7lXHla6igAjS4 pkCMfH9y0MLDA== From: Song Liu To: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Cc: kernel-team@meta.com, andrii@kernel.org, ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev, kpsingh@kernel.org, mattbobrowski@google.com, paul@paul-moore.com, jmorris@namei.org, serge@hallyn.com, memxor@gmail.com, Song Liu Subject: [PATCH v8 bpf-next 5/7] bpf: Use btf_kfunc_id_set.remap logic for bpf_dynptr_from_skb Date: Wed, 8 Jan 2025 14:51:38 -0800 Message-ID: <20250108225140.3467654-6-song@kernel.org> X-Mailer: git-send-email 2.43.5 In-Reply-To: <20250108225140.3467654-1-song@kernel.org> References: <20250108225140.3467654-1-song@kernel.org> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net btf_kfunc_id_set.remap can pick proper version of a kfunc for the calling context. Use this logic to select bpf_dynptr_from_skb or bpf_dynptr_from_skb_rdonly. This will make the verifier simpler. Unfortunately, btf_kfunc_id_set.remap cannot cover the DYNPTR_TYPE_SKB logic in check_kfunc_args(). This can be addressed later. Signed-off-by: Song Liu --- kernel/bpf/verifier.c | 25 ++++++---------------- net/core/filter.c | 49 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index c321fd25fca3..95b0847191fe 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -11677,6 +11677,7 @@ enum special_kfunc_type { KF_bpf_rbtree_add_impl, KF_bpf_rbtree_first, KF_bpf_dynptr_from_skb, + KF_bpf_dynptr_from_skb_rdonly, KF_bpf_dynptr_from_xdp, KF_bpf_dynptr_slice, KF_bpf_dynptr_slice_rdwr, @@ -11712,6 +11713,7 @@ BTF_ID(func, bpf_rbtree_add_impl) BTF_ID(func, bpf_rbtree_first) #ifdef CONFIG_NET BTF_ID(func, bpf_dynptr_from_skb) +BTF_ID(func, bpf_dynptr_from_skb_rdonly) BTF_ID(func, bpf_dynptr_from_xdp) #endif BTF_ID(func, bpf_dynptr_slice) @@ -11743,10 +11745,12 @@ BTF_ID(func, bpf_rbtree_add_impl) BTF_ID(func, bpf_rbtree_first) #ifdef CONFIG_NET BTF_ID(func, bpf_dynptr_from_skb) +BTF_ID(func, bpf_dynptr_from_skb_rdonly) BTF_ID(func, bpf_dynptr_from_xdp) #else BTF_ID_UNUSED BTF_ID_UNUSED +BTF_ID_UNUSED #endif BTF_ID(func, bpf_dynptr_slice) BTF_ID(func, bpf_dynptr_slice_rdwr) @@ -12668,7 +12672,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_ if (is_kfunc_arg_uninit(btf, &args[i])) dynptr_arg_type |= MEM_UNINIT; - if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) { + if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb] || + meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb_rdonly]) { dynptr_arg_type |= DYNPTR_TYPE_SKB; } else if (meta->func_id == special_kfunc_list[KF_bpf_dynptr_from_xdp]) { dynptr_arg_type |= DYNPTR_TYPE_XDP; @@ -20821,9 +20826,7 @@ static void specialize_kfunc(struct bpf_verifier_env *env, u32 func_id, u16 offset, unsigned long *addr) { struct bpf_prog *prog = env->prog; - bool seen_direct_write; void *xdp_kfunc; - bool is_rdonly; if (bpf_dev_bound_kfunc_id(func_id)) { xdp_kfunc = bpf_dev_bound_resolve_kfunc(prog, func_id); @@ -20833,22 +20836,6 @@ static void specialize_kfunc(struct bpf_verifier_env *env, } /* fallback to default kfunc when not supported by netdev */ } - - if (offset) - return; - - if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) { - seen_direct_write = env->seen_direct_write; - is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE); - - if (is_rdonly) - *addr = (unsigned long)bpf_dynptr_from_skb_rdonly; - - /* restore env->seen_direct_write to its original value, since - * may_access_direct_pkt_data mutates it - */ - env->seen_direct_write = seen_direct_write; - } } static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux, diff --git a/net/core/filter.c b/net/core/filter.c index 21131ec25f24..f12bcc1b21d1 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -12047,10 +12047,8 @@ __bpf_kfunc int bpf_sk_assign_tcp_reqsk(struct __sk_buff *s, struct sock *sk, #endif } -__bpf_kfunc_end_defs(); - -int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags, - struct bpf_dynptr *ptr__uninit) +__bpf_kfunc int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags, + struct bpf_dynptr *ptr__uninit) { struct bpf_dynptr_kern *ptr = (struct bpf_dynptr_kern *)ptr__uninit; int err; @@ -12064,10 +12062,16 @@ int bpf_dynptr_from_skb_rdonly(struct __sk_buff *skb, u64 flags, return 0; } +__bpf_kfunc_end_defs(); + BTF_KFUNCS_START(bpf_kfunc_check_set_skb) BTF_ID_FLAGS(func, bpf_dynptr_from_skb, KF_TRUSTED_ARGS) BTF_KFUNCS_END(bpf_kfunc_check_set_skb) +BTF_HIDDEN_KFUNCS_START(bpf_kfunc_check_hidden_set_skb) +BTF_ID_FLAGS(func, bpf_dynptr_from_skb_rdonly, KF_TRUSTED_ARGS) +BTF_KFUNCS_END(bpf_kfunc_check_hidden_set_skb) + BTF_KFUNCS_START(bpf_kfunc_check_set_xdp) BTF_ID_FLAGS(func, bpf_dynptr_from_xdp) BTF_KFUNCS_END(bpf_kfunc_check_set_xdp) @@ -12080,9 +12084,46 @@ BTF_KFUNCS_START(bpf_kfunc_check_set_tcp_reqsk) BTF_ID_FLAGS(func, bpf_sk_assign_tcp_reqsk, KF_TRUSTED_ARGS) BTF_KFUNCS_END(bpf_kfunc_check_set_tcp_reqsk) +BTF_ID_LIST(bpf_dynptr_from_skb_list) +BTF_ID(func, bpf_dynptr_from_skb) +BTF_ID(func, bpf_dynptr_from_skb_rdonly) + +static u32 bpf_kfunc_set_skb_remap(const struct bpf_prog *prog, u32 kfunc_id) +{ + if (kfunc_id != bpf_dynptr_from_skb_list[0]) + return 0; + + switch (resolve_prog_type(prog)) { + /* Program types only with direct read access go here! */ + case BPF_PROG_TYPE_LWT_IN: + case BPF_PROG_TYPE_LWT_OUT: + case BPF_PROG_TYPE_LWT_SEG6LOCAL: + case BPF_PROG_TYPE_SK_REUSEPORT: + case BPF_PROG_TYPE_FLOW_DISSECTOR: + case BPF_PROG_TYPE_CGROUP_SKB: + return bpf_dynptr_from_skb_list[1]; + + /* Program types with direct read + write access go here! */ + case BPF_PROG_TYPE_SCHED_CLS: + case BPF_PROG_TYPE_SCHED_ACT: + case BPF_PROG_TYPE_XDP: + case BPF_PROG_TYPE_LWT_XMIT: + case BPF_PROG_TYPE_SK_SKB: + case BPF_PROG_TYPE_SK_MSG: + case BPF_PROG_TYPE_CGROUP_SOCKOPT: + return kfunc_id; + + default: + break; + } + return bpf_dynptr_from_skb_list[1]; +} + static const struct btf_kfunc_id_set bpf_kfunc_set_skb = { .owner = THIS_MODULE, .set = &bpf_kfunc_check_set_skb, + .hidden_set = &bpf_kfunc_check_hidden_set_skb, + .remap = &bpf_kfunc_set_skb_remap, }; static const struct btf_kfunc_id_set bpf_kfunc_set_xdp = {