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_btf_skc_cls_ingress.c (3461B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2020 Facebook */
      3
      4#include <string.h>
      5#include <errno.h>
      6#include <netinet/in.h>
      7#include <linux/stddef.h>
      8#include <linux/bpf.h>
      9#include <linux/ipv6.h>
     10#include <linux/tcp.h>
     11#include <linux/if_ether.h>
     12#include <linux/pkt_cls.h>
     13
     14#include <bpf/bpf_helpers.h>
     15#include <bpf/bpf_endian.h>
     16#include "bpf_tcp_helpers.h"
     17
     18struct sockaddr_in6 srv_sa6 = {};
     19__u16 listen_tp_sport = 0;
     20__u16 req_sk_sport = 0;
     21__u32 recv_cookie = 0;
     22__u32 gen_cookie = 0;
     23__u32 linum = 0;
     24
     25#define LOG() ({ if (!linum) linum = __LINE__; })
     26
     27static void test_syncookie_helper(struct ipv6hdr *ip6h, struct tcphdr *th,
     28				  struct tcp_sock *tp,
     29				  struct __sk_buff *skb)
     30{
     31	if (th->syn) {
     32		__s64 mss_cookie;
     33		void *data_end;
     34
     35		data_end = (void *)(long)(skb->data_end);
     36
     37		if (th->doff * 4 != 40) {
     38			LOG();
     39			return;
     40		}
     41
     42		if ((void *)th + 40 > data_end) {
     43			LOG();
     44			return;
     45		}
     46
     47		mss_cookie = bpf_tcp_gen_syncookie(tp, ip6h, sizeof(*ip6h),
     48						   th, 40);
     49		if (mss_cookie < 0) {
     50			if (mss_cookie != -ENOENT)
     51				LOG();
     52		} else {
     53			gen_cookie = (__u32)mss_cookie;
     54		}
     55	} else if (gen_cookie) {
     56		/* It was in cookie mode */
     57		int ret = bpf_tcp_check_syncookie(tp, ip6h, sizeof(*ip6h),
     58						  th, sizeof(*th));
     59
     60		if (ret < 0) {
     61			if (ret != -ENOENT)
     62				LOG();
     63		} else {
     64			recv_cookie = bpf_ntohl(th->ack_seq) - 1;
     65		}
     66	}
     67}
     68
     69static int handle_ip6_tcp(struct ipv6hdr *ip6h, struct __sk_buff *skb)
     70{
     71	struct bpf_sock_tuple *tuple;
     72	struct bpf_sock *bpf_skc;
     73	unsigned int tuple_len;
     74	struct tcphdr *th;
     75	void *data_end;
     76
     77	data_end = (void *)(long)(skb->data_end);
     78
     79	th = (struct tcphdr *)(ip6h + 1);
     80	if (th + 1 > data_end)
     81		return TC_ACT_OK;
     82
     83	/* Is it the testing traffic? */
     84	if (th->dest != srv_sa6.sin6_port)
     85		return TC_ACT_OK;
     86
     87	tuple_len = sizeof(tuple->ipv6);
     88	tuple = (struct bpf_sock_tuple *)&ip6h->saddr;
     89	if ((void *)tuple + tuple_len > data_end) {
     90		LOG();
     91		return TC_ACT_OK;
     92	}
     93
     94	bpf_skc = bpf_skc_lookup_tcp(skb, tuple, tuple_len,
     95				     BPF_F_CURRENT_NETNS, 0);
     96	if (!bpf_skc) {
     97		LOG();
     98		return TC_ACT_OK;
     99	}
    100
    101	if (bpf_skc->state == BPF_TCP_NEW_SYN_RECV) {
    102		struct request_sock *req_sk;
    103
    104		req_sk = (struct request_sock *)bpf_skc_to_tcp_request_sock(bpf_skc);
    105		if (!req_sk) {
    106			LOG();
    107			goto release;
    108		}
    109
    110		if (bpf_sk_assign(skb, req_sk, 0)) {
    111			LOG();
    112			goto release;
    113		}
    114
    115		req_sk_sport = req_sk->__req_common.skc_num;
    116
    117		bpf_sk_release(req_sk);
    118		return TC_ACT_OK;
    119	} else if (bpf_skc->state == BPF_TCP_LISTEN) {
    120		struct tcp_sock *tp;
    121
    122		tp = bpf_skc_to_tcp_sock(bpf_skc);
    123		if (!tp) {
    124			LOG();
    125			goto release;
    126		}
    127
    128		if (bpf_sk_assign(skb, tp, 0)) {
    129			LOG();
    130			goto release;
    131		}
    132
    133		listen_tp_sport = tp->inet_conn.icsk_inet.sk.__sk_common.skc_num;
    134
    135		test_syncookie_helper(ip6h, th, tp, skb);
    136		bpf_sk_release(tp);
    137		return TC_ACT_OK;
    138	}
    139
    140	if (bpf_sk_assign(skb, bpf_skc, 0))
    141		LOG();
    142
    143release:
    144	bpf_sk_release(bpf_skc);
    145	return TC_ACT_OK;
    146}
    147
    148SEC("tc")
    149int cls_ingress(struct __sk_buff *skb)
    150{
    151	struct ipv6hdr *ip6h;
    152	struct ethhdr *eth;
    153	void *data_end;
    154
    155	data_end = (void *)(long)(skb->data_end);
    156
    157	eth = (struct ethhdr *)(long)(skb->data);
    158	if (eth + 1 > data_end)
    159		return TC_ACT_OK;
    160
    161	if (eth->h_proto != bpf_htons(ETH_P_IPV6))
    162		return TC_ACT_OK;
    163
    164	ip6h = (struct ipv6hdr *)(eth + 1);
    165	if (ip6h + 1 > data_end)
    166		return TC_ACT_OK;
    167
    168	if (ip6h->nexthdr == IPPROTO_TCP)
    169		return handle_ip6_tcp(ip6h, skb);
    170
    171	return TC_ACT_OK;
    172}
    173
    174char _license[] SEC("license") = "GPL";