1 /* SPDX-License-Identifier: GPL-2.0 */
2 // Copyright (c) 2018 Covalent IO, Inc. http://covalent.io
8 #include <linux/if_ether.h>
11 #include <linux/ipv6.h>
12 #include <linux/pkt_cls.h>
13 #include <linux/tcp.h>
14 #include <sys/socket.h>
15 #include "bpf_helpers.h"
16 #include "bpf_endian.h"
18 int _version
SEC("version") = 1;
19 char _license
[] SEC("license") = "GPL";
21 /* Fill 'tuple' with L3 info, and attempt to find L4. On fail, return NULL. */
22 static struct bpf_sock_tuple
*get_tuple(void *data
, __u64 nh_off
,
23 void *data_end
, __u16 eth_proto
,
26 struct bpf_sock_tuple
*result
;
30 if (eth_proto
== bpf_htons(ETH_P_IP
)) {
31 struct iphdr
*iph
= (struct iphdr
*)(data
+ nh_off
);
33 if (iph
+ 1 > data_end
)
35 ihl_len
= iph
->ihl
* 4;
36 proto
= iph
->protocol
;
38 result
= (struct bpf_sock_tuple
*)&iph
->saddr
;
39 } else if (eth_proto
== bpf_htons(ETH_P_IPV6
)) {
40 struct ipv6hdr
*ip6h
= (struct ipv6hdr
*)(data
+ nh_off
);
42 if (ip6h
+ 1 > data_end
)
44 ihl_len
= sizeof(*ip6h
);
45 proto
= ip6h
->nexthdr
;
47 result
= (struct bpf_sock_tuple
*)&ip6h
->saddr
;
50 if (data
+ nh_off
+ ihl_len
> data_end
|| proto
!= IPPROTO_TCP
)
56 SEC("sk_lookup_success")
57 int bpf_sk_lookup_test0(struct __sk_buff
*skb
)
59 void *data_end
= (void *)(long)skb
->data_end
;
60 void *data
= (void *)(long)skb
->data
;
61 struct ethhdr
*eth
= (struct ethhdr
*)(data
);
62 struct bpf_sock_tuple
*tuple
;
67 if (eth
+ 1 > data_end
)
70 tuple
= get_tuple(data
, sizeof(*eth
), data_end
, eth
->h_proto
, &ipv4
);
71 if (!tuple
|| tuple
+ sizeof *tuple
> data_end
)
74 tuple_len
= ipv4
? sizeof(tuple
->ipv4
) : sizeof(tuple
->ipv6
);
75 sk
= bpf_sk_lookup_tcp(skb
, tuple
, tuple_len
, BPF_F_CURRENT_NETNS
, 0);
78 return sk
? TC_ACT_OK
: TC_ACT_UNSPEC
;
81 SEC("sk_lookup_success_simple")
82 int bpf_sk_lookup_test1(struct __sk_buff
*skb
)
84 struct bpf_sock_tuple tuple
= {};
87 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
93 SEC("fail_use_after_free")
94 int bpf_sk_lookup_uaf(struct __sk_buff
*skb
)
96 struct bpf_sock_tuple tuple
= {};
100 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
108 SEC("fail_modify_sk_pointer")
109 int bpf_sk_lookup_modptr(struct __sk_buff
*skb
)
111 struct bpf_sock_tuple tuple
= {};
115 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
123 SEC("fail_modify_sk_or_null_pointer")
124 int bpf_sk_lookup_modptr_or_null(struct __sk_buff
*skb
)
126 struct bpf_sock_tuple tuple
= {};
130 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
137 SEC("fail_no_release")
138 int bpf_sk_lookup_test2(struct __sk_buff
*skb
)
140 struct bpf_sock_tuple tuple
= {};
142 bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
146 SEC("fail_release_twice")
147 int bpf_sk_lookup_test3(struct __sk_buff
*skb
)
149 struct bpf_sock_tuple tuple
= {};
152 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
158 SEC("fail_release_unchecked")
159 int bpf_sk_lookup_test4(struct __sk_buff
*skb
)
161 struct bpf_sock_tuple tuple
= {};
164 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
169 void lookup_no_release(struct __sk_buff
*skb
)
171 struct bpf_sock_tuple tuple
= {};
172 bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
175 SEC("fail_no_release_subcall")
176 int bpf_sk_lookup_test5(struct __sk_buff
*skb
)
178 lookup_no_release(skb
);