bpf: Remove struct bpf_verifier_env argument from print_bpf_insn
Subsystems (5)
Jiri Olsa
reviewerPATCH 1/2 bpf: Remove struct bpf_verifier_env argument from print_bpf_insn
We use print_bpf_insn in user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel struct bpf_verifier_env argument.
This argument can be safely removed, because its users can use the struct bpf_insn_cbs::private_data to pass it.
--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)
kernel/bpf/disasm.c +26 -26
@@ -113,16 +113,16 @@ static const char *const bpf_jmp_string[16] = { };static void print_bpf_end_insn (bpf_insn_print_t verbose, -struct bpf_verifier_env *env, +void *private_data,const struct bpf_insn *insn) { -verbose (env,"(%02x) r%d = %s%d r%d\n" , insn->code, insn->dst_reg, +verbose (private_data,"(%02x) r%d = %s%d r%d\n" , + insn->code, insn->dst_reg,BPF_SRC (insn->code) ==BPF_TO_BE ?"be" :"le" , insn->imm, insn->dst_reg); }void print_bpf_insn (const struct bpf_insn_cbs *cbs, -struct bpf_verifier_env *env,const struct bpf_insn *insn,bool allow_ptr_leaks) {
@@ -132,23 +132,23 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,if (class ==BPF_ALU || class ==BPF_ALU64 ) {if (BPF_OP (insn->code) ==BPF_END ) {if (class ==BPF_ALU64 ) -verbose (env,"BUG_alu64_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_alu64_%02x\n" , insn->code);else -print_bpf_end_insn (verbose, env, insn); +print_bpf_end_insn (verbose, cbs->private_data, insn); }else if (BPF_OP (insn->code) ==BPF_NEG ) { -verbose (env,"(%02x) r%d = %s-r%d\n" , +verbose (cbs->private_data,"(%02x) r%d = %s-r%d\n" , insn->code, insn->dst_reg, class ==BPF_ALU ?"(u32) " :"" , insn->dst_reg); }else if (BPF_SRC (insn->code) ==BPF_X ) { -verbose (env,"(%02x) %sr%d %s %sr%d\n" , +verbose (cbs->private_data,"(%02x) %sr%d %s %sr%d\n" , insn->code, class ==BPF_ALU ?"(u32) " :"" , insn->dst_reg, bpf_alu_string[BPF_OP (insn->code) >>4 ], class ==BPF_ALU ?"(u32) " :"" , insn->src_reg); }else { - verbose(env, "(%02x) %sr%d %s %s%d\n", + verbose(cbs->private_data, "(%02x) %sr%d %s %s%d\n", insn->code, class == BPF_ALU ? "(u32) " : "", insn->dst_reg, bpf_alu_string[BPF_OP(insn->code) >> 4],
@@ -157,46 +157,46 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, } }else if (class ==BPF_STX ) {if (BPF_MODE (insn->code) ==BPF_MEM ) -verbose (env,"(%02x) *(%s *)(r%d %+d) = r%d\n" , +verbose (cbs->private_data,"(%02x) *(%s *)(r%d %+d) = r%d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->src_reg);else if (BPF_MODE (insn->code) ==BPF_XADD ) -verbose (env,"(%02x) lock *(%s *)(r%d %+d) += r%d\n" , +verbose (cbs->private_data,"(%02x) lock *(%s *)(r%d %+d) += r%d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->src_reg);else -verbose (env,"BUG_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_%02x\n" , insn->code); }else if (class ==BPF_ST ) {if (BPF_MODE (insn->code) !=BPF_MEM ) { -verbose (env,"BUG_st_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_st_%02x\n" , insn->code);return ; } -verbose (env,"(%02x) *(%s *)(r%d %+d) = %d\n" , +verbose (cbs->private_data,"(%02x) *(%s *)(r%d %+d) = %d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->imm); }else if (class ==BPF_LDX ) {if (BPF_MODE (insn->code) !=BPF_MEM ) { -verbose (env,"BUG_ldx_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_ldx_%02x\n" , insn->code);return ; } -verbose (env,"(%02x) r%d = *(%s *)(r%d %+d)\n" , +verbose (cbs->private_data,"(%02x) r%d = *(%s *)(r%d %+d)\n" , insn->code, insn->dst_reg, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->src_reg, insn->off); }else if (class ==BPF_LD ) {if (BPF_MODE (insn->code) ==BPF_ABS ) { -verbose (env,"(%02x) r0 = *(%s *)skb[%d]\n" , +verbose (cbs->private_data,"(%02x) r0 = *(%s *)skb[%d]\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->imm); }else if (BPF_MODE (insn->code) ==BPF_IND ) { -verbose (env,"(%02x) r0 = *(%s *)skb[r%d + %d]\n" , +verbose (cbs->private_data,"(%02x) r0 = *(%s *)skb[r%d + %d]\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->src_reg, insn->imm);
@@ -212,12 +212,12 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,if (map_ptr && !allow_ptr_leaks) imm =0 ; -verbose (env,"(%02x) r%d = %s\n" , +verbose (cbs->private_data,"(%02x) r%d = %s\n" , insn->code, insn->dst_reg,__func_imm_name (cbs, insn, imm, tmp,sizeof (tmp))); }else { -verbose (env,"BUG_ld_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_ld_%02x\n" , insn->code);return ; } }else if (class ==BPF_JMP ) {
@@ -227,35 +227,35 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,char tmp[64 ];if (insn->src_reg ==BPF_PSEUDO_CALL ) { -verbose (env,"(%02x) call pc%s\n" , +verbose (cbs->private_data,"(%02x) call pc%s\n" , insn->code,__func_get_name (cbs, insn, tmp,sizeof (tmp))); }else {strcpy (tmp,"unknown" ); -verbose (env,"(%02x) call %s#%d\n" , insn->code, +verbose (cbs->private_data,"(%02x) call %s#%d\n" , insn->code,__func_get_name (cbs, insn, tmp,sizeof (tmp)), insn->imm); } }else if (insn->code == (BPF_JMP |BPF_JA )) { -verbose (env,"(%02x) goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) goto pc%+d\n" , insn->code, insn->off); }else if (insn->code == (BPF_JMP |BPF_EXIT )) { -verbose (env,"(%02x) exit\n" , insn->code); +verbose (cbs->private_data,"(%02x) exit\n" , insn->code); }else if (BPF_SRC (insn->code) ==BPF_X ) { -verbose (env,"(%02x) if r%d %s r%d goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) if r%d %s r%d goto pc%+d\n" , insn->code, insn->dst_reg, bpf_jmp_string[BPF_OP (insn->code) >>4 ], insn->src_reg, insn->off); }else { -verbose (env,"(%02x) if r%d %s 0x%x goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) if r%d %s 0x%x goto pc%+d\n" , insn->code, insn->dst_reg, bpf_jmp_string[BPF_OP (insn->code) >>4 ], insn->imm, insn->off); } }else { -verbose (env,"(%02x) %s\n" , +verbose (cbs->private_data,"(%02x) %s\n" , insn->code, bpf_class_string[class]); } }
kernel/bpf/disasm.h +1 -4
@@ -22,14 +22,12 @@#include <string.h> #endif -struct bpf_verifier_env ; -extern const char *const bpf_alu_string[16 ];extern const char *const bpf_class_string[8 ];const char *func_id_name (int id); -typedef __printf(2, 3) void (*bpf_insn_print_t)(struct bpf_verifier_env *env, +typedef __printf(2, 3) void (*bpf_insn_print_t)(void *private_data, const char *, ...); typedef const char *(*bpf_insn_revmap_call_t)(void *private_data, const struct bpf_insn *insn);
@@ -45,7 +43,6 @@ struct bpf_insn_cbs { };void print_bpf_insn (const struct bpf_insn_cbs *cbs, -struct bpf_verifier_env *env,const struct bpf_insn *insn,bool allow_ptr_leaks);#endif
kernel/bpf/verifier.c +3 -3
@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env, - const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));static bool type_is_pkt_pointer (enum bpf_reg_type type)
@@ -4601,10 +4600,11 @@ static int do_check(struct bpf_verifier_env *env)if (env->log.level) {const struct bpf_insn_cbs cbs = { .cb_print = verbose, + .private_data = env, };verbose (env,"%d: " , insn_idx); -print_bpf_insn (&cbs, env, insn, env->allow_ptr_leaks); +print_bpf_insn (&cbs, insn, env->allow_ptr_leaks); }if (bpf_prog_is_dev_bound (env->prog->aux)) {
Signature · 1 line
2.13.6
Jiri Olsa
reviewerPATCH 2/2 bpftool: Adjust to new print_bpf_insn interface
Change bpftool to skip the removed struct bpf_verifier_env argument in print_bpf_insn. It was passed as NULL anyway.
No functional change intended.
--- tools/bpf/bpftool/prog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/bpf/bpftool/prog.c +4 -4
@@ -489,7 +489,7 @@ static struct kernel_sym *kernel_syms_search(struct dump_data *dd, sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL; } -static void print_insn (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn (void *private_data,const char *fmt, ...) {va_list args;
@@ -576,7 +576,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );printf ("% 4d: " , i); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {printf (" " );
@@ -590,7 +590,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, } } -static void print_insn_json (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn_json (void *private_data,const char *fmt, ...) {unsigned int l =strlen (fmt);char chomped_fmt[l];
@@ -628,7 +628,7 @@ static void dump_xlated_json(struct dump_data *dd, void *buf,jsonw_start_object (json_wtr);jsonw_name (json_wtr,"disasm" ); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {jsonw_name (json_wtr,"opcodes" );
Signature · 1 line
2.13.6
Re: [PATCH 2/2] bpftool: Adjust to new print_bpf_insn interface
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 43 lines
Change bpftool to skip the removed struct
bpf_verifier_envargument inprint_bpf_insn. It was passed as NULL anyway.No functional change intended.
Signed-off-by Jiri Olsa <[email protected]>--- tools/bpf/bpftool/prog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)tools/bpf/bpftool/prog.c +3
-3@@ -489,7 +489,7 @@ static struct kernel_sym *kernel_syms_search(struct dump_data *dd, sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL; } -static void print_insn (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn (void *private_data,const char *fmt, ...) {va_list args;@@ -576,7 +576,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );printf ("% 4d: " , i); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {printf (" " );@@ -590,7 +590,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, } } -static void print_insn_json (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn_json (void *private_data,const char *fmt, ...) {unsigned int l =strlen (fmt);char chomped_fmt[l];
tools/bpf/bpftool/prog.c static void dump_xlated_json(struct dump_data *dd, void *buf, · line 634
Quoted 8 lines
tools/bpf/bpftool/prog.c +1
-1@@ -628,7 +628,7 @@ static void dump_xlated_json(struct dump_data *dd, void *buf,jsonw_start_object (json_wtr);jsonw_name (json_wtr,"disasm" ); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {jsonw_name (json_wtr,"opcodes" );
Hi Jiri, this code has changed in the tree. It was moved to tools/bpf/bpftool/xlated_dumper.c, and there is now a third function to
update: print_insn_for_graph(). Could you please rebase the patch?
Quentin
Re: [PATCH 2/2] bpftool: Adjust to new print_bpf_insn interface
Quoted 49 lines · Quentin Monnet
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 48 lines
Change bpftool to skip the removed struct
bpf_verifier_envargument inprint_bpf_insn. It was passed as NULL anyway.No functional change intended.
Signed-off-by Jiri Olsa <[email protected]>--- tools/bpf/bpftool/prog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)tools/bpf/bpftool/prog.c +4
-4@@ -489,7 +489,7 @@ static struct kernel_sym *kernel_syms_search(struct dump_data *dd, sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL; } -static void print_insn (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn (void *private_data,const char *fmt, ...) {va_list args;@@ -576,7 +576,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );printf ("% 4d: " , i); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {printf (" " );@@ -590,7 +590,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, } } -static void print_insn_json (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn_json (void *private_data,const char *fmt, ...) {unsigned int l =strlen (fmt);char chomped_fmt[l];@@ -628,7 +628,7 @@ static void dump_xlated_json(struct dump_data *dd, void *buf,jsonw_start_object (json_wtr);jsonw_name (json_wtr,"disasm" ); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);
Quoted 7 lines
tools/bpf/bpftool/prog.c static void dump_xlated_json(struct dump_data *dd, void *buf, · line 634
Quoted 3 lines
tools/bpf/bpftool/prog.c +0
-0if (opcodes) {jsonw_name (json_wtr,"opcodes" );Hi Jiri, this code has changed in the tree. It was moved to
tools/bpf/bpftool/xlated_dumper.c, and there is now a third function to
update:print_insn_for_graph(). Could you please rebase the patch?
sure.. I was over perf tree, I'll check on bpf tree
thanks,
jirka
Daniel Borkmann
maintainerRe: [PATCH 2/2] bpftool: Adjust to new print_bpf_insn interface
Quoted 58 lines · Jiri Olsa
Quoted 49 lines · Quentin Monnet
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 48 lines
Change bpftool to skip the removed struct
bpf_verifier_envargument inprint_bpf_insn. It was passed as NULL anyway.No functional change intended.
Signed-off-by Jiri Olsa <[email protected]>--- tools/bpf/bpftool/prog.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)tools/bpf/bpftool/prog.c +4
-4@@ -489,7 +489,7 @@ static struct kernel_sym *kernel_syms_search(struct dump_data *dd, sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL; } -static void print_insn (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn (void *private_data,const char *fmt, ...) {va_list args;@@ -576,7 +576,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );printf ("% 4d: " , i); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {printf (" " );@@ -590,7 +590,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf, } } -static void print_insn_json (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn_json (void *private_data,const char *fmt, ...) {unsigned int l =strlen (fmt);char chomped_fmt[l];@@ -628,7 +628,7 @@ static void dump_xlated_json(struct dump_data *dd, void *buf,jsonw_start_object (json_wtr);jsonw_name (json_wtr,"disasm" ); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);Quoted 7 lines
tools/bpf/bpftool/prog.c static void dump_xlated_json(struct dump_data *dd, void *buf, · line 634
Quoted 3 lines
tools/bpf/bpftool/prog.c +0
-0if (opcodes) {jsonw_name (json_wtr,"opcodes" );Hi Jiri, this code has changed in the tree. It was moved to
tools/bpf/bpftool/xlated_dumper.c, and there is now a third function to
update:print_insn_for_graph(). Could you please rebase the patch?
Quoted 1 line
sure.. I was over perf tree, I'll check on bpf tree
Just to be sure, it should be bpf-next. bpf is for fixes only.
Thanks,
Daniel
PATCH v2 2/2 bpftool: Adjust to new print_bpf_insn interface
On Wed, Mar 21, 2018 at 05:44:52PM +0100, Daniel Borkmann wrote:
SNIP
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hi Jiri, this code has changed in the tree. It was moved to
tools/bpf/bpftool/xlated_dumper.c, and there is now a third function to
update:print_insn_for_graph(). Could you please rebase the patch?sure.. I was over perf tree, I'll check on bpf tree
Just to be sure, it should be bpf-next. bpf is for fixes only.
v2 attached
thanks,
jirka
---
Change bpftool to skip the removed struct bpf_verifier_env argument in print_bpf_insn. It was passed as NULL anyway.
No functional change intended.
--- tools/bpf/bpftool/xlated_dumper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
tools/bpf/bpftool/xlated_dumper.c +6 -6
@@ -114,7 +114,7 @@ static struct kernel_sym *kernel_syms_search(struct dump_data *dd, sizeof(*dd->sym_mapping), kernel_syms_cmp) : NULL; } -static void print_insn (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn (void *private_data,const char *fmt, ...) {va_list args;
@@ -124,7 +124,7 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...) }static void -print_insn_for_graph (struct bpf_verifier_env *env,const char *fmt, ...) +print_insn_for_graph (void *private_data,const char *fmt, ...) {char buf[64 ], *p;va_list args;
@@ -154,7 +154,7 @@ print_insn_for_graph(struct bpf_verifier_env *env, const char *fmt, ...)printf ("%s" , buf); } -static void print_insn_json (struct bpf_verifier_env *env,const char *fmt, ...) +static void print_insn_json (void *private_data,const char *fmt, ...) {unsigned int l =strlen (fmt);char chomped_fmt[l];
@@ -248,7 +248,7 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len,jsonw_start_object (json_wtr);jsonw_name (json_wtr,"disasm" ); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {jsonw_name (json_wtr,"opcodes" );
@@ -302,7 +302,7 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );printf ("% 4d: " , i); -print_bpf_insn (&cbs,NULL , insn + i, true); +print_bpf_insn (&cbs, insn + i, true);if (opcodes) {printf (" " );
@@ -331,7 +331,7 @@ void dump_xlated_for_graph(struct dump_data *dd, void *buf_start, void *buf_end,for (; cur <= insn_end; cur++) {printf ("% 4d: " , (int )(cur - insn_start + start_idx)); -print_bpf_insn (&cbs,NULL , cur, true); +print_bpf_insn (&cbs, cur, true);if (cur != insn_end)printf (" | " ); }
Signature · 1 line
2.13.6
Re: [PATCHv2 2/2] bpftool: Adjust to new print_bpf_insn interface
2018-03-21 18:00 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 22 lines · Daniel Borkmann
SNIP
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Hi Jiri, this code has changed in the tree. It was moved to
tools/bpf/bpftool/xlated_dumper.c, and there is now a third function to
update:print_insn_for_graph(). Could you please rebase the patch?sure.. I was over perf tree, I'll check on bpf tree
Just to be sure, it should be bpf-next. bpf is for fixes only.
v2 attached
thanks,
jirka---
Change bpftool to skip the removed structbpf_verifier_envargument inprint_bpf_insn. It was passed as NULL anyway.
Quoted 7 lines
No functional change intended.
Signed-off-by Jiri Olsa <[email protected]>--- tools/bpf/bpftool/xlated_dumper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
Thank you!
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 14 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)
[...]
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 12 lines
kernel/bpf/verifier.c +1
-2@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env, - const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));
Just as a note, verbose() will be aliased to a function whose prototype differs (bpf_verifier_log_write() still expects a struct bpf_verifier_env as its first argument). I am not so familiar with function aliases, could this change be a concern?
Other than this the patch seems good to me.
Quentin
Quoted 16 lines
kernel/bpf/verifier.c +2
-1static bool type_is_pkt_pointer (enum bpf_reg_type type)@@ -4601,10 +4600,11 @@ static int do_check(struct bpf_verifier_env *env)if (env->log.level) {const struct bpf_insn_cbs cbs = { .cb_print = verbose, + .private_data = env, };verbose (env,"%d: " , insn_idx); -print_bpf_insn (&cbs, env, insn, env->allow_ptr_leaks); +print_bpf_insn (&cbs, insn, env->allow_ptr_leaks); }if (bpf_prog_is_dev_bound (env->prog->aux)) {
Quoted 27 lines · Quentin Monnet
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 14 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)[...]
Quoted 9 lines
kernel/bpf/verifier.c +0
-1@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env,
Quoted 8 lines
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 3 lines
kernel/bpf/verifier.c +1
-1- const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));Just as a note,
verbose()will be aliased to a function whose prototype differs (bpf_verifier_log_write()still expects a structbpf_verifier_envas its first argument). I am not so familiar with function aliases, could this change be a concern?
yea, but as it was pointer for pointer switch I did not see any problem with that.. I'll check more
jirka
Daniel Borkmann
maintainerQuoted 36 lines · Jiri Olsa
Quoted 26 lines · Quentin Monnet
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 13 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)[...]
Quoted 9 lines
kernel/bpf/verifier.c +0
-1@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env,Quoted 8 lines
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 3 lines
kernel/bpf/verifier.c +1
-1- const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));Just as a note,
verbose()will be aliased to a function whose prototype differs (bpf_verifier_log_write()still expects a structbpf_verifier_envas its first argument). I am not so familiar with function aliases, could this change be a concern?
Quoted 2 lines
yea, but as it was pointer for pointer switch I did not see any problem with that.. I'll check more
Ok, holding off for now until we have clarification. Other option could also be to make it void *private_data everywhere and for the kernel writer then do struct bpf_verifier_env *env = private_data.
Quoted 37 lines · Daniel Borkmann
Quoted 36 lines · Jiri Olsa
Quoted 34 lines · Quentin Monnet
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 13 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)[...]
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 12 lines
kernel/bpf/verifier.c +1
-2@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env, - const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));Just as a note,
verbose()will be aliased to a function whose prototype differs (bpf_verifier_log_write()still expects a structbpf_verifier_envas its first argument). I am not so familiar with function aliases, could this change be a concern?
Quoted 6 lines
Quoted 2 lines
yea, but as it was pointer for pointer switch I did not see any problem with that.. I'll check more
Ok, holding off for now until we have clarification. Other option could also be to make it void
*private_dataeverywhere and for the kernel writer then do structbpf_verifier_env*env =private_data.
can't find much info about the alias behaviour for this case.. so how about having separate function for the print_cb like below.. I still need to test it
thanks,
jirka
--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 41 +++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 41 deletions(-)
kernel/bpf/disasm.c +26 -26
@@ -113,16 +113,16 @@ static const char *const bpf_jmp_string[16] = { };static void print_bpf_end_insn (bpf_insn_print_t verbose, -struct bpf_verifier_env *env, +void *private_data,const struct bpf_insn *insn) { -verbose (env,"(%02x) r%d = %s%d r%d\n" , insn->code, insn->dst_reg, +verbose (private_data,"(%02x) r%d = %s%d r%d\n" , + insn->code, insn->dst_reg,BPF_SRC (insn->code) ==BPF_TO_BE ?"be" :"le" , insn->imm, insn->dst_reg); }void print_bpf_insn (const struct bpf_insn_cbs *cbs, -struct bpf_verifier_env *env,const struct bpf_insn *insn,bool allow_ptr_leaks) {
@@ -132,23 +132,23 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,if (class ==BPF_ALU || class ==BPF_ALU64 ) {if (BPF_OP (insn->code) ==BPF_END ) {if (class ==BPF_ALU64 ) -verbose (env,"BUG_alu64_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_alu64_%02x\n" , insn->code);else -print_bpf_end_insn (verbose, env, insn); +print_bpf_end_insn (verbose, cbs->private_data, insn); }else if (BPF_OP (insn->code) ==BPF_NEG ) { -verbose (env,"(%02x) r%d = %s-r%d\n" , +verbose (cbs->private_data,"(%02x) r%d = %s-r%d\n" , insn->code, insn->dst_reg, class ==BPF_ALU ?"(u32) " :"" , insn->dst_reg); }else if (BPF_SRC (insn->code) ==BPF_X ) { -verbose (env,"(%02x) %sr%d %s %sr%d\n" , +verbose (cbs->private_data,"(%02x) %sr%d %s %sr%d\n" , insn->code, class ==BPF_ALU ?"(u32) " :"" , insn->dst_reg, bpf_alu_string[BPF_OP (insn->code) >>4 ], class ==BPF_ALU ?"(u32) " :"" , insn->src_reg); }else { - verbose(env, "(%02x) %sr%d %s %s%d\n", + verbose(cbs->private_data, "(%02x) %sr%d %s %s%d\n", insn->code, class == BPF_ALU ? "(u32) " : "", insn->dst_reg, bpf_alu_string[BPF_OP(insn->code) >> 4],
@@ -157,46 +157,46 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, } }else if (class ==BPF_STX ) {if (BPF_MODE (insn->code) ==BPF_MEM ) -verbose (env,"(%02x) *(%s *)(r%d %+d) = r%d\n" , +verbose (cbs->private_data,"(%02x) *(%s *)(r%d %+d) = r%d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->src_reg);else if (BPF_MODE (insn->code) ==BPF_XADD ) -verbose (env,"(%02x) lock *(%s *)(r%d %+d) += r%d\n" , +verbose (cbs->private_data,"(%02x) lock *(%s *)(r%d %+d) += r%d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->src_reg);else -verbose (env,"BUG_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_%02x\n" , insn->code); }else if (class ==BPF_ST ) {if (BPF_MODE (insn->code) !=BPF_MEM ) { -verbose (env,"BUG_st_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_st_%02x\n" , insn->code);return ; } -verbose (env,"(%02x) *(%s *)(r%d %+d) = %d\n" , +verbose (cbs->private_data,"(%02x) *(%s *)(r%d %+d) = %d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->imm); }else if (class ==BPF_LDX ) {if (BPF_MODE (insn->code) !=BPF_MEM ) { -verbose (env,"BUG_ldx_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_ldx_%02x\n" , insn->code);return ; } -verbose (env,"(%02x) r%d = *(%s *)(r%d %+d)\n" , +verbose (cbs->private_data,"(%02x) r%d = *(%s *)(r%d %+d)\n" , insn->code, insn->dst_reg, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->src_reg, insn->off); }else if (class ==BPF_LD ) {if (BPF_MODE (insn->code) ==BPF_ABS ) { -verbose (env,"(%02x) r0 = *(%s *)skb[%d]\n" , +verbose (cbs->private_data,"(%02x) r0 = *(%s *)skb[%d]\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->imm); }else if (BPF_MODE (insn->code) ==BPF_IND ) { -verbose (env,"(%02x) r0 = *(%s *)skb[r%d + %d]\n" , +verbose (cbs->private_data,"(%02x) r0 = *(%s *)skb[r%d + %d]\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->src_reg, insn->imm);
@@ -212,12 +212,12 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,if (map_ptr && !allow_ptr_leaks) imm =0 ; -verbose (env,"(%02x) r%d = %s\n" , +verbose (cbs->private_data,"(%02x) r%d = %s\n" , insn->code, insn->dst_reg,__func_imm_name (cbs, insn, imm, tmp,sizeof (tmp))); }else { -verbose (env,"BUG_ld_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_ld_%02x\n" , insn->code);return ; } }else if (class ==BPF_JMP ) {
@@ -227,35 +227,35 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,char tmp[64 ];if (insn->src_reg ==BPF_PSEUDO_CALL ) { -verbose (env,"(%02x) call pc%s\n" , +verbose (cbs->private_data,"(%02x) call pc%s\n" , insn->code,__func_get_name (cbs, insn, tmp,sizeof (tmp))); }else {strcpy (tmp,"unknown" ); -verbose (env,"(%02x) call %s#%d\n" , insn->code, +verbose (cbs->private_data,"(%02x) call %s#%d\n" , insn->code,__func_get_name (cbs, insn, tmp,sizeof (tmp)), insn->imm); } }else if (insn->code == (BPF_JMP |BPF_JA )) { -verbose (env,"(%02x) goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) goto pc%+d\n" , insn->code, insn->off); }else if (insn->code == (BPF_JMP |BPF_EXIT )) { -verbose (env,"(%02x) exit\n" , insn->code); +verbose (cbs->private_data,"(%02x) exit\n" , insn->code); }else if (BPF_SRC (insn->code) ==BPF_X ) { -verbose (env,"(%02x) if r%d %s r%d goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) if r%d %s r%d goto pc%+d\n" , insn->code, insn->dst_reg, bpf_jmp_string[BPF_OP (insn->code) >>4 ], insn->src_reg, insn->off); }else { -verbose (env,"(%02x) if r%d %s 0x%x goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) if r%d %s 0x%x goto pc%+d\n" , insn->code, insn->dst_reg, bpf_jmp_string[BPF_OP (insn->code) >>4 ], insn->imm, insn->off); } }else { -verbose (env,"(%02x) %s\n" , +verbose (cbs->private_data,"(%02x) %s\n" , insn->code, bpf_class_string[class]); } }
kernel/bpf/disasm.h +1 -4
@@ -22,14 +22,12 @@#include <string.h> #endif -struct bpf_verifier_env ; -extern const char *const bpf_alu_string[16 ];extern const char *const bpf_class_string[8 ];const char *func_id_name (int id); -typedef __printf(2, 3) void (*bpf_insn_print_t)(struct bpf_verifier_env *env, +typedef __printf(2, 3) void (*bpf_insn_print_t)(void *private_data, const char *, ...); typedef const char *(*bpf_insn_revmap_call_t)(void *private_data, const struct bpf_insn *insn);
@@ -45,7 +43,6 @@ struct bpf_insn_cbs { };void print_bpf_insn (const struct bpf_insn_cbs *cbs, -struct bpf_verifier_env *env,const struct bpf_insn *insn,bool allow_ptr_leaks);#endif
kernel/bpf/verifier.c +30 -11
71 lines not on this page · raw message
Signature · 1 line
2.13.6
2018-03-22 14:32 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 41 lines · Daniel Borkmann
Quoted 40 lines · Jiri Olsa
Quoted 38 lines · Quentin Monnet
Quoted 26 lines
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 13 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)[...]
Quoted 9 lines
kernel/bpf/verifier.c +0
-1@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env,Quoted 8 lines
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 3 lines
kernel/bpf/verifier.c +1
-1- const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));Just as a note,
verbose()will be aliased to a function whose prototype differs (bpf_verifier_log_write()still expects a structbpf_verifier_envas its first argument). I am not so familiar with function aliases, could this change be a concern?yea, but as it was pointer for pointer switch I did not see any problem with that.. I'll check more
Quoted 7 lines
Quoted 3 lines
Ok, holding off for now until we have clarification. Other option could also be to make it void
*private_dataeverywhere and for the kernel writer then do structbpf_verifier_env*env =private_data.can't find much info about the alias behaviour for this case.. so how about having separate function for the
print_cblike below.. I still need to test it
I have nothing against splitting the function. This is a solution I considered for verbose() and bpf_verifier_log_write(), before switching to function alias (on Daniel's suggestion) because the code would be identical for the two separate functions at that time. But with your change they would not have the same signature anymore, so it sounds reasonable. Just a note below...
Quoted 11 lines
thanks,
jirka--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 41 +++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 41 deletions(-)
[...]
Quoted 42 lines
kernel/bpf/verifier.c +10
-9@@ -168,23 +168,16 @@ struct bpf_call_arg_meta {static DEFINE_MUTEX (bpf_verifier_lock); -/* log_level controls verbosity level of eBPF verifier. -* bpf_verifier_log_write() is used to dump the verification trace to the log, -* so the user can figure out what's wrong with the program -*/ -__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, -const char *fmt, ...) +static void log_write (struct bpf_verifier_env *env,const char *fmt, +va_list args) {struct bpf_verifer_log *log = &env->log;unsigned int n; -va_list args;if (!log->level || !log->ubuf ||bpf_verifier_log_full (log))return ; -va_start (args, fmt); n =vscnprintf (log->kbuf,BPF_VERIFIER_TMP_LOG_SIZE , fmt, args); -va_end (args);WARN_ONCE (n >=BPF_VERIFIER_TMP_LOG_SIZE -1 ,"verifier log line truncated - local buffer too short\n" );@@ -197,7 +190,32 @@ __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,else log->ubuf =NULL ; } + +/* log_level controls verbosity level of eBPF verifier. +* bpf_verifier_log_write() is used to dump the verification trace to the log, +* so the user can figure out what's wrong with the program +*/ +__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, +const char *fmt, ...) +{
kernel/bpf/verifier.c __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, · line 210
Quoted 10 lines
kernel/bpf/verifier.c +9
-0+va_list args; + +va_start (args, fmt); +log_write (env, fmt, args); +va_end (args); +}EXPORT_SYMBOL_GPL (bpf_verifier_log_write); + +__printf(2, 3) static void print_ins(void *private_data, +const char *fmt, ...)
Unless I am mistaken, you could just call this one "verbose()" and simply remove the function alias?
Quoted 27 lines
kernel/bpf/verifier.c +11
-2+{ +va_list args; + +va_start (args, fmt); +log_write (private_data, fmt, args); +va_end (args); +} +/* Historically bpf_verifier_log_write was called verbose, but the name was too * generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. @@ -4599,11 +4617,12 @@ static int do_check(struct bpf_verifier_env *env)if (env->log.level) {const struct bpf_insn_cbs cbs = { - .cb_print = verbose, + .cb_print = print_ins, + .private_data = env, };verbose (env,"%d: " , insn_idx); -print_bpf_insn (&cbs, env, insn, env->allow_ptr_leaks); +print_bpf_insn (&cbs, insn, env->allow_ptr_leaks); }if (bpf_prog_is_dev_bound (env->prog->aux)) {
Quoted 118 lines · Quentin Monnet
2018-03-22 14:32 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 41 lines · Daniel Borkmann
Quoted 40 lines · Jiri Olsa
Quoted 38 lines · Quentin Monnet
Quoted 26 lines
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 13 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)[...]
Quoted 9 lines
kernel/bpf/verifier.c +0
-1@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env,Quoted 8 lines
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 3 lines
kernel/bpf/verifier.c +1
-1- const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));Just as a note,
verbose()will be aliased to a function whose prototype differs (bpf_verifier_log_write()still expects a structbpf_verifier_envas its first argument). I am not so familiar with function aliases, could this change be a concern?yea, but as it was pointer for pointer switch I did not see any problem with that.. I'll check more
Quoted 7 lines
Quoted 3 lines
Ok, holding off for now until we have clarification. Other option could also be to make it void
*private_dataeverywhere and for the kernel writer then do structbpf_verifier_env*env =private_data.can't find much info about the alias behaviour for this case.. so how about having separate function for the
print_cblike below.. I still need to test itI have nothing against splitting the function. This is a solution I considered for
verbose()andbpf_verifier_log_write(), before switching to function alias (on Daniel's suggestion) because the code would be identical for the two separate functions at that time. But with your change they would not have the same signature anymore, so it sounds reasonable. Just a note below...Quoted 11 lines
thanks,
jirka--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 41 +++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 41 deletions(-)[...]
Quoted 47 lines
kernel/bpf/verifier.c +15
-9@@ -168,23 +168,16 @@ struct bpf_call_arg_meta {static DEFINE_MUTEX (bpf_verifier_lock); -/* log_level controls verbosity level of eBPF verifier. -* bpf_verifier_log_write() is used to dump the verification trace to the log, -* so the user can figure out what's wrong with the program -*/ -__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, -const char *fmt, ...) +static void log_write (struct bpf_verifier_env *env,const char *fmt, +va_list args) {struct bpf_verifer_log *log = &env->log;unsigned int n; -va_list args;if (!log->level || !log->ubuf ||bpf_verifier_log_full (log))return ; -va_start (args, fmt); n =vscnprintf (log->kbuf,BPF_VERIFIER_TMP_LOG_SIZE , fmt, args); -va_end (args);WARN_ONCE (n >=BPF_VERIFIER_TMP_LOG_SIZE -1 ,"verifier log line truncated - local buffer too short\n" );@@ -197,7 +190,32 @@ __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,else log->ubuf =NULL ; } + +/* log_level controls verbosity level of eBPF verifier. +* bpf_verifier_log_write() is used to dump the verification trace to the log, +* so the user can figure out what's wrong with the program +*/ +__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, +const char *fmt, ...) +{ +va_list args; + +va_start (args, fmt); +log_write (env, fmt, args); +va_end (args);
Quoted 8 lines
kernel/bpf/verifier.c __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, · line 210
Quoted 5 lines
kernel/bpf/verifier.c +4
-0+}EXPORT_SYMBOL_GPL (bpf_verifier_log_write); + +__printf(2, 3) static void print_ins(void *private_data, +const char *fmt, ...)Unless I am mistaken, you could just call this one "
verbose()" and simply remove the function alias?
right you are ;-) I haven't realized that struct bpf_verifier_env *env will cleanly cast to void *
new version attached.. I'll make some tests and send full patch
jirka
---
kernel/bpf/disasm.c +26 -26
@@ -113,16 +113,16 @@ static const char *const bpf_jmp_string[16] = { };static void print_bpf_end_insn (bpf_insn_print_t verbose, -struct bpf_verifier_env *env, +void *private_data,const struct bpf_insn *insn) { -verbose (env,"(%02x) r%d = %s%d r%d\n" , insn->code, insn->dst_reg, +verbose (private_data,"(%02x) r%d = %s%d r%d\n" , + insn->code, insn->dst_reg,BPF_SRC (insn->code) ==BPF_TO_BE ?"be" :"le" , insn->imm, insn->dst_reg); }void print_bpf_insn (const struct bpf_insn_cbs *cbs, -struct bpf_verifier_env *env,const struct bpf_insn *insn,bool allow_ptr_leaks) {
@@ -132,23 +132,23 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,if (class ==BPF_ALU || class ==BPF_ALU64 ) {if (BPF_OP (insn->code) ==BPF_END ) {if (class ==BPF_ALU64 ) -verbose (env,"BUG_alu64_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_alu64_%02x\n" , insn->code);else -print_bpf_end_insn (verbose, env, insn); +print_bpf_end_insn (verbose, cbs->private_data, insn); }else if (BPF_OP (insn->code) ==BPF_NEG ) { -verbose (env,"(%02x) r%d = %s-r%d\n" , +verbose (cbs->private_data,"(%02x) r%d = %s-r%d\n" , insn->code, insn->dst_reg, class ==BPF_ALU ?"(u32) " :"" , insn->dst_reg); }else if (BPF_SRC (insn->code) ==BPF_X ) { -verbose (env,"(%02x) %sr%d %s %sr%d\n" , +verbose (cbs->private_data,"(%02x) %sr%d %s %sr%d\n" , insn->code, class ==BPF_ALU ?"(u32) " :"" , insn->dst_reg, bpf_alu_string[BPF_OP (insn->code) >>4 ], class ==BPF_ALU ?"(u32) " :"" , insn->src_reg); }else { - verbose(env, "(%02x) %sr%d %s %s%d\n", + verbose(cbs->private_data, "(%02x) %sr%d %s %s%d\n", insn->code, class == BPF_ALU ? "(u32) " : "", insn->dst_reg, bpf_alu_string[BPF_OP(insn->code) >> 4],
@@ -157,46 +157,46 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, } }else if (class ==BPF_STX ) {if (BPF_MODE (insn->code) ==BPF_MEM ) -verbose (env,"(%02x) *(%s *)(r%d %+d) = r%d\n" , +verbose (cbs->private_data,"(%02x) *(%s *)(r%d %+d) = r%d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->src_reg);else if (BPF_MODE (insn->code) ==BPF_XADD ) -verbose (env,"(%02x) lock *(%s *)(r%d %+d) += r%d\n" , +verbose (cbs->private_data,"(%02x) lock *(%s *)(r%d %+d) += r%d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->src_reg);else -verbose (env,"BUG_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_%02x\n" , insn->code); }else if (class ==BPF_ST ) {if (BPF_MODE (insn->code) !=BPF_MEM ) { -verbose (env,"BUG_st_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_st_%02x\n" , insn->code);return ; } -verbose (env,"(%02x) *(%s *)(r%d %+d) = %d\n" , +verbose (cbs->private_data,"(%02x) *(%s *)(r%d %+d) = %d\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->dst_reg, insn->off, insn->imm); }else if (class ==BPF_LDX ) {if (BPF_MODE (insn->code) !=BPF_MEM ) { -verbose (env,"BUG_ldx_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_ldx_%02x\n" , insn->code);return ; } -verbose (env,"(%02x) r%d = *(%s *)(r%d %+d)\n" , +verbose (cbs->private_data,"(%02x) r%d = *(%s *)(r%d %+d)\n" , insn->code, insn->dst_reg, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->src_reg, insn->off); }else if (class ==BPF_LD ) {if (BPF_MODE (insn->code) ==BPF_ABS ) { -verbose (env,"(%02x) r0 = *(%s *)skb[%d]\n" , +verbose (cbs->private_data,"(%02x) r0 = *(%s *)skb[%d]\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->imm); }else if (BPF_MODE (insn->code) ==BPF_IND ) { -verbose (env,"(%02x) r0 = *(%s *)skb[r%d + %d]\n" , +verbose (cbs->private_data,"(%02x) r0 = *(%s *)skb[r%d + %d]\n" , insn->code, bpf_ldst_string[BPF_SIZE (insn->code) >>3 ], insn->src_reg, insn->imm);
@@ -212,12 +212,12 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,if (map_ptr && !allow_ptr_leaks) imm =0 ; -verbose (env,"(%02x) r%d = %s\n" , +verbose (cbs->private_data,"(%02x) r%d = %s\n" , insn->code, insn->dst_reg,__func_imm_name (cbs, insn, imm, tmp,sizeof (tmp))); }else { -verbose (env,"BUG_ld_%02x\n" , insn->code); +verbose (cbs->private_data,"BUG_ld_%02x\n" , insn->code);return ; } }else if (class ==BPF_JMP ) {
@@ -227,35 +227,35 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,char tmp[64 ];if (insn->src_reg ==BPF_PSEUDO_CALL ) { -verbose (env,"(%02x) call pc%s\n" , +verbose (cbs->private_data,"(%02x) call pc%s\n" , insn->code,__func_get_name (cbs, insn, tmp,sizeof (tmp))); }else {strcpy (tmp,"unknown" ); -verbose (env,"(%02x) call %s#%d\n" , insn->code, +verbose (cbs->private_data,"(%02x) call %s#%d\n" , insn->code,__func_get_name (cbs, insn, tmp,sizeof (tmp)), insn->imm); } }else if (insn->code == (BPF_JMP |BPF_JA )) { -verbose (env,"(%02x) goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) goto pc%+d\n" , insn->code, insn->off); }else if (insn->code == (BPF_JMP |BPF_EXIT )) { -verbose (env,"(%02x) exit\n" , insn->code); +verbose (cbs->private_data,"(%02x) exit\n" , insn->code); }else if (BPF_SRC (insn->code) ==BPF_X ) { -verbose (env,"(%02x) if r%d %s r%d goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) if r%d %s r%d goto pc%+d\n" , insn->code, insn->dst_reg, bpf_jmp_string[BPF_OP (insn->code) >>4 ], insn->src_reg, insn->off); }else { -verbose (env,"(%02x) if r%d %s 0x%x goto pc%+d\n" , +verbose (cbs->private_data,"(%02x) if r%d %s 0x%x goto pc%+d\n" , insn->code, insn->dst_reg, bpf_jmp_string[BPF_OP (insn->code) >>4 ], insn->imm, insn->off); } }else { -verbose (env,"(%02x) %s\n" , +verbose (cbs->private_data,"(%02x) %s\n" , insn->code, bpf_class_string[class]); } }
kernel/bpf/disasm.h +1 -4
@@ -22,14 +22,12 @@#include <string.h> #endif -struct bpf_verifier_env ; -extern const char *const bpf_alu_string[16 ];extern const char *const bpf_class_string[8 ];const char *func_id_name (int id); -typedef __printf(2, 3) void (*bpf_insn_print_t)(struct bpf_verifier_env *env, +typedef __printf(2, 3) void (*bpf_insn_print_t)(void *private_data, const char *, ...); typedef const char *(*bpf_insn_revmap_call_t)(void *private_data, const struct bpf_insn *insn);
@@ -45,7 +43,6 @@ struct bpf_insn_cbs { };void print_bpf_insn (const struct bpf_insn_cbs *cbs, -struct bpf_verifier_env *env,const struct bpf_insn *insn,bool allow_ptr_leaks);#endif
kernel/bpf/verifier.c +27 -17
74 lines not on this page · raw message
Daniel Borkmann
maintainerQuoted 128 lines · Jiri Olsa
Quoted 118 lines · Quentin Monnet
2018-03-22 14:32 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 41 lines · Daniel Borkmann
Quoted 40 lines · Jiri Olsa
Quoted 38 lines · Quentin Monnet
Quoted 26 lines
2018-03-21 16:02 UTC+0100 ~ Jiri Olsa <[email protected]>
Quoted 13 lines
We use
print_bpf_insnin user space (bpftool and soon perf), so it'd be nice to keep it generic and strip it off the kernel structbpf_verifier_envargument.This argument can be safely removed, because its users can use the struct
bpf_insn_cbs::private_datato pass it.Signed-off-by Jiri Olsa <[email protected]>--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 6 +++--- 3 files changed, 30 insertions(+), 33 deletions(-)[...]
Quoted 9 lines
kernel/bpf/verifier.c +0
-1@@ -202,8 +202,7 @@ EXPORT_SYMBOL_GPL(bpf_verifier_log_write);* generic for symbol export. The function was renamed, but not the calls in * the verifier to avoid complicating backports. Hence the alias below. */ -static __printf(2, 3) void verbose(struct bpf_verifier_env *env,Quoted 8 lines
kernel/bpf/verifier.c EXPORT_SYMBOL_GPL(bpf_verifier_log_write); · line 206
Quoted 3 lines
kernel/bpf/verifier.c +1
-1- const char *fmt, ...) +static __printf(2, 3) void verbose(void *private_data, const char *fmt, ...) __attribute__((alias("bpf_verifier_log_write")));Just as a note,
verbose()will be aliased to a function whose prototype differs (bpf_verifier_log_write()still expects a structbpf_verifier_envas its first argument). I am not so familiar with function aliases, could this change be a concern?yea, but as it was pointer for pointer switch I did not see any problem with that.. I'll check more
Quoted 7 lines
Quoted 3 lines
Ok, holding off for now until we have clarification. Other option could also be to make it void
*private_dataeverywhere and for the kernel writer then do structbpf_verifier_env*env =private_data.can't find much info about the alias behaviour for this case.. so how about having separate function for the
print_cblike below.. I still need to test itI have nothing against splitting the function. This is a solution I considered for
verbose()andbpf_verifier_log_write(), before switching to function alias (on Daniel's suggestion) because the code would be identical for the two separate functions at that time. But with your change they would not have the same signature anymore, so it sounds reasonable. Just a note below...Quoted 11 lines
thanks,
jirka--- kernel/bpf/disasm.c | 52 +++++++++++++++++++++++++-------------------------- kernel/bpf/disasm.h | 5 +---- kernel/bpf/verifier.c | 41 +++++++++++++++++++++++++++++----------- 3 files changed, 57 insertions(+), 41 deletions(-)[...]
Quoted 47 lines
kernel/bpf/verifier.c +15
-9@@ -168,23 +168,16 @@ struct bpf_call_arg_meta {static DEFINE_MUTEX (bpf_verifier_lock); -/* log_level controls verbosity level of eBPF verifier. -* bpf_verifier_log_write() is used to dump the verification trace to the log, -* so the user can figure out what's wrong with the program -*/ -__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, -const char *fmt, ...) +static void log_write (struct bpf_verifier_env *env,const char *fmt, +va_list args) {struct bpf_verifer_log *log = &env->log;unsigned int n; -va_list args;if (!log->level || !log->ubuf ||bpf_verifier_log_full (log))return ; -va_start (args, fmt); n =vscnprintf (log->kbuf,BPF_VERIFIER_TMP_LOG_SIZE , fmt, args); -va_end (args);WARN_ONCE (n >=BPF_VERIFIER_TMP_LOG_SIZE -1 ,"verifier log line truncated - local buffer too short\n" );@@ -197,7 +190,32 @@ __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,else log->ubuf =NULL ; } + +/* log_level controls verbosity level of eBPF verifier. +* bpf_verifier_log_write() is used to dump the verification trace to the log, +* so the user can figure out what's wrong with the program +*/ +__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, +const char *fmt, ...) +{ +va_list args; + +va_start (args, fmt); +log_write (env, fmt, args); +va_end (args);Quoted 8 lines
kernel/bpf/verifier.c __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env, · line 210
Quoted 5 lines
kernel/bpf/verifier.c +4
-0+}EXPORT_SYMBOL_GPL (bpf_verifier_log_write); + +__printf(2, 3) static void print_ins(void *private_data, +const char *fmt, ...)Unless I am mistaken, you could just call this one "
verbose()" and simply remove the function alias?
Quoted 4 lines
right you are ;-) I haven't realized that struct
bpf_verifier_env*env will cleanly cast to void *new version attached.. I'll make some tests and send full patch
When you do so, please make sure to send a full fresh series with the two patches and also cover letter included, otherwise it's more fragile wrt potentially applying the wrong patch from one of the replies. :-)
Thanks,
Daniel
On Thu, Mar 22, 2018 at 05:07:48PM +0100, Daniel Borkmann wrote:
SNIP
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
kernel/bpf/verifier.c __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,
Quoted 6 lines
kernel/bpf/verifier.c +5
-0+va_end (args); +}EXPORT_SYMBOL_GPL (bpf_verifier_log_write); + +__printf(2, 3) static void print_ins(void *private_data, +const char *fmt, ...)Unless I am mistaken, you could just call this one "
verbose()" and simply remove the function alias?
Quoted 8 lines
Quoted 4 lines
right you are ;-) I haven't realized that struct
bpf_verifier_env*env will cleanly cast to void *new version attached.. I'll make some tests and send full patch
When you do so, please make sure to send a full fresh series with the two patches and also cover letter included, otherwise it's more fragile wrt potentially applying the wrong patch from one of the replies. :-)
will do, thanks
jirka