Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 // Copyright (c) 2018 Covalent IO, Inc. http://covalent.io
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 /* Fill 'tuple' with L3 info, and attempt to find L4. On fail, return NULL. */
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 }