Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.13 181 lines 4.4 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2// Copyright (c) 2018 Covalent IO, Inc. http://covalent.io 3 4#include <stddef.h> 5#include <stdbool.h> 6#include <string.h> 7#include <linux/bpf.h> 8#include <linux/if_ether.h> 9#include <linux/in.h> 10#include <linux/ip.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> 17 18int _version SEC("version") = 1; 19char _license[] SEC("license") = "GPL"; 20 21/* Fill 'tuple' with L3 info, and attempt to find L4. On fail, return NULL. */ 22static struct bpf_sock_tuple *get_tuple(void *data, __u64 nh_off, 23 void *data_end, __u16 eth_proto, 24 bool *ipv4) 25{ 26 struct bpf_sock_tuple *result; 27 __u8 proto = 0; 28 __u64 ihl_len; 29 30 if (eth_proto == bpf_htons(ETH_P_IP)) { 31 struct iphdr *iph = (struct iphdr *)(data + nh_off); 32 33 if (iph + 1 > data_end) 34 return NULL; 35 ihl_len = iph->ihl * 4; 36 proto = iph->protocol; 37 *ipv4 = true; 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); 41 42 if (ip6h + 1 > data_end) 43 return NULL; 44 ihl_len = sizeof(*ip6h); 45 proto = ip6h->nexthdr; 46 *ipv4 = true; 47 result = (struct bpf_sock_tuple *)&ip6h->saddr; 48 } 49 50 if (data + nh_off + ihl_len > data_end || proto != IPPROTO_TCP) 51 return NULL; 52 53 return result; 54} 55 56SEC("classifier/sk_lookup_success") 57int bpf_sk_lookup_test0(struct __sk_buff *skb) 58{ 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; 63 struct bpf_sock *sk; 64 size_t tuple_len; 65 bool ipv4; 66 67 if (eth + 1 > data_end) 68 return TC_ACT_SHOT; 69 70 tuple = get_tuple(data, sizeof(*eth), data_end, eth->h_proto, &ipv4); 71 if (!tuple || tuple + sizeof *tuple > data_end) 72 return TC_ACT_SHOT; 73 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); 77 if (sk) 78 bpf_sk_release(sk); 79 return sk ? TC_ACT_OK : TC_ACT_UNSPEC; 80} 81 82SEC("classifier/sk_lookup_success_simple") 83int bpf_sk_lookup_test1(struct __sk_buff *skb) 84{ 85 struct bpf_sock_tuple tuple = {}; 86 struct bpf_sock *sk; 87 88 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 89 if (sk) 90 bpf_sk_release(sk); 91 return 0; 92} 93 94SEC("classifier/fail_use_after_free") 95int bpf_sk_lookup_uaf(struct __sk_buff *skb) 96{ 97 struct bpf_sock_tuple tuple = {}; 98 struct bpf_sock *sk; 99 __u32 family = 0; 100 101 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 102 if (sk) { 103 bpf_sk_release(sk); 104 family = sk->family; 105 } 106 return family; 107} 108 109SEC("classifier/fail_modify_sk_pointer") 110int bpf_sk_lookup_modptr(struct __sk_buff *skb) 111{ 112 struct bpf_sock_tuple tuple = {}; 113 struct bpf_sock *sk; 114 __u32 family; 115 116 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 117 if (sk) { 118 sk += 1; 119 bpf_sk_release(sk); 120 } 121 return 0; 122} 123 124SEC("classifier/fail_modify_sk_or_null_pointer") 125int bpf_sk_lookup_modptr_or_null(struct __sk_buff *skb) 126{ 127 struct bpf_sock_tuple tuple = {}; 128 struct bpf_sock *sk; 129 __u32 family; 130 131 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 132 sk += 1; 133 if (sk) 134 bpf_sk_release(sk); 135 return 0; 136} 137 138SEC("classifier/fail_no_release") 139int bpf_sk_lookup_test2(struct __sk_buff *skb) 140{ 141 struct bpf_sock_tuple tuple = {}; 142 143 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 144 return 0; 145} 146 147SEC("classifier/fail_release_twice") 148int bpf_sk_lookup_test3(struct __sk_buff *skb) 149{ 150 struct bpf_sock_tuple tuple = {}; 151 struct bpf_sock *sk; 152 153 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 154 bpf_sk_release(sk); 155 bpf_sk_release(sk); 156 return 0; 157} 158 159SEC("classifier/fail_release_unchecked") 160int bpf_sk_lookup_test4(struct __sk_buff *skb) 161{ 162 struct bpf_sock_tuple tuple = {}; 163 struct bpf_sock *sk; 164 165 sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 166 bpf_sk_release(sk); 167 return 0; 168} 169 170void lookup_no_release(struct __sk_buff *skb) 171{ 172 struct bpf_sock_tuple tuple = {}; 173 bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); 174} 175 176SEC("classifier/fail_no_release_subcall") 177int bpf_sk_lookup_test5(struct __sk_buff *skb) 178{ 179 lookup_no_release(skb); 180 return 0; 181}