0001
0002
0003
0004 #include <stddef.h>
0005 #include <stdbool.h>
0006 #include <string.h>
0007 #include <linux/bpf.h>
0008 #include <linux/if_ether.h>
0009 #include <linux/in.h>
0010 #include <linux/ip.h>
0011 #include <linux/ipv6.h>
0012 #include <linux/pkt_cls.h>
0013 #include <linux/tcp.h>
0014 #include <sys/socket.h>
0015 #include <bpf/bpf_helpers.h>
0016 #include <bpf/bpf_endian.h>
0017
0018 char _license[] SEC("license") = "GPL";
0019
0020
0021 static struct bpf_sock_tuple *get_tuple(void *data, __u64 nh_off,
0022 void *data_end, __u16 eth_proto,
0023 bool *ipv4)
0024 {
0025 struct bpf_sock_tuple *result;
0026 __u8 proto = 0;
0027 __u64 ihl_len;
0028
0029 if (eth_proto == bpf_htons(ETH_P_IP)) {
0030 struct iphdr *iph = (struct iphdr *)(data + nh_off);
0031
0032 if (iph + 1 > data_end)
0033 return NULL;
0034 ihl_len = iph->ihl * 4;
0035 proto = iph->protocol;
0036 *ipv4 = true;
0037 result = (struct bpf_sock_tuple *)&iph->saddr;
0038 } else if (eth_proto == bpf_htons(ETH_P_IPV6)) {
0039 struct ipv6hdr *ip6h = (struct ipv6hdr *)(data + nh_off);
0040
0041 if (ip6h + 1 > data_end)
0042 return NULL;
0043 ihl_len = sizeof(*ip6h);
0044 proto = ip6h->nexthdr;
0045 *ipv4 = true;
0046 result = (struct bpf_sock_tuple *)&ip6h->saddr;
0047 }
0048
0049 if (data + nh_off + ihl_len > data_end || proto != IPPROTO_TCP)
0050 return NULL;
0051
0052 return result;
0053 }
0054
0055 SEC("?tc")
0056 int sk_lookup_success(struct __sk_buff *skb)
0057 {
0058 void *data_end = (void *)(long)skb->data_end;
0059 void *data = (void *)(long)skb->data;
0060 struct ethhdr *eth = (struct ethhdr *)(data);
0061 struct bpf_sock_tuple *tuple;
0062 struct bpf_sock *sk;
0063 size_t tuple_len;
0064 bool ipv4;
0065
0066 if (eth + 1 > data_end)
0067 return TC_ACT_SHOT;
0068
0069 tuple = get_tuple(data, sizeof(*eth), data_end, eth->h_proto, &ipv4);
0070 if (!tuple || tuple + sizeof *tuple > data_end)
0071 return TC_ACT_SHOT;
0072
0073 tuple_len = ipv4 ? sizeof(tuple->ipv4) : sizeof(tuple->ipv6);
0074 sk = bpf_sk_lookup_tcp(skb, tuple, tuple_len, BPF_F_CURRENT_NETNS, 0);
0075 bpf_printk("sk=%d\n", sk ? 1 : 0);
0076 if (sk)
0077 bpf_sk_release(sk);
0078 return sk ? TC_ACT_OK : TC_ACT_UNSPEC;
0079 }
0080
0081 SEC("?tc")
0082 int sk_lookup_success_simple(struct __sk_buff *skb)
0083 {
0084 struct bpf_sock_tuple tuple = {};
0085 struct bpf_sock *sk;
0086
0087 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0088 if (sk)
0089 bpf_sk_release(sk);
0090 return 0;
0091 }
0092
0093 SEC("?tc")
0094 int err_use_after_free(struct __sk_buff *skb)
0095 {
0096 struct bpf_sock_tuple tuple = {};
0097 struct bpf_sock *sk;
0098 __u32 family = 0;
0099
0100 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0101 if (sk) {
0102 bpf_sk_release(sk);
0103 family = sk->family;
0104 }
0105 return family;
0106 }
0107
0108 SEC("?tc")
0109 int err_modify_sk_pointer(struct __sk_buff *skb)
0110 {
0111 struct bpf_sock_tuple tuple = {};
0112 struct bpf_sock *sk;
0113 __u32 family;
0114
0115 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0116 if (sk) {
0117 sk += 1;
0118 bpf_sk_release(sk);
0119 }
0120 return 0;
0121 }
0122
0123 SEC("?tc")
0124 int err_modify_sk_or_null_pointer(struct __sk_buff *skb)
0125 {
0126 struct bpf_sock_tuple tuple = {};
0127 struct bpf_sock *sk;
0128 __u32 family;
0129
0130 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0131 sk += 1;
0132 if (sk)
0133 bpf_sk_release(sk);
0134 return 0;
0135 }
0136
0137 SEC("?tc")
0138 int err_no_release(struct __sk_buff *skb)
0139 {
0140 struct bpf_sock_tuple tuple = {};
0141
0142 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0143 return 0;
0144 }
0145
0146 SEC("?tc")
0147 int err_release_twice(struct __sk_buff *skb)
0148 {
0149 struct bpf_sock_tuple tuple = {};
0150 struct bpf_sock *sk;
0151
0152 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0153 bpf_sk_release(sk);
0154 bpf_sk_release(sk);
0155 return 0;
0156 }
0157
0158 SEC("?tc")
0159 int err_release_unchecked(struct __sk_buff *skb)
0160 {
0161 struct bpf_sock_tuple tuple = {};
0162 struct bpf_sock *sk;
0163
0164 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0165 bpf_sk_release(sk);
0166 return 0;
0167 }
0168
0169 void lookup_no_release(struct __sk_buff *skb)
0170 {
0171 struct bpf_sock_tuple tuple = {};
0172 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
0173 }
0174
0175 SEC("?tc")
0176 int err_no_release_subcall(struct __sk_buff *skb)
0177 {
0178 lookup_no_release(skb);
0179 return 0;
0180 }