brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · 0f4dfb7 Raw
209 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2021 Facebook */3#include <linux/stddef.h>4#include <linux/bpf.h>5#include <bpf/bpf_helpers.h>6#include <bpf/bpf_tracing.h>7#include <../../../tools/include/linux/filter.h>8#include <linux/btf.h>9#include <string.h>10#include <errno.h>11#include "bpf_misc.h"12 13char _license[] SEC("license") = "GPL";14 15struct bpf_map {16	int id;17}  __attribute__((preserve_access_index));18 19struct args {20	__u64 log_buf;21	__u32 log_size;22	int max_entries;23	int map_fd;24	int prog_fd;25	int btf_fd;26};27 28#define BTF_INFO_ENC(kind, kind_flag, vlen) \29	((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))30#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)31#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \32	((encoding) << 24 | (bits_offset) << 16 | (nr_bits))33#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \34	BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \35	BTF_INT_ENC(encoding, bits_offset, bits)36 37struct {38	__uint(type, BPF_MAP_TYPE_ARRAY);39	__type(key, int);40	__type(value, union bpf_attr);41	__uint(max_entries, 1);42} bpf_attr_array SEC(".maps");43 44struct inner_map_type {45	__uint(type, BPF_MAP_TYPE_ARRAY);46	__uint(key_size, 4);47	__uint(value_size, 4);48	__uint(max_entries, 1);49} inner_map SEC(".maps");50 51struct {52	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);53	__type(key, int);54	__type(value, int);55	__uint(max_entries, 1);56	__array(values, struct inner_map_type);57} outer_array_map SEC(".maps") = {58	.values = {59		[0] = &inner_map,60	},61};62 63static inline __u64 ptr_to_u64(const void *ptr)64{65	return (__u64) (unsigned long) ptr;66}67 68static int btf_load(void)69{70	struct btf_blob {71		struct btf_header btf_hdr;72		__u32 types[8];73		__u32 str;74	} raw_btf = {75		.btf_hdr = {76			.magic = BTF_MAGIC,77			.version = BTF_VERSION,78			.hdr_len = sizeof(struct btf_header),79			.type_len = sizeof(__u32) * 8,80			.str_off = sizeof(__u32) * 8,81			.str_len = sizeof(__u32),82		},83		.types = {84			/* long */85			BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),  /* [1] */86			/* unsigned long */87			BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),  /* [2] */88		},89	};90	static union bpf_attr btf_load_attr = {91		.btf_size = sizeof(raw_btf),92	};93 94	btf_load_attr.btf = (long)&raw_btf;95	return bpf_sys_bpf(BPF_BTF_LOAD, &btf_load_attr, sizeof(btf_load_attr));96}97 98SEC("syscall")99int load_prog(struct args *ctx)100{101	static char license[] = "GPL";102	static struct bpf_insn insns[] = {103		BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),104		BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),105		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),106		BPF_LD_MAP_FD(BPF_REG_1, 0),107		BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),108		BPF_MOV64_IMM(BPF_REG_0, 0),109		BPF_EXIT_INSN(),110	};111	static union bpf_attr map_create_attr = {112		.map_type = BPF_MAP_TYPE_HASH,113		.key_size = 8,114		.value_size = 8,115		.btf_key_type_id = 1,116		.btf_value_type_id = 2,117	};118	static union bpf_attr map_update_attr = { .map_fd = 1, };119	static __u64 key = 12;120	static __u64 value = 34;121	static union bpf_attr prog_load_attr = {122		.prog_type = BPF_PROG_TYPE_XDP,123		.insn_cnt = ARRAY_SIZE(insns),124	};125	int ret;126 127	ret = btf_load();128	if (ret <= 0)129		return ret;130 131	ctx->btf_fd = ret;132	map_create_attr.max_entries = ctx->max_entries;133	map_create_attr.btf_fd = ret;134 135	prog_load_attr.license = ptr_to_u64(license);136	prog_load_attr.insns = ptr_to_u64(insns);137	prog_load_attr.log_buf = ctx->log_buf;138	prog_load_attr.log_size = ctx->log_size;139	prog_load_attr.log_level = 1;140 141	ret = bpf_sys_bpf(BPF_MAP_CREATE, &map_create_attr, sizeof(map_create_attr));142	if (ret <= 0)143		return ret;144	ctx->map_fd = ret;145	insns[3].imm = ret;146 147	map_update_attr.map_fd = ret;148	map_update_attr.key = ptr_to_u64(&key);149	map_update_attr.value = ptr_to_u64(&value);150	ret = bpf_sys_bpf(BPF_MAP_UPDATE_ELEM, &map_update_attr, sizeof(map_update_attr));151	if (ret < 0)152		return ret;153 154	ret = bpf_sys_bpf(BPF_PROG_LOAD, &prog_load_attr, sizeof(prog_load_attr));155	if (ret <= 0)156		return ret;157	ctx->prog_fd = ret;158	return 1;159}160 161SEC("syscall")162int update_outer_map(void *ctx)163{164	int zero = 0, ret = 0, outer_fd = -1, inner_fd = -1, err;165	const int attr_sz = sizeof(union bpf_attr);166	union bpf_attr *attr;167 168	attr = bpf_map_lookup_elem((struct bpf_map *)&bpf_attr_array, &zero);169	if (!attr)170		goto out;171 172	memset(attr, 0, attr_sz);173	attr->map_id = ((struct bpf_map *)&outer_array_map)->id;174	outer_fd = bpf_sys_bpf(BPF_MAP_GET_FD_BY_ID, attr, attr_sz);175	if (outer_fd < 0)176		goto out;177 178	memset(attr, 0, attr_sz);179	attr->map_type = BPF_MAP_TYPE_ARRAY;180	attr->key_size = 4;181	attr->value_size = 4;182	attr->max_entries = 1;183	inner_fd = bpf_sys_bpf(BPF_MAP_CREATE, attr, attr_sz);184	if (inner_fd < 0)185		goto out;186 187	memset(attr, 0, attr_sz);188	attr->map_fd = outer_fd;189	attr->key = ptr_to_u64(&zero);190	attr->value = ptr_to_u64(&inner_fd);191	err = bpf_sys_bpf(BPF_MAP_UPDATE_ELEM, attr, attr_sz);192	if (err)193		goto out;194 195	memset(attr, 0, attr_sz);196	attr->map_fd = outer_fd;197	attr->key = ptr_to_u64(&zero);198	err = bpf_sys_bpf(BPF_MAP_DELETE_ELEM, attr, attr_sz);199	if (err)200		goto out;201	ret = 1;202out:203	if (inner_fd >= 0)204		bpf_sys_close(inner_fd);205	if (outer_fd >= 0)206		bpf_sys_close(outer_fd);207	return ret;208}209