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

Yonghong Song
2020-04-10T06:12:39Z

On 4/9/20 8:26 PM, Alexei Starovoitov wrote:
> 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.

Will do.