[LTP] [PATCH v2 4/5] bpf: Add bpf_insn_buf, map and instruction concatenation helpers

Cyril Hrubis chrubis@suse.cz
Fri Apr 30 10:44:25 CEST 2021


Hi!
> Add helpers for building up programs. Tests before bpf_prog05 have not
> been updated to use this for two reasons.
> 
> 1. Some apply offsets to the map pointer returned or jump to the end
>    of the program instead of just over an immediate exit
>    instruction. Either way modifying them would require testing they
>    still reproduce the bug.
> 
> 2. Some have a lot of comments describing the program which is useful
>    to learn from. These would need to be moved.
> 
> Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com>
> ---
>  testcases/kernel/syscalls/bpf/bpf_common.c | 40 ++++++++++++++++++++++
>  testcases/kernel/syscalls/bpf/bpf_common.h | 12 +++++++
>  2 files changed, 52 insertions(+)
> 
> diff --git a/testcases/kernel/syscalls/bpf/bpf_common.c b/testcases/kernel/syscalls/bpf/bpf_common.c
> index b5337c22a..d80ed91bb 100644
> --- a/testcases/kernel/syscalls/bpf/bpf_common.c
> +++ b/testcases/kernel/syscalls/bpf/bpf_common.c
> @@ -82,6 +82,46 @@ long bpf_map_array_get(const int map_fd,
>  	return TST_RET;
>  }
>  
> +void bpf_insn_buf_cat(struct bpf_insn_buf *const self,
> +		      const struct bpf_insn *const insn_to_cat,
> +		      const size_t insn_to_cat_len)
> +{
> +	memcpy(((char *)self->insn) + self->byte_len,
> +	       insn_to_cat, insn_to_cat_len);
> +	self->byte_len += insn_to_cat_len;
> +}
> +
> +/* map[array_indx] = reg_to_save
> + *
> + * Inserts the following into insn_out.
> + *
> + * r1 = map_fd
> + * r2 = fp
> + * r2 = r2 - 4
> + * r2 = array_indx
> + * call map_lookup_elem(r1, r2)
> + * if r0 != 0 goto pc+1
> + * exit
> + * *r0 = reg_to_save
> + *
> + */
> + void bpf_insn_buf_array_set(struct bpf_insn_buf *const self, const int map_fd,
> +			     const uint32_t array_indx, const uint8_t reg_to_save)
> +{
> +	const struct bpf_insn map_insn[] = {
> +		BPF_LD_MAP_FD(BPF_REG_1, map_fd),
> +		BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
> +		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
> +		BPF_ST_MEM(BPF_W, BPF_REG_2, 0, array_indx),
> +		BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
> +		BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
> +		BPF_EXIT_INSN(),
> +		BPF_STX_MEM(BPF_DW, BPF_REG_0, reg_to_save, 0),
> +	};

I'm wondering if it would be easier to write a macro that would produce
this code, something as:

	#define BPF_ARRAY_STORE(map_fd, arr_idx, reg_to_save) \
		BPF_LD_MAP_FD(BPF_REG_1, map_fd), \
		BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), \
		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), \
		BPF_ST_MEM(BPF_W, BPF_REG_2, 0, arr_indx), \
		BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), \
		BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1), \
		BPF_EXIT_INSN(), \
		BPF_STX_MEM(BPF_DW, BPF_REG_0, reg_to_save, 0)


Then we can use this piece as any other macros when constructing the
program, the only difference is that this macro emits 8 instructions
instead of one.

What do you think?

> +	bpf_insn_buf_cat(self, map_insn, sizeof(map_insn));
> +}
> +
>  void bpf_init_prog_attr(union bpf_attr *attr, const struct bpf_insn *prog,
>  	size_t prog_size, char *log_buf, size_t log_size)
>  {
> diff --git a/testcases/kernel/syscalls/bpf/bpf_common.h b/testcases/kernel/syscalls/bpf/bpf_common.h
> index 9e9935c2c..10b1eee86 100644
> --- a/testcases/kernel/syscalls/bpf/bpf_common.h
> +++ b/testcases/kernel/syscalls/bpf/bpf_common.h
> @@ -13,6 +13,11 @@
>  
>  #define BPF_MEMLOCK_ADD (2*1024*1024)
>  
> +struct bpf_insn_buf {
> +	size_t byte_len;
> +	struct bpf_insn insn[BPF_MAXINSNS];
> +};
> +
>  void rlimit_bump_memlock(void);
>  int bpf_map_create(union bpf_attr *attr);
>  int bpf_map_array_create(uint32_t max_entries);
> @@ -20,6 +25,13 @@ long bpf_map_array_get(const int map_fd,
>  		       const uint32_t *const array_indx,
>  		       uint64_t *const array_val);
>  
> +void bpf_insn_buf_cat(struct bpf_insn_buf *const self,
> +		      const struct bpf_insn *const insn_to_cat,
> +		      const size_t insn_to_cat_len);
> +void bpf_insn_buf_array_set(struct bpf_insn_buf *const self,
> +			    const int map_fd,
> +			    const uint32_t array_indx, const uint8_t reg_to_save);
> +
>  void bpf_init_prog_attr(union bpf_attr *attr, const struct bpf_insn *prog,
>  			size_t prog_size, char *log_buf, size_t log_size);
>  int bpf_load_prog(union bpf_attr *attr, const char *log);
> -- 
> 2.31.1
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp

-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list