brintos

brintos / linux-shallow public Read only

0
0
Text · 6.9 KiB · 2ec1de1 Raw
291 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 helpers99	 * are responsible for catching this, when doing actual size adjust100	 */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 helpers239	 * are responsible for catching this, when doing actual size adjust240	 */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}291