Re: [RFC PATCH bpf-next 09/16] bpf: add bpf_seq_printf and bpf_seq_write helpers

Alexei Starovoitov
2020-04-10T03:26:12Z

On Wed, Apr 08, 2020 at 04:25:31PM -0700, Yonghong Song wrote:
>
> +BPF_CALL_5(bpf_seq_printf, struct seq_file *, m, char *, fmt, u32, fmt_size, u64, arg1,
> + u64, arg2)
> +{
> + bool buf_used = false;
> + int i, copy_size;
> + int mod[2] = {};
> + int fmt_cnt = 0;
> + u64 unsafe_addr;
> + char buf[64];
> +
> + /*
> + * bpf_check()->check_func_arg()->check_stack_boundary()
> + * guarantees that fmt points to bpf program stack,
> + * fmt_size bytes of it were initialized and fmt_size > 0
> + */
> + if (fmt[--fmt_size] != 0)
> + return -EINVAL;
...
> +/* Horrid workaround for getting va_list handling working with different
> + * argument type combinations generically for 32 and 64 bit archs.
> + */
> +#define __BPF_SP_EMIT() __BPF_ARG2_SP()
> +#define __BPF_SP(...) \
> + seq_printf(m, fmt, ##__VA_ARGS__)
> +
> +#define __BPF_ARG1_SP(...) \
> + ((mod[0] == 2 || (mod[0] == 1 && __BITS_PER_LONG == 64)) \
> + ? __BPF_SP(arg1, ##__VA_ARGS__) \
> + : ((mod[0] == 1 || (mod[0] == 0 && __BITS_PER_LONG == 32)) \
> + ? __BPF_SP((long)arg1, ##__VA_ARGS__) \
> + : __BPF_SP((u32)arg1, ##__VA_ARGS__)))
> +
> +#define __BPF_ARG2_SP(...) \
> + ((mod[1] == 2 || (mod[1] == 1 && __BITS_PER_LONG == 64)) \
> + ? __BPF_ARG1_SP(arg2, ##__VA_ARGS__) \
> + : ((mod[1] == 1 || (mod[1] == 0 && __BITS_PER_LONG == 32)) \
> + ? __BPF_ARG1_SP((long)arg2, ##__VA_ARGS__) \
> + : __BPF_ARG1_SP((u32)arg2, ##__VA_ARGS__)))
> +
> + __BPF_SP_EMIT();
> + return seq_has_overflowed(m);
> +}

This function is mostly a copy-paste of bpf_trace_printk() with difference
of printing via seq_printf vs __trace_printk.
Please find a way to share the code.