[PATCH bpf-next] bpf: Add rcu ptr in btf_id_sock_common_types

Philo Lu posted 1 patch 1 month, 2 weeks ago
kernel/bpf/verifier.c | 1 +
1 file changed, 1 insertion(+)
[PATCH bpf-next] bpf: Add rcu ptr in btf_id_sock_common_types
Posted by Philo Lu 1 month, 2 weeks ago
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
Re: [PATCH bpf-next] bpf: Add rcu ptr in btf_id_sock_common_types
Posted by Martin KaFai Lau 1 month, 2 weeks ago
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
Re: [PATCH bpf-next] bpf: Add rcu ptr in btf_id_sock_common_types
Posted by Philo Lu 1 month, 2 weeks ago

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

Re: [PATCH bpf-next] bpf: Add rcu ptr in btf_id_sock_common_types
Posted by Martin KaFai Lau 1 month, 2 weeks ago
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.
Re: [PATCH bpf-next] bpf: Add rcu ptr in btf_id_sock_common_types
Posted by Philo Lu 1 month, 2 weeks ago

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