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

tc_l2_redirect_kern.c (6142B)


      1/* Copyright (c) 2016 Facebook
      2 *
      3 * This program is free software; you can redistribute it and/or
      4 * modify it under the terms of version 2 of the GNU General Public
      5 * License as published by the Free Software Foundation.
      6 */
      7#define KBUILD_MODNAME "foo"
      8#include <uapi/linux/bpf.h>
      9#include <uapi/linux/if_ether.h>
     10#include <uapi/linux/if_packet.h>
     11#include <uapi/linux/ip.h>
     12#include <uapi/linux/ipv6.h>
     13#include <uapi/linux/in.h>
     14#include <uapi/linux/tcp.h>
     15#include <uapi/linux/filter.h>
     16#include <uapi/linux/pkt_cls.h>
     17#include <net/ipv6.h>
     18#include <bpf/bpf_helpers.h>
     19
     20#define _htonl __builtin_bswap32
     21
     22#define PIN_GLOBAL_NS		2
     23struct bpf_elf_map {
     24	__u32 type;
     25	__u32 size_key;
     26	__u32 size_value;
     27	__u32 max_elem;
     28	__u32 flags;
     29	__u32 id;
     30	__u32 pinning;
     31};
     32
     33/* copy of 'struct ethhdr' without __packed */
     34struct eth_hdr {
     35	unsigned char   h_dest[ETH_ALEN];
     36	unsigned char   h_source[ETH_ALEN];
     37	unsigned short  h_proto;
     38};
     39
     40struct bpf_elf_map SEC("maps") tun_iface = {
     41	.type = BPF_MAP_TYPE_ARRAY,
     42	.size_key = sizeof(int),
     43	.size_value = sizeof(int),
     44	.pinning = PIN_GLOBAL_NS,
     45	.max_elem = 1,
     46};
     47
     48static __always_inline bool is_vip_addr(__be16 eth_proto, __be32 daddr)
     49{
     50	if (eth_proto == htons(ETH_P_IP))
     51		return (_htonl(0xffffff00) & daddr) == _htonl(0x0a0a0100);
     52	else if (eth_proto == htons(ETH_P_IPV6))
     53		return (daddr == _htonl(0x2401face));
     54
     55	return false;
     56}
     57
     58SEC("l2_to_iptun_ingress_forward")
     59int _l2_to_iptun_ingress_forward(struct __sk_buff *skb)
     60{
     61	struct bpf_tunnel_key tkey = {};
     62	void *data = (void *)(long)skb->data;
     63	struct eth_hdr *eth = data;
     64	void *data_end = (void *)(long)skb->data_end;
     65	int key = 0, *ifindex;
     66
     67	int ret;
     68
     69	if (data + sizeof(*eth) > data_end)
     70		return TC_ACT_OK;
     71
     72	ifindex = bpf_map_lookup_elem(&tun_iface, &key);
     73	if (!ifindex)
     74		return TC_ACT_OK;
     75
     76	if (eth->h_proto == htons(ETH_P_IP)) {
     77		char fmt4[] = "ingress forward to ifindex:%d daddr4:%x\n";
     78		struct iphdr *iph = data + sizeof(*eth);
     79
     80		if (data + sizeof(*eth) + sizeof(*iph) > data_end)
     81			return TC_ACT_OK;
     82
     83		if (iph->protocol != IPPROTO_IPIP)
     84			return TC_ACT_OK;
     85
     86		bpf_trace_printk(fmt4, sizeof(fmt4), *ifindex,
     87				 _htonl(iph->daddr));
     88		return bpf_redirect(*ifindex, BPF_F_INGRESS);
     89	} else if (eth->h_proto == htons(ETH_P_IPV6)) {
     90		char fmt6[] = "ingress forward to ifindex:%d daddr6:%x::%x\n";
     91		struct ipv6hdr *ip6h = data + sizeof(*eth);
     92
     93		if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
     94			return TC_ACT_OK;
     95
     96		if (ip6h->nexthdr != IPPROTO_IPIP &&
     97		    ip6h->nexthdr != IPPROTO_IPV6)
     98			return TC_ACT_OK;
     99
    100		bpf_trace_printk(fmt6, sizeof(fmt6), *ifindex,
    101				 _htonl(ip6h->daddr.s6_addr32[0]),
    102				 _htonl(ip6h->daddr.s6_addr32[3]));
    103		return bpf_redirect(*ifindex, BPF_F_INGRESS);
    104	}
    105
    106	return TC_ACT_OK;
    107}
    108
    109SEC("l2_to_iptun_ingress_redirect")
    110int _l2_to_iptun_ingress_redirect(struct __sk_buff *skb)
    111{
    112	struct bpf_tunnel_key tkey = {};
    113	void *data = (void *)(long)skb->data;
    114	struct eth_hdr *eth = data;
    115	void *data_end = (void *)(long)skb->data_end;
    116	int key = 0, *ifindex;
    117
    118	int ret;
    119
    120	if (data + sizeof(*eth) > data_end)
    121		return TC_ACT_OK;
    122
    123	ifindex = bpf_map_lookup_elem(&tun_iface, &key);
    124	if (!ifindex)
    125		return TC_ACT_OK;
    126
    127	if (eth->h_proto == htons(ETH_P_IP)) {
    128		char fmt4[] = "e/ingress redirect daddr4:%x to ifindex:%d\n";
    129		struct iphdr *iph = data + sizeof(*eth);
    130		__be32 daddr = iph->daddr;
    131
    132		if (data + sizeof(*eth) + sizeof(*iph) > data_end)
    133			return TC_ACT_OK;
    134
    135		if (!is_vip_addr(eth->h_proto, daddr))
    136			return TC_ACT_OK;
    137
    138		bpf_trace_printk(fmt4, sizeof(fmt4), _htonl(daddr), *ifindex);
    139	} else {
    140		return TC_ACT_OK;
    141	}
    142
    143	tkey.tunnel_id = 10000;
    144	tkey.tunnel_ttl = 64;
    145	tkey.remote_ipv4 = 0x0a020166; /* 10.2.1.102 */
    146	bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), 0);
    147	return bpf_redirect(*ifindex, 0);
    148}
    149
    150SEC("l2_to_ip6tun_ingress_redirect")
    151int _l2_to_ip6tun_ingress_redirect(struct __sk_buff *skb)
    152{
    153	struct bpf_tunnel_key tkey = {};
    154	void *data = (void *)(long)skb->data;
    155	struct eth_hdr *eth = data;
    156	void *data_end = (void *)(long)skb->data_end;
    157	int key = 0, *ifindex;
    158
    159	if (data + sizeof(*eth) > data_end)
    160		return TC_ACT_OK;
    161
    162	ifindex = bpf_map_lookup_elem(&tun_iface, &key);
    163	if (!ifindex)
    164		return TC_ACT_OK;
    165
    166	if (eth->h_proto == htons(ETH_P_IP)) {
    167		char fmt4[] = "e/ingress redirect daddr4:%x to ifindex:%d\n";
    168		struct iphdr *iph = data + sizeof(*eth);
    169
    170		if (data + sizeof(*eth) + sizeof(*iph) > data_end)
    171			return TC_ACT_OK;
    172
    173		if (!is_vip_addr(eth->h_proto, iph->daddr))
    174			return TC_ACT_OK;
    175
    176		bpf_trace_printk(fmt4, sizeof(fmt4), _htonl(iph->daddr),
    177				 *ifindex);
    178	} else if (eth->h_proto == htons(ETH_P_IPV6)) {
    179		char fmt6[] = "e/ingress redirect daddr6:%x to ifindex:%d\n";
    180		struct ipv6hdr *ip6h = data + sizeof(*eth);
    181
    182		if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
    183			return TC_ACT_OK;
    184
    185		if (!is_vip_addr(eth->h_proto, ip6h->daddr.s6_addr32[0]))
    186			return TC_ACT_OK;
    187
    188		bpf_trace_printk(fmt6, sizeof(fmt6),
    189				 _htonl(ip6h->daddr.s6_addr32[0]), *ifindex);
    190	} else {
    191		return TC_ACT_OK;
    192	}
    193
    194	tkey.tunnel_id = 10000;
    195	tkey.tunnel_ttl = 64;
    196	/* 2401:db02:0:0:0:0:0:66 */
    197	tkey.remote_ipv6[0] = _htonl(0x2401db02);
    198	tkey.remote_ipv6[1] = 0;
    199	tkey.remote_ipv6[2] = 0;
    200	tkey.remote_ipv6[3] = _htonl(0x00000066);
    201	bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), BPF_F_TUNINFO_IPV6);
    202	return bpf_redirect(*ifindex, 0);
    203}
    204
    205SEC("drop_non_tun_vip")
    206int _drop_non_tun_vip(struct __sk_buff *skb)
    207{
    208	struct bpf_tunnel_key tkey = {};
    209	void *data = (void *)(long)skb->data;
    210	struct eth_hdr *eth = data;
    211	void *data_end = (void *)(long)skb->data_end;
    212
    213	if (data + sizeof(*eth) > data_end)
    214		return TC_ACT_OK;
    215
    216	if (eth->h_proto == htons(ETH_P_IP)) {
    217		struct iphdr *iph = data + sizeof(*eth);
    218
    219		if (data + sizeof(*eth) + sizeof(*iph) > data_end)
    220			return TC_ACT_OK;
    221
    222		if (is_vip_addr(eth->h_proto, iph->daddr))
    223			return TC_ACT_SHOT;
    224	} else if (eth->h_proto == htons(ETH_P_IPV6)) {
    225		struct ipv6hdr *ip6h = data + sizeof(*eth);
    226
    227		if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
    228			return TC_ACT_OK;
    229
    230		if (is_vip_addr(eth->h_proto, ip6h->daddr.s6_addr32[0]))
    231			return TC_ACT_SHOT;
    232	}
    233
    234	return TC_ACT_OK;
    235}
    236
    237char _license[] SEC("license") = "GPL";