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_tc_neigh_fib.c (3858B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <stdint.h>
      3#include <stdbool.h>
      4#include <stddef.h>
      5
      6#include <linux/bpf.h>
      7#include <linux/stddef.h>
      8#include <linux/pkt_cls.h>
      9#include <linux/if_ether.h>
     10#include <linux/in.h>
     11#include <linux/ip.h>
     12#include <linux/ipv6.h>
     13
     14#include <bpf/bpf_helpers.h>
     15#include <bpf/bpf_endian.h>
     16
     17#ifndef ctx_ptr
     18# define ctx_ptr(field)		(void *)(long)(field)
     19#endif
     20
     21#define AF_INET 2
     22#define AF_INET6 10
     23
     24static __always_inline int fill_fib_params_v4(struct __sk_buff *skb,
     25					      struct bpf_fib_lookup *fib_params)
     26{
     27	void *data_end = ctx_ptr(skb->data_end);
     28	void *data = ctx_ptr(skb->data);
     29	struct iphdr *ip4h;
     30
     31	if (data + sizeof(struct ethhdr) > data_end)
     32		return -1;
     33
     34	ip4h = (struct iphdr *)(data + sizeof(struct ethhdr));
     35	if ((void *)(ip4h + 1) > data_end)
     36		return -1;
     37
     38	fib_params->family = AF_INET;
     39	fib_params->tos = ip4h->tos;
     40	fib_params->l4_protocol = ip4h->protocol;
     41	fib_params->sport = 0;
     42	fib_params->dport = 0;
     43	fib_params->tot_len = bpf_ntohs(ip4h->tot_len);
     44	fib_params->ipv4_src = ip4h->saddr;
     45	fib_params->ipv4_dst = ip4h->daddr;
     46
     47	return 0;
     48}
     49
     50static __always_inline int fill_fib_params_v6(struct __sk_buff *skb,
     51					      struct bpf_fib_lookup *fib_params)
     52{
     53	struct in6_addr *src = (struct in6_addr *)fib_params->ipv6_src;
     54	struct in6_addr *dst = (struct in6_addr *)fib_params->ipv6_dst;
     55	void *data_end = ctx_ptr(skb->data_end);
     56	void *data = ctx_ptr(skb->data);
     57	struct ipv6hdr *ip6h;
     58
     59	if (data + sizeof(struct ethhdr) > data_end)
     60		return -1;
     61
     62	ip6h = (struct ipv6hdr *)(data + sizeof(struct ethhdr));
     63	if ((void *)(ip6h + 1) > data_end)
     64		return -1;
     65
     66	fib_params->family = AF_INET6;
     67	fib_params->flowinfo = 0;
     68	fib_params->l4_protocol = ip6h->nexthdr;
     69	fib_params->sport = 0;
     70	fib_params->dport = 0;
     71	fib_params->tot_len = bpf_ntohs(ip6h->payload_len);
     72	*src = ip6h->saddr;
     73	*dst = ip6h->daddr;
     74
     75	return 0;
     76}
     77
     78SEC("tc")
     79int tc_chk(struct __sk_buff *skb)
     80{
     81	void *data_end = ctx_ptr(skb->data_end);
     82	void *data = ctx_ptr(skb->data);
     83	__u32 *raw = data;
     84
     85	if (data + sizeof(struct ethhdr) > data_end)
     86		return TC_ACT_SHOT;
     87
     88	return !raw[0] && !raw[1] && !raw[2] ? TC_ACT_SHOT : TC_ACT_OK;
     89}
     90
     91static __always_inline int tc_redir(struct __sk_buff *skb)
     92{
     93	struct bpf_fib_lookup fib_params = { .ifindex = skb->ingress_ifindex };
     94	__u8 zero[ETH_ALEN * 2];
     95	int ret = -1;
     96
     97	switch (skb->protocol) {
     98	case __bpf_constant_htons(ETH_P_IP):
     99		ret = fill_fib_params_v4(skb, &fib_params);
    100		break;
    101	case __bpf_constant_htons(ETH_P_IPV6):
    102		ret = fill_fib_params_v6(skb, &fib_params);
    103		break;
    104	}
    105
    106	if (ret)
    107		return TC_ACT_OK;
    108
    109	ret = bpf_fib_lookup(skb, &fib_params, sizeof(fib_params), 0);
    110	if (ret == BPF_FIB_LKUP_RET_NOT_FWDED || ret < 0)
    111		return TC_ACT_OK;
    112
    113	__builtin_memset(&zero, 0, sizeof(zero));
    114	if (bpf_skb_store_bytes(skb, 0, &zero, sizeof(zero), 0) < 0)
    115		return TC_ACT_SHOT;
    116
    117	if (ret == BPF_FIB_LKUP_RET_NO_NEIGH) {
    118		struct bpf_redir_neigh nh_params = {};
    119
    120		nh_params.nh_family = fib_params.family;
    121		__builtin_memcpy(&nh_params.ipv6_nh, &fib_params.ipv6_dst,
    122				 sizeof(nh_params.ipv6_nh));
    123
    124		return bpf_redirect_neigh(fib_params.ifindex, &nh_params,
    125					  sizeof(nh_params), 0);
    126
    127	} else if (ret == BPF_FIB_LKUP_RET_SUCCESS) {
    128		void *data_end = ctx_ptr(skb->data_end);
    129		struct ethhdr *eth = ctx_ptr(skb->data);
    130
    131		if (eth + 1 > data_end)
    132			return TC_ACT_SHOT;
    133
    134		__builtin_memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN);
    135		__builtin_memcpy(eth->h_source, fib_params.smac, ETH_ALEN);
    136
    137		return bpf_redirect(fib_params.ifindex, 0);
    138	}
    139
    140	return TC_ACT_SHOT;
    141}
    142
    143/* these are identical, but keep them separate for compatibility with the
    144 * section names expected by test_tc_redirect.sh
    145 */
    146SEC("tc")
    147int tc_dst(struct __sk_buff *skb)
    148{
    149	return tc_redir(skb);
    150}
    151
    152SEC("tc")
    153int tc_src(struct __sk_buff *skb)
    154{
    155	return tc_redir(skb);
    156}
    157
    158char __license[] SEC("license") = "GPL";