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/bpf_helpers.h>
16 #include <bpf/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("classifier/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);
76 bpf_printk("sk=%d\n", sk
? 1 : 0);
79 return sk
? TC_ACT_OK
: TC_ACT_UNSPEC
;
82 SEC("classifier/sk_lookup_success_simple")
83 int bpf_sk_lookup_test1(struct __sk_buff
*skb
)
85 struct bpf_sock_tuple tuple
= {};
88 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
94 SEC("classifier/fail_use_after_free")
95 int bpf_sk_lookup_uaf(struct __sk_buff
*skb
)
97 struct bpf_sock_tuple tuple
= {};
101 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
109 SEC("classifier/fail_modify_sk_pointer")
110 int bpf_sk_lookup_modptr(struct __sk_buff
*skb
)
112 struct bpf_sock_tuple tuple
= {};
116 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
124 SEC("classifier/fail_modify_sk_or_null_pointer")
125 int bpf_sk_lookup_modptr_or_null(struct __sk_buff
*skb
)
127 struct bpf_sock_tuple tuple
= {};
131 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
138 SEC("classifier/fail_no_release")
139 int bpf_sk_lookup_test2(struct __sk_buff
*skb
)
141 struct bpf_sock_tuple tuple
= {};
143 bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
147 SEC("classifier/fail_release_twice")
148 int bpf_sk_lookup_test3(struct __sk_buff
*skb
)
150 struct bpf_sock_tuple tuple
= {};
153 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
159 SEC("classifier/fail_release_unchecked")
160 int bpf_sk_lookup_test4(struct __sk_buff
*skb
)
162 struct bpf_sock_tuple tuple
= {};
165 sk
= bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
170 void lookup_no_release(struct __sk_buff
*skb
)
172 struct bpf_sock_tuple tuple
= {};
173 bpf_sk_lookup_tcp(skb
, &tuple
, sizeof(tuple
), BPF_F_CURRENT_NETNS
, 0);
176 SEC("classifier/fail_no_release_subcall")
177 int bpf_sk_lookup_test5(struct __sk_buff
*skb
)
179 lookup_no_release(skb
);