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

bpf-prologue.c (12225B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * bpf-prologue.c
      4 *
      5 * Copyright (C) 2015 He Kuang <hekuang@huawei.com>
      6 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
      7 * Copyright (C) 2015 Huawei Inc.
      8 */
      9
     10#include <bpf/libbpf.h>
     11#include "debug.h"
     12#include "bpf-loader.h"
     13#include "bpf-prologue.h"
     14#include "probe-finder.h"
     15#include <errno.h>
     16#include <stdlib.h>
     17#include <dwarf-regs.h>
     18#include <linux/filter.h>
     19
     20#define BPF_REG_SIZE		8
     21
     22#define JMP_TO_ERROR_CODE	-1
     23#define JMP_TO_SUCCESS_CODE	-2
     24#define JMP_TO_USER_CODE	-3
     25
     26struct bpf_insn_pos {
     27	struct bpf_insn *begin;
     28	struct bpf_insn *end;
     29	struct bpf_insn *pos;
     30};
     31
     32static inline int
     33pos_get_cnt(struct bpf_insn_pos *pos)
     34{
     35	return pos->pos - pos->begin;
     36}
     37
     38static int
     39append_insn(struct bpf_insn new_insn, struct bpf_insn_pos *pos)
     40{
     41	if (!pos->pos)
     42		return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
     43
     44	if (pos->pos + 1 >= pos->end) {
     45		pr_err("bpf prologue: prologue too long\n");
     46		pos->pos = NULL;
     47		return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
     48	}
     49
     50	*(pos->pos)++ = new_insn;
     51	return 0;
     52}
     53
     54static int
     55check_pos(struct bpf_insn_pos *pos)
     56{
     57	if (!pos->pos || pos->pos >= pos->end)
     58		return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
     59	return 0;
     60}
     61
     62/*
     63 * Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see
     64 * Documentation/trace/kprobetrace.rst) to size field of BPF_LDX_MEM
     65 * instruction (BPF_{B,H,W,DW}).
     66 */
     67static int
     68argtype_to_ldx_size(const char *type)
     69{
     70	int arg_size = type ? atoi(&type[1]) : 64;
     71
     72	switch (arg_size) {
     73	case 8:
     74		return BPF_B;
     75	case 16:
     76		return BPF_H;
     77	case 32:
     78		return BPF_W;
     79	case 64:
     80	default:
     81		return BPF_DW;
     82	}
     83}
     84
     85static const char *
     86insn_sz_to_str(int insn_sz)
     87{
     88	switch (insn_sz) {
     89	case BPF_B:
     90		return "BPF_B";
     91	case BPF_H:
     92		return "BPF_H";
     93	case BPF_W:
     94		return "BPF_W";
     95	case BPF_DW:
     96		return "BPF_DW";
     97	default:
     98		return "UNKNOWN";
     99	}
    100}
    101
    102/* Give it a shorter name */
    103#define ins(i, p) append_insn((i), (p))
    104
    105/*
    106 * Give a register name (in 'reg'), generate instruction to
    107 * load register into an eBPF register rd:
    108 *   'ldd target_reg, offset(ctx_reg)', where:
    109 * ctx_reg is pre initialized to pointer of 'struct pt_regs'.
    110 */
    111static int
    112gen_ldx_reg_from_ctx(struct bpf_insn_pos *pos, int ctx_reg,
    113		     const char *reg, int target_reg)
    114{
    115	int offset = regs_query_register_offset(reg);
    116
    117	if (offset < 0) {
    118		pr_err("bpf: prologue: failed to get register %s\n",
    119		       reg);
    120		return offset;
    121	}
    122	ins(BPF_LDX_MEM(BPF_DW, target_reg, ctx_reg, offset), pos);
    123
    124	return check_pos(pos);
    125}
    126
    127/*
    128 * Generate a BPF_FUNC_probe_read function call.
    129 *
    130 * src_base_addr_reg is a register holding base address,
    131 * dst_addr_reg is a register holding dest address (on stack),
    132 * result is:
    133 *
    134 *  *[dst_addr_reg] = *([src_base_addr_reg] + offset)
    135 *
    136 * Arguments of BPF_FUNC_probe_read:
    137 *     ARG1: ptr to stack (dest)
    138 *     ARG2: size (8)
    139 *     ARG3: unsafe ptr (src)
    140 */
    141static int
    142gen_read_mem(struct bpf_insn_pos *pos,
    143	     int src_base_addr_reg,
    144	     int dst_addr_reg,
    145	     long offset,
    146	     int probeid)
    147{
    148	/* mov arg3, src_base_addr_reg */
    149	if (src_base_addr_reg != BPF_REG_ARG3)
    150		ins(BPF_MOV64_REG(BPF_REG_ARG3, src_base_addr_reg), pos);
    151	/* add arg3, #offset */
    152	if (offset)
    153		ins(BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG3, offset), pos);
    154
    155	/* mov arg2, #reg_size */
    156	ins(BPF_ALU64_IMM(BPF_MOV, BPF_REG_ARG2, BPF_REG_SIZE), pos);
    157
    158	/* mov arg1, dst_addr_reg */
    159	if (dst_addr_reg != BPF_REG_ARG1)
    160		ins(BPF_MOV64_REG(BPF_REG_ARG1, dst_addr_reg), pos);
    161
    162	/* Call probe_read  */
    163	ins(BPF_EMIT_CALL(probeid), pos);
    164	/*
    165	 * Error processing: if read fail, goto error code,
    166	 * will be relocated. Target should be the start of
    167	 * error processing code.
    168	 */
    169	ins(BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, JMP_TO_ERROR_CODE),
    170	    pos);
    171
    172	return check_pos(pos);
    173}
    174
    175/*
    176 * Each arg should be bare register. Fetch and save them into argument
    177 * registers (r3 - r5).
    178 *
    179 * BPF_REG_1 should have been initialized with pointer to
    180 * 'struct pt_regs'.
    181 */
    182static int
    183gen_prologue_fastpath(struct bpf_insn_pos *pos,
    184		      struct probe_trace_arg *args, int nargs)
    185{
    186	int i, err = 0;
    187
    188	for (i = 0; i < nargs; i++) {
    189		err = gen_ldx_reg_from_ctx(pos, BPF_REG_1, args[i].value,
    190					   BPF_PROLOGUE_START_ARG_REG + i);
    191		if (err)
    192			goto errout;
    193	}
    194
    195	return check_pos(pos);
    196errout:
    197	return err;
    198}
    199
    200/*
    201 * Slow path:
    202 *   At least one argument has the form of 'offset($rx)'.
    203 *
    204 * Following code first stores them into stack, then loads all of then
    205 * to r2 - r5.
    206 * Before final loading, the final result should be:
    207 *
    208 * low address
    209 * BPF_REG_FP - 24  ARG3
    210 * BPF_REG_FP - 16  ARG2
    211 * BPF_REG_FP - 8   ARG1
    212 * BPF_REG_FP
    213 * high address
    214 *
    215 * For each argument (described as: offn(...off2(off1(reg)))),
    216 * generates following code:
    217 *
    218 *  r7 <- fp
    219 *  r7 <- r7 - stack_offset  // Ideal code should initialize r7 using
    220 *                           // fp before generating args. However,
    221 *                           // eBPF won't regard r7 as stack pointer
    222 *                           // if it is generated by minus 8 from
    223 *                           // another stack pointer except fp.
    224 *                           // This is why we have to set r7
    225 *                           // to fp for each variable.
    226 *  r3 <- value of 'reg'-> generated using gen_ldx_reg_from_ctx()
    227 *  (r7) <- r3       // skip following instructions for bare reg
    228 *  r3 <- r3 + off1  . // skip if off1 == 0
    229 *  r2 <- 8           \
    230 *  r1 <- r7           |-> generated by gen_read_mem()
    231 *  call probe_read    /
    232 *  jnei r0, 0, err  ./
    233 *  r3 <- (r7)
    234 *  r3 <- r3 + off2  . // skip if off2 == 0
    235 *  r2 <- 8           \  // r2 may be broken by probe_read, so set again
    236 *  r1 <- r7           |-> generated by gen_read_mem()
    237 *  call probe_read    /
    238 *  jnei r0, 0, err  ./
    239 *  ...
    240 */
    241static int
    242gen_prologue_slowpath(struct bpf_insn_pos *pos,
    243		      struct probe_trace_arg *args, int nargs)
    244{
    245	int err, i, probeid;
    246
    247	for (i = 0; i < nargs; i++) {
    248		struct probe_trace_arg *arg = &args[i];
    249		const char *reg = arg->value;
    250		struct probe_trace_arg_ref *ref = NULL;
    251		int stack_offset = (i + 1) * -8;
    252
    253		pr_debug("prologue: fetch arg %d, base reg is %s\n",
    254			 i, reg);
    255
    256		/* value of base register is stored into ARG3 */
    257		err = gen_ldx_reg_from_ctx(pos, BPF_REG_CTX, reg,
    258					   BPF_REG_ARG3);
    259		if (err) {
    260			pr_err("prologue: failed to get offset of register %s\n",
    261			       reg);
    262			goto errout;
    263		}
    264
    265		/* Make r7 the stack pointer. */
    266		ins(BPF_MOV64_REG(BPF_REG_7, BPF_REG_FP), pos);
    267		/* r7 += -8 */
    268		ins(BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, stack_offset), pos);
    269		/*
    270		 * Store r3 (base register) onto stack
    271		 * Ensure fp[offset] is set.
    272		 * fp is the only valid base register when storing
    273		 * into stack. We are not allowed to use r7 as base
    274		 * register here.
    275		 */
    276		ins(BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_ARG3,
    277				stack_offset), pos);
    278
    279		ref = arg->ref;
    280		probeid = BPF_FUNC_probe_read_kernel;
    281		while (ref) {
    282			pr_debug("prologue: arg %d: offset %ld\n",
    283				 i, ref->offset);
    284
    285			if (ref->user_access)
    286				probeid = BPF_FUNC_probe_read_user;
    287
    288			err = gen_read_mem(pos, BPF_REG_3, BPF_REG_7,
    289					   ref->offset, probeid);
    290			if (err) {
    291				pr_err("prologue: failed to generate probe_read function call\n");
    292				goto errout;
    293			}
    294
    295			ref = ref->next;
    296			/*
    297			 * Load previous result into ARG3. Use
    298			 * BPF_REG_FP instead of r7 because verifier
    299			 * allows FP based addressing only.
    300			 */
    301			if (ref)
    302				ins(BPF_LDX_MEM(BPF_DW, BPF_REG_ARG3,
    303						BPF_REG_FP, stack_offset), pos);
    304		}
    305	}
    306
    307	/* Final pass: read to registers */
    308	for (i = 0; i < nargs; i++) {
    309		int insn_sz = (args[i].ref) ? argtype_to_ldx_size(args[i].type) : BPF_DW;
    310
    311		pr_debug("prologue: load arg %d, insn_sz is %s\n",
    312			 i, insn_sz_to_str(insn_sz));
    313		ins(BPF_LDX_MEM(insn_sz, BPF_PROLOGUE_START_ARG_REG + i,
    314				BPF_REG_FP, -BPF_REG_SIZE * (i + 1)), pos);
    315	}
    316
    317	ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_SUCCESS_CODE), pos);
    318
    319	return check_pos(pos);
    320errout:
    321	return err;
    322}
    323
    324static int
    325prologue_relocate(struct bpf_insn_pos *pos, struct bpf_insn *error_code,
    326		  struct bpf_insn *success_code, struct bpf_insn *user_code)
    327{
    328	struct bpf_insn *insn;
    329
    330	if (check_pos(pos))
    331		return -BPF_LOADER_ERRNO__PROLOGUE2BIG;
    332
    333	for (insn = pos->begin; insn < pos->pos; insn++) {
    334		struct bpf_insn *target;
    335		u8 class = BPF_CLASS(insn->code);
    336		u8 opcode;
    337
    338		if (class != BPF_JMP)
    339			continue;
    340		opcode = BPF_OP(insn->code);
    341		if (opcode == BPF_CALL)
    342			continue;
    343
    344		switch (insn->off) {
    345		case JMP_TO_ERROR_CODE:
    346			target = error_code;
    347			break;
    348		case JMP_TO_SUCCESS_CODE:
    349			target = success_code;
    350			break;
    351		case JMP_TO_USER_CODE:
    352			target = user_code;
    353			break;
    354		default:
    355			pr_err("bpf prologue: internal error: relocation failed\n");
    356			return -BPF_LOADER_ERRNO__PROLOGUE;
    357		}
    358
    359		insn->off = target - (insn + 1);
    360	}
    361	return 0;
    362}
    363
    364int bpf__gen_prologue(struct probe_trace_arg *args, int nargs,
    365		      struct bpf_insn *new_prog, size_t *new_cnt,
    366		      size_t cnt_space)
    367{
    368	struct bpf_insn *success_code = NULL;
    369	struct bpf_insn *error_code = NULL;
    370	struct bpf_insn *user_code = NULL;
    371	struct bpf_insn_pos pos;
    372	bool fastpath = true;
    373	int err = 0, i;
    374
    375	if (!new_prog || !new_cnt)
    376		return -EINVAL;
    377
    378	if (cnt_space > BPF_MAXINSNS)
    379		cnt_space = BPF_MAXINSNS;
    380
    381	pos.begin = new_prog;
    382	pos.end = new_prog + cnt_space;
    383	pos.pos = new_prog;
    384
    385	if (!nargs) {
    386		ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 0),
    387		    &pos);
    388
    389		if (check_pos(&pos))
    390			goto errout;
    391
    392		*new_cnt = pos_get_cnt(&pos);
    393		return 0;
    394	}
    395
    396	if (nargs > BPF_PROLOGUE_MAX_ARGS) {
    397		pr_warning("bpf: prologue: %d arguments are dropped\n",
    398			   nargs - BPF_PROLOGUE_MAX_ARGS);
    399		nargs = BPF_PROLOGUE_MAX_ARGS;
    400	}
    401
    402	/* First pass: validation */
    403	for (i = 0; i < nargs; i++) {
    404		struct probe_trace_arg_ref *ref = args[i].ref;
    405
    406		if (args[i].value[0] == '@') {
    407			/* TODO: fetch global variable */
    408			pr_err("bpf: prologue: global %s%+ld not support\n",
    409				args[i].value, ref ? ref->offset : 0);
    410			return -ENOTSUP;
    411		}
    412
    413		while (ref) {
    414			/* fastpath is true if all args has ref == NULL */
    415			fastpath = false;
    416
    417			/*
    418			 * Instruction encodes immediate value using
    419			 * s32, ref->offset is long. On systems which
    420			 * can't fill long in s32, refuse to process if
    421			 * ref->offset too large (or small).
    422			 */
    423#ifdef __LP64__
    424#define OFFSET_MAX	((1LL << 31) - 1)
    425#define OFFSET_MIN	((1LL << 31) * -1)
    426			if (ref->offset > OFFSET_MAX ||
    427					ref->offset < OFFSET_MIN) {
    428				pr_err("bpf: prologue: offset out of bound: %ld\n",
    429				       ref->offset);
    430				return -BPF_LOADER_ERRNO__PROLOGUEOOB;
    431			}
    432#endif
    433			ref = ref->next;
    434		}
    435	}
    436	pr_debug("prologue: pass validation\n");
    437
    438	if (fastpath) {
    439		/* If all variables are registers... */
    440		pr_debug("prologue: fast path\n");
    441		err = gen_prologue_fastpath(&pos, args, nargs);
    442		if (err)
    443			goto errout;
    444	} else {
    445		pr_debug("prologue: slow path\n");
    446
    447		/* Initialization: move ctx to a callee saved register. */
    448		ins(BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1), &pos);
    449
    450		err = gen_prologue_slowpath(&pos, args, nargs);
    451		if (err)
    452			goto errout;
    453		/*
    454		 * start of ERROR_CODE (only slow pass needs error code)
    455		 *   mov r2 <- 1  // r2 is error number
    456		 *   mov r3 <- 0  // r3, r4... should be touched or
    457		 *                // verifier would complain
    458		 *   mov r4 <- 0
    459		 *   ...
    460		 *   goto usercode
    461		 */
    462		error_code = pos.pos;
    463		ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 1),
    464		    &pos);
    465
    466		for (i = 0; i < nargs; i++)
    467			ins(BPF_ALU64_IMM(BPF_MOV,
    468					  BPF_PROLOGUE_START_ARG_REG + i,
    469					  0),
    470			    &pos);
    471		ins(BPF_JMP_IMM(BPF_JA, BPF_REG_0, 0, JMP_TO_USER_CODE),
    472				&pos);
    473	}
    474
    475	/*
    476	 * start of SUCCESS_CODE:
    477	 *   mov r2 <- 0
    478	 *   goto usercode  // skip
    479	 */
    480	success_code = pos.pos;
    481	ins(BPF_ALU64_IMM(BPF_MOV, BPF_PROLOGUE_FETCH_RESULT_REG, 0), &pos);
    482
    483	/*
    484	 * start of USER_CODE:
    485	 *   Restore ctx to r1
    486	 */
    487	user_code = pos.pos;
    488	if (!fastpath) {
    489		/*
    490		 * Only slow path needs restoring of ctx. In fast path,
    491		 * register are loaded directly from r1.
    492		 */
    493		ins(BPF_MOV64_REG(BPF_REG_ARG1, BPF_REG_CTX), &pos);
    494		err = prologue_relocate(&pos, error_code, success_code,
    495					user_code);
    496		if (err)
    497			goto errout;
    498	}
    499
    500	err = check_pos(&pos);
    501	if (err)
    502		goto errout;
    503
    504	*new_cnt = pos_get_cnt(&pos);
    505	return 0;
    506errout:
    507	return err;
    508}