kernel/bpf/verifier.c | 1 + 1 file changed, 1 insertion(+)
Sometimes sk is dereferenced as an rcu ptr, such as skb->sk in tp_btf,
which is a valid type of sock common. Then helpers like bpf_skc_to_*()
can be used with skb->sk.
For example, the following prog will be rejected without this patch:
```
SEC("tp_btf/tcp_bad_csum")
int BPF_PROG(tcp_bad_csum, struct sk_buff* skb)
{
struct sock *sk = skb->sk;
struct tcp_sock *tp;
if (!sk)
return 0;
tp = bpf_skc_to_tcp_sock(sk);
return 0;
}
```
Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
---
kernel/bpf/verifier.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 9a7ed527e47e..3e7ce448ae03 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8362,6 +8362,7 @@ static const struct bpf_reg_types btf_id_sock_common_types = {
PTR_TO_XDP_SOCK,
PTR_TO_BTF_ID,
PTR_TO_BTF_ID | PTR_TRUSTED,
+ PTR_TO_BTF_ID | MEM_RCU,
},
.btf_id = &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON],
};
--
2.32.0.3.g01195cf9f
On 10/8/24 1:09 AM, Philo Lu wrote: > Sometimes sk is dereferenced as an rcu ptr, such as skb->sk in tp_btf, > which is a valid type of sock common. Then helpers like bpf_skc_to_*() > can be used with skb->sk. > > For example, the following prog will be rejected without this patch: > ``` > SEC("tp_btf/tcp_bad_csum") > int BPF_PROG(tcp_bad_csum, struct sk_buff* skb) > { > struct sock *sk = skb->sk; > struct tcp_sock *tp; > > if (!sk) > return 0; > tp = bpf_skc_to_tcp_sock(sk); If the use case is for reading the fields in tp, please use the bpf_core_cast from the libbpf's bpf_core_read.h. bpf_core_cast is using the bpf_rdonly_cast kfunc underneath. pw-bot: cr
On 2024/10/9 03:05, Martin KaFai Lau wrote: > On 10/8/24 1:09 AM, Philo Lu wrote: >> Sometimes sk is dereferenced as an rcu ptr, such as skb->sk in tp_btf, >> which is a valid type of sock common. Then helpers like bpf_skc_to_*() >> can be used with skb->sk. >> >> For example, the following prog will be rejected without this patch: >> ``` >> SEC("tp_btf/tcp_bad_csum") >> int BPF_PROG(tcp_bad_csum, struct sk_buff* skb) >> { >> struct sock *sk = skb->sk; >> struct tcp_sock *tp; >> >> if (!sk) >> return 0; >> tp = bpf_skc_to_tcp_sock(sk); > > If the use case is for reading the fields in tp, please use the > bpf_core_cast from the libbpf's bpf_core_read.h. bpf_core_cast is using > the bpf_rdonly_cast kfunc underneath. > Thank you! This works for me so this patch is unnecessary then. Just curious is there any technical issue to include rcu_ptr into btf_id_sock_common_types? AFAICT rcu_ptr should also be a valid ptr type, and then btf_id_sock_common_types will behave like (PTR_TO_BTF_ID + &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON]) in bpf_func_proto. Thanks. -- Philo
On 10/8/24 7:23 PM, Philo Lu wrote: > > > On 2024/10/9 03:05, Martin KaFai Lau wrote: >> On 10/8/24 1:09 AM, Philo Lu wrote: >>> Sometimes sk is dereferenced as an rcu ptr, such as skb->sk in tp_btf, >>> which is a valid type of sock common. Then helpers like bpf_skc_to_*() >>> can be used with skb->sk. >>> >>> For example, the following prog will be rejected without this patch: >>> ``` >>> SEC("tp_btf/tcp_bad_csum") >>> int BPF_PROG(tcp_bad_csum, struct sk_buff* skb) >>> { >>> struct sock *sk = skb->sk; >>> struct tcp_sock *tp; >>> >>> if (!sk) >>> return 0; >>> tp = bpf_skc_to_tcp_sock(sk); >> >> If the use case is for reading the fields in tp, please use the bpf_core_cast >> from the libbpf's bpf_core_read.h. bpf_core_cast is using the bpf_rdonly_cast >> kfunc underneath. >> > > Thank you! This works for me so this patch is unnecessary then. > > Just curious is there any technical issue to include rcu_ptr into > btf_id_sock_common_types? AFAICT rcu_ptr should also be a valid ptr type, and > then btf_id_sock_common_types will behave like (PTR_TO_BTF_ID + > &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON]) in bpf_func_proto. bpf_skc_to_*() returns a PTR_TO_BTF_ID which can be passed into other helpers that takes ARG_PTR_TO_BTF_ID_SOCK_COMMON. There are helpers that change the sk. e.g. bpf_setsockopt() changes the sk and needs sk to be locked. Other non tracing hooks do have a hold on the skb also. I did take a quick look at the bpf_setsockopt situation and looks ok. I am positive there are other helpers that need to audit first. Tracing use case should only read the sk. bpf_core_cast() is the correct one to use. The bpf_sk_storage_{get,delete}() should be the only allowed helper that can change the sk.
On 2024/10/11 06:07, Martin KaFai Lau wrote: > On 10/8/24 7:23 PM, Philo Lu wrote: >> >> >> On 2024/10/9 03:05, Martin KaFai Lau wrote: >>> On 10/8/24 1:09 AM, Philo Lu wrote: >>>> Sometimes sk is dereferenced as an rcu ptr, such as skb->sk in tp_btf, >>>> which is a valid type of sock common. Then helpers like bpf_skc_to_*() >>>> can be used with skb->sk. >>>> >>>> For example, the following prog will be rejected without this patch: >>>> ``` >>>> SEC("tp_btf/tcp_bad_csum") >>>> int BPF_PROG(tcp_bad_csum, struct sk_buff* skb) >>>> { >>>> struct sock *sk = skb->sk; >>>> struct tcp_sock *tp; >>>> >>>> if (!sk) >>>> return 0; >>>> tp = bpf_skc_to_tcp_sock(sk); >>> >>> If the use case is for reading the fields in tp, please use the >>> bpf_core_cast from the libbpf's bpf_core_read.h. bpf_core_cast is >>> using the bpf_rdonly_cast kfunc underneath. >>> >> >> Thank you! This works for me so this patch is unnecessary then. >> >> Just curious is there any technical issue to include rcu_ptr into >> btf_id_sock_common_types? AFAICT rcu_ptr should also be a valid ptr >> type, and then btf_id_sock_common_types will behave like >> (PTR_TO_BTF_ID + &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON]) in >> bpf_func_proto. > > bpf_skc_to_*() returns a PTR_TO_BTF_ID which can be passed into other > helpers that takes ARG_PTR_TO_BTF_ID_SOCK_COMMON. There are helpers that > change the sk. e.g. bpf_setsockopt() changes the sk and needs sk to be > locked. Other non tracing hooks do have a hold on the skb also. I did > take a quick look at the bpf_setsockopt situation and looks ok. I am > positive there are other helpers that need to audit first. > > Tracing use case should only read the sk. bpf_core_cast() is the correct > one to use. The bpf_sk_storage_{get,delete}() should be the only allowed > helper that can change the sk. Thank you for explanation, Martin. This helps me a lot. -- Philo
© 2016 - 2024 Red Hat, Inc.