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 - 2026 Red Hat, Inc.