cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_sk_lookup_kern.c (4064B)


      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
     18char _license[] SEC("license") = "GPL";
     19
     20/* Fill 'tuple' with L3 info, and attempt to find L4. On fail, return NULL. */
     21static struct bpf_sock_tuple *get_tuple(void *data, __u64 nh_off,
     22					void *data_end, __u16 eth_proto,
     23					bool *ipv4)
     24{
     25	struct bpf_sock_tuple *result;
     26	__u8 proto = 0;
     27	__u64 ihl_len;
     28
     29	if (eth_proto == bpf_htons(ETH_P_IP)) {
     30		struct iphdr *iph = (struct iphdr *)(data + nh_off);
     31
     32		if (iph + 1 > data_end)
     33			return NULL;
     34		ihl_len = iph->ihl * 4;
     35		proto = iph->protocol;
     36		*ipv4 = true;
     37		result = (struct bpf_sock_tuple *)&iph->saddr;
     38	} else if (eth_proto == bpf_htons(ETH_P_IPV6)) {
     39		struct ipv6hdr *ip6h = (struct ipv6hdr *)(data + nh_off);
     40
     41		if (ip6h + 1 > data_end)
     42			return NULL;
     43		ihl_len = sizeof(*ip6h);
     44		proto = ip6h->nexthdr;
     45		*ipv4 = true;
     46		result = (struct bpf_sock_tuple *)&ip6h->saddr;
     47	}
     48
     49	if (data + nh_off + ihl_len > data_end || proto != IPPROTO_TCP)
     50		return NULL;
     51
     52	return result;
     53}
     54
     55SEC("?tc")
     56int sk_lookup_success(struct __sk_buff *skb)
     57{
     58	void *data_end = (void *)(long)skb->data_end;
     59	void *data = (void *)(long)skb->data;
     60	struct ethhdr *eth = (struct ethhdr *)(data);
     61	struct bpf_sock_tuple *tuple;
     62	struct bpf_sock *sk;
     63	size_t tuple_len;
     64	bool ipv4;
     65
     66	if (eth + 1 > data_end)
     67		return TC_ACT_SHOT;
     68
     69	tuple = get_tuple(data, sizeof(*eth), data_end, eth->h_proto, &ipv4);
     70	if (!tuple || tuple + sizeof *tuple > data_end)
     71		return TC_ACT_SHOT;
     72
     73	tuple_len = ipv4 ? sizeof(tuple->ipv4) : sizeof(tuple->ipv6);
     74	sk = bpf_sk_lookup_tcp(skb, tuple, tuple_len, BPF_F_CURRENT_NETNS, 0);
     75	bpf_printk("sk=%d\n", sk ? 1 : 0);
     76	if (sk)
     77		bpf_sk_release(sk);
     78	return sk ? TC_ACT_OK : TC_ACT_UNSPEC;
     79}
     80
     81SEC("?tc")
     82int sk_lookup_success_simple(struct __sk_buff *skb)
     83{
     84	struct bpf_sock_tuple tuple = {};
     85	struct bpf_sock *sk;
     86
     87	sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
     88	if (sk)
     89		bpf_sk_release(sk);
     90	return 0;
     91}
     92
     93SEC("?tc")
     94int err_use_after_free(struct __sk_buff *skb)
     95{
     96	struct bpf_sock_tuple tuple = {};
     97	struct bpf_sock *sk;
     98	__u32 family = 0;
     99
    100	sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    101	if (sk) {
    102		bpf_sk_release(sk);
    103		family = sk->family;
    104	}
    105	return family;
    106}
    107
    108SEC("?tc")
    109int err_modify_sk_pointer(struct __sk_buff *skb)
    110{
    111	struct bpf_sock_tuple tuple = {};
    112	struct bpf_sock *sk;
    113	__u32 family;
    114
    115	sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    116	if (sk) {
    117		sk += 1;
    118		bpf_sk_release(sk);
    119	}
    120	return 0;
    121}
    122
    123SEC("?tc")
    124int err_modify_sk_or_null_pointer(struct __sk_buff *skb)
    125{
    126	struct bpf_sock_tuple tuple = {};
    127	struct bpf_sock *sk;
    128	__u32 family;
    129
    130	sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    131	sk += 1;
    132	if (sk)
    133		bpf_sk_release(sk);
    134	return 0;
    135}
    136
    137SEC("?tc")
    138int err_no_release(struct __sk_buff *skb)
    139{
    140	struct bpf_sock_tuple tuple = {};
    141
    142	bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    143	return 0;
    144}
    145
    146SEC("?tc")
    147int err_release_twice(struct __sk_buff *skb)
    148{
    149	struct bpf_sock_tuple tuple = {};
    150	struct bpf_sock *sk;
    151
    152	sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    153	bpf_sk_release(sk);
    154	bpf_sk_release(sk);
    155	return 0;
    156}
    157
    158SEC("?tc")
    159int err_release_unchecked(struct __sk_buff *skb)
    160{
    161	struct bpf_sock_tuple tuple = {};
    162	struct bpf_sock *sk;
    163
    164	sk = bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    165	bpf_sk_release(sk);
    166	return 0;
    167}
    168
    169void lookup_no_release(struct __sk_buff *skb)
    170{
    171	struct bpf_sock_tuple tuple = {};
    172	bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0);
    173}
    174
    175SEC("?tc")
    176int err_no_release_subcall(struct __sk_buff *skb)
    177{
    178	lookup_no_release(skb);
    179	return 0;
    180}