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_check_mtu.c (7088B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright (c) 2020 Jesper Dangaard Brouer */
      3
      4#include <linux/bpf.h>
      5#include <bpf/bpf_helpers.h>
      6#include <linux/if_ether.h>
      7
      8#include <stddef.h>
      9#include <stdint.h>
     10
     11char _license[] SEC("license") = "GPL";
     12
     13/* Userspace will update with MTU it can see on device */
     14volatile const int GLOBAL_USER_MTU;
     15volatile const __u32 GLOBAL_USER_IFINDEX;
     16
     17/* BPF-prog will update these with MTU values it can see */
     18__u32 global_bpf_mtu_xdp = 0;
     19__u32 global_bpf_mtu_tc  = 0;
     20
     21SEC("xdp")
     22int xdp_use_helper_basic(struct xdp_md *ctx)
     23{
     24	__u32 mtu_len = 0;
     25
     26	if (bpf_check_mtu(ctx, 0, &mtu_len, 0, 0))
     27		return XDP_ABORTED;
     28
     29	return XDP_PASS;
     30}
     31
     32SEC("xdp")
     33int xdp_use_helper(struct xdp_md *ctx)
     34{
     35	int retval = XDP_PASS; /* Expected retval on successful test */
     36	__u32 mtu_len = 0;
     37	__u32 ifindex = 0;
     38	int delta = 0;
     39
     40	/* When ifindex is zero, save net_device lookup and use ctx netdev */
     41	if (GLOBAL_USER_IFINDEX > 0)
     42		ifindex = GLOBAL_USER_IFINDEX;
     43
     44	if (bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0)) {
     45		/* mtu_len is also valid when check fail */
     46		retval = XDP_ABORTED;
     47		goto out;
     48	}
     49
     50	if (mtu_len != GLOBAL_USER_MTU)
     51		retval = XDP_DROP;
     52
     53out:
     54	global_bpf_mtu_xdp = mtu_len;
     55	return retval;
     56}
     57
     58SEC("xdp")
     59int xdp_exceed_mtu(struct xdp_md *ctx)
     60{
     61	void *data_end = (void *)(long)ctx->data_end;
     62	void *data = (void *)(long)ctx->data;
     63	__u32 ifindex = GLOBAL_USER_IFINDEX;
     64	__u32 data_len = data_end - data;
     65	int retval = XDP_ABORTED; /* Fail */
     66	__u32 mtu_len = 0;
     67	int delta;
     68	int err;
     69
     70	/* Exceed MTU with 1 via delta adjust */
     71	delta = GLOBAL_USER_MTU - (data_len - ETH_HLEN) + 1;
     72
     73	err = bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0);
     74	if (err) {
     75		retval = XDP_PASS; /* Success in exceeding MTU check */
     76		if (err != BPF_MTU_CHK_RET_FRAG_NEEDED)
     77			retval = XDP_DROP;
     78	}
     79
     80	global_bpf_mtu_xdp = mtu_len;
     81	return retval;
     82}
     83
     84SEC("xdp")
     85int xdp_minus_delta(struct xdp_md *ctx)
     86{
     87	int retval = XDP_PASS; /* Expected retval on successful test */
     88	void *data_end = (void *)(long)ctx->data_end;
     89	void *data = (void *)(long)ctx->data;
     90	__u32 ifindex = GLOBAL_USER_IFINDEX;
     91	__u32 data_len = data_end - data;
     92	__u32 mtu_len = 0;
     93	int delta;
     94
     95	/* Borderline test case: Minus delta exceeding packet length allowed */
     96	delta = -((data_len - ETH_HLEN) + 1);
     97
     98	/* Minus length (adjusted via delta) still pass MTU check, other helpers
     99	 * are responsible for catching this, when doing actual size adjust
    100	 */
    101	if (bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0))
    102		retval = XDP_ABORTED;
    103
    104	global_bpf_mtu_xdp = mtu_len;
    105	return retval;
    106}
    107
    108SEC("xdp")
    109int xdp_input_len(struct xdp_md *ctx)
    110{
    111	int retval = XDP_PASS; /* Expected retval on successful test */
    112	void *data_end = (void *)(long)ctx->data_end;
    113	void *data = (void *)(long)ctx->data;
    114	__u32 ifindex = GLOBAL_USER_IFINDEX;
    115	__u32 data_len = data_end - data;
    116
    117	/* API allow user give length to check as input via mtu_len param,
    118	 * resulting MTU value is still output in mtu_len param after call.
    119	 *
    120	 * Input len is L3, like MTU and iph->tot_len.
    121	 * Remember XDP data_len is L2.
    122	 */
    123	__u32 mtu_len = data_len - ETH_HLEN;
    124
    125	if (bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0))
    126		retval = XDP_ABORTED;
    127
    128	global_bpf_mtu_xdp = mtu_len;
    129	return retval;
    130}
    131
    132SEC("xdp")
    133int xdp_input_len_exceed(struct xdp_md *ctx)
    134{
    135	int retval = XDP_ABORTED; /* Fail */
    136	__u32 ifindex = GLOBAL_USER_IFINDEX;
    137	int err;
    138
    139	/* API allow user give length to check as input via mtu_len param,
    140	 * resulting MTU value is still output in mtu_len param after call.
    141	 *
    142	 * Input length value is L3 size like MTU.
    143	 */
    144	__u32 mtu_len = GLOBAL_USER_MTU;
    145
    146	mtu_len += 1; /* Exceed with 1 */
    147
    148	err = bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0);
    149	if (err == BPF_MTU_CHK_RET_FRAG_NEEDED)
    150		retval = XDP_PASS ; /* Success in exceeding MTU check */
    151
    152	global_bpf_mtu_xdp = mtu_len;
    153	return retval;
    154}
    155
    156SEC("tc")
    157int tc_use_helper(struct __sk_buff *ctx)
    158{
    159	int retval = BPF_OK; /* Expected retval on successful test */
    160	__u32 mtu_len = 0;
    161	int delta = 0;
    162
    163	if (bpf_check_mtu(ctx, 0, &mtu_len, delta, 0)) {
    164		retval = BPF_DROP;
    165		goto out;
    166	}
    167
    168	if (mtu_len != GLOBAL_USER_MTU)
    169		retval = BPF_REDIRECT;
    170out:
    171	global_bpf_mtu_tc = mtu_len;
    172	return retval;
    173}
    174
    175SEC("tc")
    176int tc_exceed_mtu(struct __sk_buff *ctx)
    177{
    178	__u32 ifindex = GLOBAL_USER_IFINDEX;
    179	int retval = BPF_DROP; /* Fail */
    180	__u32 skb_len = ctx->len;
    181	__u32 mtu_len = 0;
    182	int delta;
    183	int err;
    184
    185	/* Exceed MTU with 1 via delta adjust */
    186	delta = GLOBAL_USER_MTU - (skb_len - ETH_HLEN) + 1;
    187
    188	err = bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0);
    189	if (err) {
    190		retval = BPF_OK; /* Success in exceeding MTU check */
    191		if (err != BPF_MTU_CHK_RET_FRAG_NEEDED)
    192			retval = BPF_DROP;
    193	}
    194
    195	global_bpf_mtu_tc = mtu_len;
    196	return retval;
    197}
    198
    199SEC("tc")
    200int tc_exceed_mtu_da(struct __sk_buff *ctx)
    201{
    202	/* SKB Direct-Access variant */
    203	void *data_end = (void *)(long)ctx->data_end;
    204	void *data = (void *)(long)ctx->data;
    205	__u32 ifindex = GLOBAL_USER_IFINDEX;
    206	__u32 data_len = data_end - data;
    207	int retval = BPF_DROP; /* Fail */
    208	__u32 mtu_len = 0;
    209	int delta;
    210	int err;
    211
    212	/* Exceed MTU with 1 via delta adjust */
    213	delta = GLOBAL_USER_MTU - (data_len - ETH_HLEN) + 1;
    214
    215	err = bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0);
    216	if (err) {
    217		retval = BPF_OK; /* Success in exceeding MTU check */
    218		if (err != BPF_MTU_CHK_RET_FRAG_NEEDED)
    219			retval = BPF_DROP;
    220	}
    221
    222	global_bpf_mtu_tc = mtu_len;
    223	return retval;
    224}
    225
    226SEC("tc")
    227int tc_minus_delta(struct __sk_buff *ctx)
    228{
    229	int retval = BPF_OK; /* Expected retval on successful test */
    230	__u32 ifindex = GLOBAL_USER_IFINDEX;
    231	__u32 skb_len = ctx->len;
    232	__u32 mtu_len = 0;
    233	int delta;
    234
    235	/* Borderline test case: Minus delta exceeding packet length allowed */
    236	delta = -((skb_len - ETH_HLEN) + 1);
    237
    238	/* Minus length (adjusted via delta) still pass MTU check, other helpers
    239	 * are responsible for catching this, when doing actual size adjust
    240	 */
    241	if (bpf_check_mtu(ctx, ifindex, &mtu_len, delta, 0))
    242		retval = BPF_DROP;
    243
    244	global_bpf_mtu_xdp = mtu_len;
    245	return retval;
    246}
    247
    248SEC("tc")
    249int tc_input_len(struct __sk_buff *ctx)
    250{
    251	int retval = BPF_OK; /* Expected retval on successful test */
    252	__u32 ifindex = GLOBAL_USER_IFINDEX;
    253
    254	/* API allow user give length to check as input via mtu_len param,
    255	 * resulting MTU value is still output in mtu_len param after call.
    256	 *
    257	 * Input length value is L3 size.
    258	 */
    259	__u32 mtu_len = GLOBAL_USER_MTU;
    260
    261	if (bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0))
    262		retval = BPF_DROP;
    263
    264	global_bpf_mtu_xdp = mtu_len;
    265	return retval;
    266}
    267
    268SEC("tc")
    269int tc_input_len_exceed(struct __sk_buff *ctx)
    270{
    271	int retval = BPF_DROP; /* Fail */
    272	__u32 ifindex = GLOBAL_USER_IFINDEX;
    273	int err;
    274
    275	/* API allow user give length to check as input via mtu_len param,
    276	 * resulting MTU value is still output in mtu_len param after call.
    277	 *
    278	 * Input length value is L3 size like MTU.
    279	 */
    280	__u32 mtu_len = GLOBAL_USER_MTU;
    281
    282	mtu_len += 1; /* Exceed with 1 */
    283
    284	err = bpf_check_mtu(ctx, ifindex, &mtu_len, 0, 0);
    285	if (err == BPF_MTU_CHK_RET_FRAG_NEEDED)
    286		retval = BPF_OK; /* Success in exceeding MTU check */
    287
    288	global_bpf_mtu_xdp = mtu_len;
    289	return retval;
    290}