brintos

brintos / linux-shallow public Read only

0
0
Text · 12.8 KiB · 6438982 Raw
613 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_experimental.h"7 8#include "linked_list.h"9 10#define INIT                                                  \11	struct map_value *v, *v2, *iv, *iv2;                  \12	struct foo *f, *f1, *f2;                              \13	struct bar *b;                                        \14	void *map;                                            \15                                                              \16	map = bpf_map_lookup_elem(&map_of_maps, &(int){ 0 }); \17	if (!map)                                             \18		return 0;                                     \19	v = bpf_map_lookup_elem(&array_map, &(int){ 0 });     \20	if (!v)                                               \21		return 0;                                     \22	v2 = bpf_map_lookup_elem(&array_map, &(int){ 0 });    \23	if (!v2)                                              \24		return 0;                                     \25	iv = bpf_map_lookup_elem(map, &(int){ 0 });           \26	if (!iv)                                              \27		return 0;                                     \28	iv2 = bpf_map_lookup_elem(map, &(int){ 0 });          \29	if (!iv2)                                             \30		return 0;                                     \31	f = bpf_obj_new(typeof(*f));                          \32	if (!f)                                               \33		return 0;                                     \34	f1 = f;                                               \35	f2 = bpf_obj_new(typeof(*f2));                        \36	if (!f2) {                                            \37		bpf_obj_drop(f1);                             \38		return 0;                                     \39	}                                                     \40	b = bpf_obj_new(typeof(*b));                          \41	if (!b) {                                             \42		bpf_obj_drop(f2);                             \43		bpf_obj_drop(f1);                             \44		return 0;                                     \45	}46 47#define CHECK(test, op, hexpr)                              \48	SEC("?tc")                                          \49	int test##_missing_lock_##op(void *ctx)             \50	{                                                   \51		INIT;                                       \52		void (*p)(void *) = (void *)&bpf_list_##op; \53		p(hexpr);                                   \54		return 0;                                   \55	}56 57CHECK(kptr, pop_front, &f->head);58CHECK(kptr, pop_back, &f->head);59 60CHECK(global, pop_front, &ghead);61CHECK(global, pop_back, &ghead);62 63CHECK(map, pop_front, &v->head);64CHECK(map, pop_back, &v->head);65 66CHECK(inner_map, pop_front, &iv->head);67CHECK(inner_map, pop_back, &iv->head);68 69#undef CHECK70 71#define CHECK(test, op, hexpr, nexpr)					\72	SEC("?tc")							\73	int test##_missing_lock_##op(void *ctx)				\74	{								\75		INIT;							\76		bpf_list_##op(hexpr, nexpr);				\77		return 0;						\78	}79 80CHECK(kptr, push_front, &f->head, &b->node);81CHECK(kptr, push_back, &f->head, &b->node);82 83CHECK(global, push_front, &ghead, &f->node2);84CHECK(global, push_back, &ghead, &f->node2);85 86CHECK(map, push_front, &v->head, &f->node2);87CHECK(map, push_back, &v->head, &f->node2);88 89CHECK(inner_map, push_front, &iv->head, &f->node2);90CHECK(inner_map, push_back, &iv->head, &f->node2);91 92#undef CHECK93 94#define CHECK(test, op, lexpr, hexpr)                       \95	SEC("?tc")                                          \96	int test##_incorrect_lock_##op(void *ctx)           \97	{                                                   \98		INIT;                                       \99		void (*p)(void *) = (void *)&bpf_list_##op; \100		bpf_spin_lock(lexpr);                       \101		p(hexpr);                                   \102		return 0;                                   \103	}104 105#define CHECK_OP(op)                                           \106	CHECK(kptr_kptr, op, &f1->lock, &f2->head);            \107	CHECK(kptr_global, op, &f1->lock, &ghead);             \108	CHECK(kptr_map, op, &f1->lock, &v->head);              \109	CHECK(kptr_inner_map, op, &f1->lock, &iv->head);       \110                                                               \111	CHECK(global_global, op, &glock2, &ghead);             \112	CHECK(global_kptr, op, &glock, &f1->head);             \113	CHECK(global_map, op, &glock, &v->head);               \114	CHECK(global_inner_map, op, &glock, &iv->head);        \115                                                               \116	CHECK(map_map, op, &v->lock, &v2->head);               \117	CHECK(map_kptr, op, &v->lock, &f2->head);              \118	CHECK(map_global, op, &v->lock, &ghead);               \119	CHECK(map_inner_map, op, &v->lock, &iv->head);         \120                                                               \121	CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head); \122	CHECK(inner_map_kptr, op, &iv->lock, &f2->head);       \123	CHECK(inner_map_global, op, &iv->lock, &ghead);        \124	CHECK(inner_map_map, op, &iv->lock, &v->head);125 126CHECK_OP(pop_front);127CHECK_OP(pop_back);128 129#undef CHECK130#undef CHECK_OP131 132#define CHECK(test, op, lexpr, hexpr, nexpr)				\133	SEC("?tc")							\134	int test##_incorrect_lock_##op(void *ctx)			\135	{								\136		INIT;							\137		bpf_spin_lock(lexpr);					\138		bpf_list_##op(hexpr, nexpr);				\139		return 0;						\140	}141 142#define CHECK_OP(op)							\143	CHECK(kptr_kptr, op, &f1->lock, &f2->head, &b->node);		\144	CHECK(kptr_global, op, &f1->lock, &ghead, &f->node2);		\145	CHECK(kptr_map, op, &f1->lock, &v->head, &f->node2);		\146	CHECK(kptr_inner_map, op, &f1->lock, &iv->head, &f->node2);	\147									\148	CHECK(global_global, op, &glock2, &ghead, &f->node2);		\149	CHECK(global_kptr, op, &glock, &f1->head, &b->node);		\150	CHECK(global_map, op, &glock, &v->head, &f->node2);		\151	CHECK(global_inner_map, op, &glock, &iv->head, &f->node2);	\152									\153	CHECK(map_map, op, &v->lock, &v2->head, &f->node2);		\154	CHECK(map_kptr, op, &v->lock, &f2->head, &b->node);		\155	CHECK(map_global, op, &v->lock, &ghead, &f->node2);		\156	CHECK(map_inner_map, op, &v->lock, &iv->head, &f->node2);	\157									\158	CHECK(inner_map_inner_map, op, &iv->lock, &iv2->head, &f->node2);\159	CHECK(inner_map_kptr, op, &iv->lock, &f2->head, &b->node);	\160	CHECK(inner_map_global, op, &iv->lock, &ghead, &f->node2);	\161	CHECK(inner_map_map, op, &iv->lock, &v->head, &f->node2);162 163CHECK_OP(push_front);164CHECK_OP(push_back);165 166#undef CHECK167#undef CHECK_OP168#undef INIT169 170SEC("?kprobe/xyz")171int map_compat_kprobe(void *ctx)172{173	bpf_list_push_front(&ghead, NULL);174	return 0;175}176 177SEC("?kretprobe/xyz")178int map_compat_kretprobe(void *ctx)179{180	bpf_list_push_front(&ghead, NULL);181	return 0;182}183 184SEC("?tracepoint/xyz")185int map_compat_tp(void *ctx)186{187	bpf_list_push_front(&ghead, NULL);188	return 0;189}190 191SEC("?perf_event")192int map_compat_perf(void *ctx)193{194	bpf_list_push_front(&ghead, NULL);195	return 0;196}197 198SEC("?raw_tp/xyz")199int map_compat_raw_tp(void *ctx)200{201	bpf_list_push_front(&ghead, NULL);202	return 0;203}204 205SEC("?raw_tp.w/xyz")206int map_compat_raw_tp_w(void *ctx)207{208	bpf_list_push_front(&ghead, NULL);209	return 0;210}211 212SEC("?tc")213int obj_type_id_oor(void *ctx)214{215	bpf_obj_new_impl(~0UL, NULL);216	return 0;217}218 219SEC("?tc")220int obj_new_no_composite(void *ctx)221{222	bpf_obj_new_impl(bpf_core_type_id_local(int), (void *)42);223	return 0;224}225 226SEC("?tc")227int obj_new_no_struct(void *ctx)228{229 230	bpf_obj_new(union { int data; unsigned udata; });231	return 0;232}233 234SEC("?tc")235int obj_drop_non_zero_off(void *ctx)236{237	void *f;238 239	f = bpf_obj_new(struct foo);240	if (!f)241		return 0;242	bpf_obj_drop(f+1);243	return 0;244}245 246SEC("?tc")247int new_null_ret(void *ctx)248{249	return bpf_obj_new(struct foo)->data;250}251 252SEC("?tc")253int obj_new_acq(void *ctx)254{255	bpf_obj_new(struct foo);256	return 0;257}258 259SEC("?tc")260int use_after_drop(void *ctx)261{262	struct foo *f;263 264	f = bpf_obj_new(typeof(*f));265	if (!f)266		return 0;267	bpf_obj_drop(f);268	return f->data;269}270 271SEC("?tc")272int ptr_walk_scalar(void *ctx)273{274	struct test1 {275		struct test2 {276			struct test2 *next;277		} *ptr;278	} *p;279 280	p = bpf_obj_new(typeof(*p));281	if (!p)282		return 0;283	bpf_this_cpu_ptr(p->ptr);284	return 0;285}286 287SEC("?tc")288int direct_read_lock(void *ctx)289{290	struct foo *f;291 292	f = bpf_obj_new(typeof(*f));293	if (!f)294		return 0;295	return *(int *)&f->lock;296}297 298SEC("?tc")299int direct_write_lock(void *ctx)300{301	struct foo *f;302 303	f = bpf_obj_new(typeof(*f));304	if (!f)305		return 0;306	*(int *)&f->lock = 0;307	return 0;308}309 310SEC("?tc")311int direct_read_head(void *ctx)312{313	struct foo *f;314 315	f = bpf_obj_new(typeof(*f));316	if (!f)317		return 0;318	return *(int *)&f->head;319}320 321SEC("?tc")322int direct_write_head(void *ctx)323{324	struct foo *f;325 326	f = bpf_obj_new(typeof(*f));327	if (!f)328		return 0;329	*(int *)&f->head = 0;330	return 0;331}332 333SEC("?tc")334int direct_read_node(void *ctx)335{336	struct foo *f;337 338	f = bpf_obj_new(typeof(*f));339	if (!f)340		return 0;341	return *(int *)&f->node2;342}343 344SEC("?tc")345int direct_write_node(void *ctx)346{347	struct foo *f;348 349	f = bpf_obj_new(typeof(*f));350	if (!f)351		return 0;352	*(int *)&f->node2 = 0;353	return 0;354}355 356static __always_inline357int use_after_unlock(bool push_front)358{359	struct foo *f;360 361	f = bpf_obj_new(typeof(*f));362	if (!f)363		return 0;364	bpf_spin_lock(&glock);365	f->data = 42;366	if (push_front)367		bpf_list_push_front(&ghead, &f->node2);368	else369		bpf_list_push_back(&ghead, &f->node2);370	bpf_spin_unlock(&glock);371 372	return f->data;373}374 375SEC("?tc")376int use_after_unlock_push_front(void *ctx)377{378	return use_after_unlock(true);379}380 381SEC("?tc")382int use_after_unlock_push_back(void *ctx)383{384	return use_after_unlock(false);385}386 387static __always_inline388int list_double_add(bool push_front)389{390	struct foo *f;391 392	f = bpf_obj_new(typeof(*f));393	if (!f)394		return 0;395	bpf_spin_lock(&glock);396	if (push_front) {397		bpf_list_push_front(&ghead, &f->node2);398		bpf_list_push_front(&ghead, &f->node2);399	} else {400		bpf_list_push_back(&ghead, &f->node2);401		bpf_list_push_back(&ghead, &f->node2);402	}403	bpf_spin_unlock(&glock);404 405	return 0;406}407 408SEC("?tc")409int double_push_front(void *ctx)410{411	return list_double_add(true);412}413 414SEC("?tc")415int double_push_back(void *ctx)416{417	return list_double_add(false);418}419 420SEC("?tc")421int no_node_value_type(void *ctx)422{423	void *p;424 425	p = bpf_obj_new(struct { int data; });426	if (!p)427		return 0;428	bpf_spin_lock(&glock);429	bpf_list_push_front(&ghead, p);430	bpf_spin_unlock(&glock);431 432	return 0;433}434 435SEC("?tc")436int incorrect_value_type(void *ctx)437{438	struct bar *b;439 440	b = bpf_obj_new(typeof(*b));441	if (!b)442		return 0;443	bpf_spin_lock(&glock);444	bpf_list_push_front(&ghead, &b->node);445	bpf_spin_unlock(&glock);446 447	return 0;448}449 450SEC("?tc")451int incorrect_node_var_off(struct __sk_buff *ctx)452{453	struct foo *f;454 455	f = bpf_obj_new(typeof(*f));456	if (!f)457		return 0;458	bpf_spin_lock(&glock);459	bpf_list_push_front(&ghead, (void *)&f->node2 + ctx->protocol);460	bpf_spin_unlock(&glock);461 462	return 0;463}464 465SEC("?tc")466int incorrect_node_off1(void *ctx)467{468	struct foo *f;469 470	f = bpf_obj_new(typeof(*f));471	if (!f)472		return 0;473	bpf_spin_lock(&glock);474	bpf_list_push_front(&ghead, (void *)&f->node2 + 1);475	bpf_spin_unlock(&glock);476 477	return 0;478}479 480SEC("?tc")481int incorrect_node_off2(void *ctx)482{483	struct foo *f;484 485	f = bpf_obj_new(typeof(*f));486	if (!f)487		return 0;488	bpf_spin_lock(&glock);489	bpf_list_push_front(&ghead, &f->node);490	bpf_spin_unlock(&glock);491 492	return 0;493}494 495SEC("?tc")496int no_head_type(void *ctx)497{498	void *p;499 500	p = bpf_obj_new(typeof(struct { int data; }));501	if (!p)502		return 0;503	bpf_spin_lock(&glock);504	bpf_list_push_front(p, NULL);505	bpf_spin_lock(&glock);506 507	return 0;508}509 510SEC("?tc")511int incorrect_head_var_off1(struct __sk_buff *ctx)512{513	struct foo *f;514 515	f = bpf_obj_new(typeof(*f));516	if (!f)517		return 0;518	bpf_spin_lock(&glock);519	bpf_list_push_front((void *)&ghead + ctx->protocol, &f->node2);520	bpf_spin_unlock(&glock);521 522	return 0;523}524 525SEC("?tc")526int incorrect_head_var_off2(struct __sk_buff *ctx)527{528	struct foo *f;529 530	f = bpf_obj_new(typeof(*f));531	if (!f)532		return 0;533	bpf_spin_lock(&glock);534	bpf_list_push_front((void *)&f->head + ctx->protocol, &f->node2);535	bpf_spin_unlock(&glock);536 537	return 0;538}539 540SEC("?tc")541int incorrect_head_off1(void *ctx)542{543	struct foo *f;544	struct bar *b;545 546	f = bpf_obj_new(typeof(*f));547	if (!f)548		return 0;549	b = bpf_obj_new(typeof(*b));550	if (!b) {551		bpf_obj_drop(f);552		return 0;553	}554 555	bpf_spin_lock(&f->lock);556	bpf_list_push_front((void *)&f->head + 1, &b->node);557	bpf_spin_unlock(&f->lock);558 559	return 0;560}561 562SEC("?tc")563int incorrect_head_off2(void *ctx)564{565	struct foo *f;566 567	f = bpf_obj_new(typeof(*f));568	if (!f)569		return 0;570 571	bpf_spin_lock(&glock);572	bpf_list_push_front((void *)&ghead + 1, &f->node2);573	bpf_spin_unlock(&glock);574 575	return 0;576}577 578static __always_inline579int pop_ptr_off(void *(*op)(void *head))580{581	struct {582		struct bpf_list_head head __contains(foo, node2);583		struct bpf_spin_lock lock;584	} *p;585	struct bpf_list_node *n;586 587	p = bpf_obj_new(typeof(*p));588	if (!p)589		return 0;590	bpf_spin_lock(&p->lock);591	n = op(&p->head);592	bpf_spin_unlock(&p->lock);593 594	if (!n)595		return 0;596	bpf_spin_lock((void *)n);597	return 0;598}599 600SEC("?tc")601int pop_front_off(void *ctx)602{603	return pop_ptr_off((void *)bpf_list_pop_front);604}605 606SEC("?tc")607int pop_back_off(void *ctx)608{609	return pop_ptr_off((void *)bpf_list_pop_back);610}611 612char _license[] SEC("license") = "GPL";613