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_lwt_bpf.c (6194B)


      1/* Copyright (c) 2016 Thomas Graf <tgraf@tgraf.ch>
      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 * This program is distributed in the hope that it will be useful, but
      8 * WITHOUT ANY WARRANTY; without even the implied warranty of
      9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     10 * General Public License for more details.
     11 */
     12
     13#include <stdint.h>
     14#include <stddef.h>
     15#include <linux/bpf.h>
     16#include <linux/ip.h>
     17#include <linux/in.h>
     18#include <linux/in6.h>
     19#include <linux/tcp.h>
     20#include <linux/udp.h>
     21#include <linux/icmpv6.h>
     22#include <linux/if_ether.h>
     23#include <bpf/bpf_helpers.h>
     24#include <string.h>
     25
     26# define printk(fmt, ...)						\
     27		({							\
     28			char ____fmt[] = fmt;				\
     29			bpf_trace_printk(____fmt, sizeof(____fmt),	\
     30				     ##__VA_ARGS__);			\
     31		})
     32
     33#define CB_MAGIC 1234
     34
     35/* Test: Pass all packets through */
     36SEC("nop")
     37int do_nop(struct __sk_buff *skb)
     38{
     39	return BPF_OK;
     40}
     41
     42/* Test: Verify context information can be accessed */
     43SEC("test_ctx")
     44int do_test_ctx(struct __sk_buff *skb)
     45{
     46	skb->cb[0] = CB_MAGIC;
     47	printk("len %d hash %d protocol %d\n", skb->len, skb->hash,
     48	       skb->protocol);
     49	printk("cb %d ingress_ifindex %d ifindex %d\n", skb->cb[0],
     50	       skb->ingress_ifindex, skb->ifindex);
     51
     52	return BPF_OK;
     53}
     54
     55/* Test: Ensure skb->cb[] buffer is cleared */
     56SEC("test_cb")
     57int do_test_cb(struct __sk_buff *skb)
     58{
     59	printk("cb0: %x cb1: %x cb2: %x\n", skb->cb[0], skb->cb[1],
     60	       skb->cb[2]);
     61	printk("cb3: %x cb4: %x\n", skb->cb[3], skb->cb[4]);
     62
     63	return BPF_OK;
     64}
     65
     66/* Test: Verify skb data can be read */
     67SEC("test_data")
     68int do_test_data(struct __sk_buff *skb)
     69{
     70	void *data = (void *)(long)skb->data;
     71	void *data_end = (void *)(long)skb->data_end;
     72	struct iphdr *iph = data;
     73
     74	if (data + sizeof(*iph) > data_end) {
     75		printk("packet truncated\n");
     76		return BPF_DROP;
     77	}
     78
     79	printk("src: %x dst: %x\n", iph->saddr, iph->daddr);
     80
     81	return BPF_OK;
     82}
     83
     84#define IP_CSUM_OFF offsetof(struct iphdr, check)
     85#define IP_DST_OFF offsetof(struct iphdr, daddr)
     86#define IP_SRC_OFF offsetof(struct iphdr, saddr)
     87#define IP_PROTO_OFF offsetof(struct iphdr, protocol)
     88#define TCP_CSUM_OFF offsetof(struct tcphdr, check)
     89#define UDP_CSUM_OFF offsetof(struct udphdr, check)
     90#define IS_PSEUDO 0x10
     91
     92static inline int rewrite(struct __sk_buff *skb, uint32_t old_ip,
     93			  uint32_t new_ip, int rw_daddr)
     94{
     95	int ret, off = 0, flags = IS_PSEUDO;
     96	uint8_t proto;
     97
     98	ret = bpf_skb_load_bytes(skb, IP_PROTO_OFF, &proto, 1);
     99	if (ret < 0) {
    100		printk("bpf_l4_csum_replace failed: %d\n", ret);
    101		return BPF_DROP;
    102	}
    103
    104	switch (proto) {
    105	case IPPROTO_TCP:
    106		off = TCP_CSUM_OFF;
    107		break;
    108
    109	case IPPROTO_UDP:
    110		off = UDP_CSUM_OFF;
    111		flags |= BPF_F_MARK_MANGLED_0;
    112		break;
    113
    114	case IPPROTO_ICMPV6:
    115		off = offsetof(struct icmp6hdr, icmp6_cksum);
    116		break;
    117	}
    118
    119	if (off) {
    120		ret = bpf_l4_csum_replace(skb, off, old_ip, new_ip,
    121					  flags | sizeof(new_ip));
    122		if (ret < 0) {
    123			printk("bpf_l4_csum_replace failed: %d\n");
    124			return BPF_DROP;
    125		}
    126	}
    127
    128	ret = bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip));
    129	if (ret < 0) {
    130		printk("bpf_l3_csum_replace failed: %d\n", ret);
    131		return BPF_DROP;
    132	}
    133
    134	if (rw_daddr)
    135		ret = bpf_skb_store_bytes(skb, IP_DST_OFF, &new_ip, sizeof(new_ip), 0);
    136	else
    137		ret = bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0);
    138
    139	if (ret < 0) {
    140		printk("bpf_skb_store_bytes() failed: %d\n", ret);
    141		return BPF_DROP;
    142	}
    143
    144	return BPF_OK;
    145}
    146
    147/* Test: Verify skb data can be modified */
    148SEC("test_rewrite")
    149int do_test_rewrite(struct __sk_buff *skb)
    150{
    151	uint32_t old_ip, new_ip = 0x3fea8c0;
    152	int ret;
    153
    154	ret = bpf_skb_load_bytes(skb, IP_DST_OFF, &old_ip, 4);
    155	if (ret < 0) {
    156		printk("bpf_skb_load_bytes failed: %d\n", ret);
    157		return BPF_DROP;
    158	}
    159
    160	if (old_ip == 0x2fea8c0) {
    161		printk("out: rewriting from %x to %x\n", old_ip, new_ip);
    162		return rewrite(skb, old_ip, new_ip, 1);
    163	}
    164
    165	return BPF_OK;
    166}
    167
    168static inline int __do_push_ll_and_redirect(struct __sk_buff *skb)
    169{
    170	uint64_t smac = SRC_MAC, dmac = DST_MAC;
    171	int ret, ifindex = DST_IFINDEX;
    172	struct ethhdr ehdr;
    173
    174	ret = bpf_skb_change_head(skb, 14, 0);
    175	if (ret < 0) {
    176		printk("skb_change_head() failed: %d\n", ret);
    177	}
    178
    179	ehdr.h_proto = __constant_htons(ETH_P_IP);
    180	memcpy(&ehdr.h_source, &smac, 6);
    181	memcpy(&ehdr.h_dest, &dmac, 6);
    182
    183	ret = bpf_skb_store_bytes(skb, 0, &ehdr, sizeof(ehdr), 0);
    184	if (ret < 0) {
    185		printk("skb_store_bytes() failed: %d\n", ret);
    186		return BPF_DROP;
    187	}
    188
    189	return bpf_redirect(ifindex, 0);
    190}
    191
    192SEC("push_ll_and_redirect_silent")
    193int do_push_ll_and_redirect_silent(struct __sk_buff *skb)
    194{
    195	return __do_push_ll_and_redirect(skb);
    196}
    197
    198SEC("push_ll_and_redirect")
    199int do_push_ll_and_redirect(struct __sk_buff *skb)
    200{
    201	int ret, ifindex = DST_IFINDEX;
    202
    203	ret = __do_push_ll_and_redirect(skb);
    204	if (ret >= 0)
    205		printk("redirected to %d\n", ifindex);
    206
    207	return ret;
    208}
    209
    210static inline void __fill_garbage(struct __sk_buff *skb)
    211{
    212	uint64_t f = 0xFFFFFFFFFFFFFFFF;
    213
    214	bpf_skb_store_bytes(skb, 0, &f, sizeof(f), 0);
    215	bpf_skb_store_bytes(skb, 8, &f, sizeof(f), 0);
    216	bpf_skb_store_bytes(skb, 16, &f, sizeof(f), 0);
    217	bpf_skb_store_bytes(skb, 24, &f, sizeof(f), 0);
    218	bpf_skb_store_bytes(skb, 32, &f, sizeof(f), 0);
    219	bpf_skb_store_bytes(skb, 40, &f, sizeof(f), 0);
    220	bpf_skb_store_bytes(skb, 48, &f, sizeof(f), 0);
    221	bpf_skb_store_bytes(skb, 56, &f, sizeof(f), 0);
    222	bpf_skb_store_bytes(skb, 64, &f, sizeof(f), 0);
    223	bpf_skb_store_bytes(skb, 72, &f, sizeof(f), 0);
    224	bpf_skb_store_bytes(skb, 80, &f, sizeof(f), 0);
    225	bpf_skb_store_bytes(skb, 88, &f, sizeof(f), 0);
    226}
    227
    228SEC("fill_garbage")
    229int do_fill_garbage(struct __sk_buff *skb)
    230{
    231	__fill_garbage(skb);
    232	printk("Set initial 96 bytes of header to FF\n");
    233	return BPF_OK;
    234}
    235
    236SEC("fill_garbage_and_redirect")
    237int do_fill_garbage_and_redirect(struct __sk_buff *skb)
    238{
    239	int ifindex = DST_IFINDEX;
    240	__fill_garbage(skb);
    241	printk("redirected to %d\n", ifindex);
    242	return bpf_redirect(ifindex, 0);
    243}
    244
    245/* Drop all packets */
    246SEC("drop_all")
    247int do_drop_all(struct __sk_buff *skb)
    248{
    249	printk("dropping with: %d\n", BPF_DROP);
    250	return BPF_DROP;
    251}
    252
    253char _license[] SEC("license") = "GPL";