brintos

brintos / linux-shallow public Read only

0
0
Text · 7.1 KiB · f09cd14 Raw
369 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <vmlinux.h>3#include <bpf/bpf_tracing.h>4#include <bpf/bpf_helpers.h>5#include <bpf/bpf_core_read.h>6#include <bpf/bpf_endian.h>7#include "bpf_misc.h"8#include "bpf_experimental.h"9 10#ifndef ETH_P_IP11#define ETH_P_IP 0x080012#endif13 14struct {15	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);16	__uint(max_entries, 4);17	__uint(key_size, sizeof(__u32));18	__uint(value_size, sizeof(__u32));19} jmp_table SEC(".maps");20 21static __noinline int static_func(u64 i)22{23	bpf_throw(32);24	return i;25}26 27__noinline int global2static_simple(u64 i)28{29	static_func(i + 2);30	return i - 1;31}32 33__noinline int global2static(u64 i)34{35	if (i == ETH_P_IP)36		bpf_throw(16);37	return static_func(i);38}39 40static __noinline int static2global(u64 i)41{42	return global2static(i) + i;43}44 45SEC("tc")46int exception_throw_always_1(struct __sk_buff *ctx)47{48	bpf_throw(64);49	return 0;50}51 52/* In this case, the global func will never be seen executing after call to53 * static subprog, hence verifier will DCE the remaining instructions. Ensure we54 * are resilient to that.55 */56SEC("tc")57int exception_throw_always_2(struct __sk_buff *ctx)58{59	return global2static_simple(ctx->protocol);60}61 62SEC("tc")63int exception_throw_unwind_1(struct __sk_buff *ctx)64{65	return static2global(bpf_ntohs(ctx->protocol));66}67 68SEC("tc")69int exception_throw_unwind_2(struct __sk_buff *ctx)70{71	return static2global(bpf_ntohs(ctx->protocol) - 1);72}73 74SEC("tc")75int exception_throw_default(struct __sk_buff *ctx)76{77	bpf_throw(0);78	return 1;79}80 81SEC("tc")82int exception_throw_default_value(struct __sk_buff *ctx)83{84	bpf_throw(5);85	return 1;86}87 88SEC("tc")89int exception_tail_call_target(struct __sk_buff *ctx)90{91	bpf_throw(16);92	return 0;93}94 95static __noinline96int exception_tail_call_subprog(struct __sk_buff *ctx)97{98	volatile int ret = 10;99 100	bpf_tail_call_static(ctx, &jmp_table, 0);101	return ret;102}103 104SEC("tc")105int exception_tail_call(struct __sk_buff *ctx) {106	volatile int ret = 0;107 108	ret = exception_tail_call_subprog(ctx);109	return ret + 8;110}111 112__noinline int exception_ext_global(struct __sk_buff *ctx)113{114	volatile int ret = 0;115 116	return ret;117}118 119static __noinline int exception_ext_static(struct __sk_buff *ctx)120{121	return exception_ext_global(ctx);122}123 124SEC("tc")125int exception_ext(struct __sk_buff *ctx)126{127	return exception_ext_static(ctx);128}129 130__noinline int exception_cb_mod_global(u64 cookie)131{132	volatile int ret = 0;133 134	return ret;135}136 137/* Example of how the exception callback supplied during verification can still138 * introduce extensions by calling to dummy global functions, and alter runtime139 * behavior.140 *141 * Right now we don't allow freplace attachment to exception callback itself,142 * but if the need arises this restriction is technically feasible to relax in143 * the future.144 */145__noinline int exception_cb_mod(u64 cookie)146{147	return exception_cb_mod_global(cookie) + cookie + 10;148}149 150SEC("tc")151__exception_cb(exception_cb_mod)152int exception_ext_mod_cb_runtime(struct __sk_buff *ctx)153{154	bpf_throw(25);155	return 0;156}157 158__noinline static int subprog(struct __sk_buff *ctx)159{160	return bpf_ktime_get_ns();161}162 163__noinline static int throwing_subprog(struct __sk_buff *ctx)164{165	if (ctx->tstamp)166		bpf_throw(0);167	return bpf_ktime_get_ns();168}169 170__noinline int global_subprog(struct __sk_buff *ctx)171{172	return bpf_ktime_get_ns();173}174 175__noinline int throwing_global_subprog(struct __sk_buff *ctx)176{177	if (ctx->tstamp)178		bpf_throw(0);179	return bpf_ktime_get_ns();180}181 182SEC("tc")183int exception_throw_subprog(struct __sk_buff *ctx)184{185	switch (ctx->protocol) {186	case 1:187		return subprog(ctx);188	case 2:189		return global_subprog(ctx);190	case 3:191		return throwing_subprog(ctx);192	case 4:193		return throwing_global_subprog(ctx);194	default:195		break;196	}197	bpf_throw(1);198	return 0;199}200 201__noinline int assert_nz_gfunc(u64 c)202{203	volatile u64 cookie = c;204 205	bpf_assert(cookie != 0);206	return 0;207}208 209__noinline int assert_zero_gfunc(u64 c)210{211	volatile u64 cookie = c;212 213	bpf_assert(bpf_cmp_unlikely(cookie, ==, 0));214	return 0;215}216 217__noinline int assert_neg_gfunc(s64 c)218{219	volatile s64 cookie = c;220 221	bpf_assert(bpf_cmp_unlikely(cookie, <, 0));222	return 0;223}224 225__noinline int assert_pos_gfunc(s64 c)226{227	volatile s64 cookie = c;228 229	bpf_assert(bpf_cmp_unlikely(cookie, >, 0));230	return 0;231}232 233__noinline int assert_negeq_gfunc(s64 c)234{235	volatile s64 cookie = c;236 237	bpf_assert(bpf_cmp_unlikely(cookie, <=, -1));238	return 0;239}240 241__noinline int assert_poseq_gfunc(s64 c)242{243	volatile s64 cookie = c;244 245	bpf_assert(bpf_cmp_unlikely(cookie, >=, 1));246	return 0;247}248 249__noinline int assert_nz_gfunc_with(u64 c)250{251	volatile u64 cookie = c;252 253	bpf_assert_with(cookie != 0, cookie + 100);254	return 0;255}256 257__noinline int assert_zero_gfunc_with(u64 c)258{259	volatile u64 cookie = c;260 261	bpf_assert_with(bpf_cmp_unlikely(cookie, ==, 0), cookie + 100);262	return 0;263}264 265__noinline int assert_neg_gfunc_with(s64 c)266{267	volatile s64 cookie = c;268 269	bpf_assert_with(bpf_cmp_unlikely(cookie, <, 0), cookie + 100);270	return 0;271}272 273__noinline int assert_pos_gfunc_with(s64 c)274{275	volatile s64 cookie = c;276 277	bpf_assert_with(bpf_cmp_unlikely(cookie, >, 0), cookie + 100);278	return 0;279}280 281__noinline int assert_negeq_gfunc_with(s64 c)282{283	volatile s64 cookie = c;284 285	bpf_assert_with(bpf_cmp_unlikely(cookie, <=, -1), cookie + 100);286	return 0;287}288 289__noinline int assert_poseq_gfunc_with(s64 c)290{291	volatile s64 cookie = c;292 293	bpf_assert_with(bpf_cmp_unlikely(cookie, >=, 1), cookie + 100);294	return 0;295}296 297#define check_assert(name, cookie, tag)				\298SEC("tc")							\299int exception##tag##name(struct __sk_buff *ctx)			\300{								\301	return name(cookie) + 1;				\302}303 304check_assert(assert_nz_gfunc, 5, _);305check_assert(assert_zero_gfunc, 0, _);306check_assert(assert_neg_gfunc, -100, _);307check_assert(assert_pos_gfunc, 100, _);308check_assert(assert_negeq_gfunc, -1, _);309check_assert(assert_poseq_gfunc, 1, _);310 311check_assert(assert_nz_gfunc_with, 5, _);312check_assert(assert_zero_gfunc_with, 0, _);313check_assert(assert_neg_gfunc_with, -100, _);314check_assert(assert_pos_gfunc_with, 100, _);315check_assert(assert_negeq_gfunc_with, -1, _);316check_assert(assert_poseq_gfunc_with, 1, _);317 318check_assert(assert_nz_gfunc, 0, _bad_);319check_assert(assert_zero_gfunc, 5, _bad_);320check_assert(assert_neg_gfunc, 100, _bad_);321check_assert(assert_pos_gfunc, -100, _bad_);322check_assert(assert_negeq_gfunc, 1, _bad_);323check_assert(assert_poseq_gfunc, -1, _bad_);324 325check_assert(assert_nz_gfunc_with, 0, _bad_);326check_assert(assert_zero_gfunc_with, 5, _bad_);327check_assert(assert_neg_gfunc_with, 100, _bad_);328check_assert(assert_pos_gfunc_with, -100, _bad_);329check_assert(assert_negeq_gfunc_with, 1, _bad_);330check_assert(assert_poseq_gfunc_with, -1, _bad_);331 332SEC("tc")333int exception_assert_range(struct __sk_buff *ctx)334{335	u64 time = bpf_ktime_get_ns();336 337	bpf_assert_range(time, 0, ~0ULL);338	return 1;339}340 341SEC("tc")342int exception_assert_range_with(struct __sk_buff *ctx)343{344	u64 time = bpf_ktime_get_ns();345 346	bpf_assert_range_with(time, 0, ~0ULL, 10);347	return 1;348}349 350SEC("tc")351int exception_bad_assert_range(struct __sk_buff *ctx)352{353	u64 time = bpf_ktime_get_ns();354 355	bpf_assert_range(time, -100, 100);356	return 1;357}358 359SEC("tc")360int exception_bad_assert_range_with(struct __sk_buff *ctx)361{362	u64 time = bpf_ktime_get_ns();363 364	bpf_assert_range_with(time, -1000, 1000, 10);365	return 1;366}367 368char _license[] SEC("license") = "GPL";369