From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:20
This series introduces a new helper, bpf_trace_vprintk, which functions
like bpf_trace_printk but supports > 3 arguments via a pseudo-vararg u64
array. The bpf_printk libbpf convenience macro is modified to use
bpf_trace_vprintk when > 3 varargs are passed, otherwise the previous
behavior - using bpf_trace_printk - is retained.
Helper functions and macros added during the implementation of
bpf_seq_printf and bpf_snprintf do most of the heavy lifting for
bpf_trace_vprintk. There's no novel format string wrangling here.
Usecase here is straightforward: Giving BPF program writers a more
powerful printk will ease development of BPF programs, particularly
during debugging and testing, where printk tends to be used.
This feature was proposed by Andrii in libbpf mirror's issue tracker
[1].
[1] https://github.com/libbpf/libbpf/issues/315
v2 -> v3:
* Clean up patch 3's commit message [Alexei]
* Add patch 4, which modifies __bpf_printk to use 'static const char' to
store fmt string with fallback for older kernels [Andrii]
* rebase
v1 -> v2:
* Naming conversation seems to have gone in favor of keeping
bpf_trace_vprintk, names are unchanged
* Patch 3 now modifies bpf_printk convenience macro to choose between
__bpf_printk and __bpf_vprintk 'implementation' macros based on arg
count. __bpf_vprintk is a renaming of bpf_vprintk convenience macro
from v1, __bpf_printk is the existing bpf_printk implementation.
This patch could use some scrutiny as I think current implementation
may regress developer experience in a specific case, turning a
compile-time error into a load-time error. Unclear to me how
common the case is, or whether the macro magic I chose is ideal.
* char ___fmt[] to static const char ___fmt[] change was not done,
wanted to leave __bpf_printk 'implementation' macro unchanged for v2
to ease discussion of above point
* Removed __always_inline from __set_printk_clr_event [Andrii]
* Simplified bpf_trace_printk docstring to refer to other functions
instead of copy/pasting and avoid specifying 12 vararg limit [Andrii]
* Migrated trace_printk selftest to use ASSERT_ instead of CHECK
* Adds new patch 5, previous patch 5 is now 6
* Migrated trace_vprintk selftest to use ASSERT_ instead of CHECK,
open_and_load instead of separate open, load [Andrii]
* Patch 2's commit message now correctly mentions trace_pipe instead of
dmesg [Andrii]
Dave Marchevsky (7):
bpf: merge printk and seq_printf VARARG max macros
bpf: add bpf_trace_vprintk helper
libbpf: Modify bpf_printk to choose helper based on arg count
libbpf: use static const fmt string in __bpf_printk
bpftool: only probe trace_vprintk feature in 'full' mode
selftests/bpf: Migrate prog_tests/trace_printk CHECKs to ASSERTs
selftests/bpf: add trace_vprintk test prog
include/linux/bpf.h | 3 +
include/uapi/linux/bpf.h | 9 +++
kernel/bpf/core.c | 5 ++
kernel/bpf/helpers.c | 6 +-
kernel/trace/bpf_trace.c | 54 ++++++++++++++-
tools/bpf/bpftool/feature.c | 1 +
tools/include/uapi/linux/bpf.h | 9 +++
tools/lib/bpf/bpf_helpers.h | 51 ++++++++++++---
tools/testing/selftests/bpf/Makefile | 3 +-
.../selftests/bpf/prog_tests/trace_printk.c | 24 +++----
.../selftests/bpf/prog_tests/trace_vprintk.c | 65 +++++++++++++++++++
.../selftests/bpf/progs/trace_vprintk.c | 25 +++++++
tools/testing/selftests/bpf/test_bpftool.py | 22 +++----
13 files changed, 234 insertions(+), 43 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/trace_vprintk.c
create mode 100644 tools/testing/selftests/bpf/progs/trace_vprintk.c
--
2.30.2
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:23
This helper is meant to be "bpf_trace_printk, but with proper vararg
support". Follow bpf_snprintf's example and take a u64 pseudo-vararg
array. Write to /sys/kernel/debug/tracing/trace_pipe using the same
mechanism as bpf_trace_printk.
Signed-off-by: Dave Marchevsky <redacted>
---
include/linux/bpf.h | 1 +
include/uapi/linux/bpf.h | 9 ++++++
kernel/bpf/core.c | 5 ++++
kernel/bpf/helpers.c | 2 ++
kernel/trace/bpf_trace.c | 52 +++++++++++++++++++++++++++++++++-
tools/include/uapi/linux/bpf.h | 9 ++++++
6 files changed, 77 insertions(+), 1 deletion(-)
@@ -4877,6 +4877,14 @@ union bpf_attr {*Getthestructpt_regsassociatedwith**task**.*Return*Apointertostructpt_regs.+*+*u64bpf_trace_vprintk(constchar*fmt,u32fmt_size,constvoid*data,u32data_len)+*Description+*Behaveslike**bpf_trace_printk**\()helper,buttakesanarrayofu64+*toformat.Argumentsaretobeusedasin**bpf_seq_printf**\()helper.+*Return+*Thenumberofbyteswrittentothebuffer,oranegativeerror+*incaseoffailure.*/#define __BPF_FUNC_MAPPER(FN) \FN(unspec),\
@@ -5055,6 +5063,7 @@ union bpf_attr {FN(get_func_ip),\FN(get_attach_cookie),\FN(task_pt_regs),\+FN(trace_vprintk),\/* *//* integer value in 'imm' field of BPF_CALL instruction selects which helper
@@ -4877,6 +4877,14 @@ union bpf_attr {*Getthestructpt_regsassociatedwith**task**.*Return*Apointertostructpt_regs.+*+*u64bpf_trace_vprintk(constchar*fmt,u32fmt_size,constvoid*data,u32data_len)+*Description+*Behaveslike**bpf_trace_printk**\()helper,buttakesanarrayofu64+*toformat.Argumentsaretobeusedasin**bpf_seq_printf**\()helper.+*Return+*Thenumberofbyteswrittentothebuffer,oranegativeerror+*incaseoffailure.*/#define __BPF_FUNC_MAPPER(FN) \FN(unspec),\
@@ -5055,6 +5063,7 @@ union bpf_attr {FN(get_func_ip),\FN(get_attach_cookie),\FN(task_pt_regs),\+FN(trace_vprintk),\/* *//* integer value in 'imm' field of BPF_CALL instruction selects which helper
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:37
MAX_SNPRINTF_VARARGS and MAX_SEQ_PRINTF_VARARGS are used by bpf helpers
bpf_snprintf and bpf_seq_printf to limit their varargs. Both call into
bpf_bprintf_prepare for print formatting logic and have convenience
macros in libbpf (BPF_SNPRINTF, BPF_SEQ_PRINTF) which use the same
helper macros to convert varargs to a byte array.
Changing shared functionality to support more varargs for either bpf
helper would affect the other as well, so let's combine the _VARARGS
macros to make this more obvious.
Signed-off-by: Dave Marchevsky <redacted>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
---
include/linux/bpf.h | 2 ++
kernel/bpf/helpers.c | 4 +---
kernel/trace/bpf_trace.c | 4 +---
3 files changed, 4 insertions(+), 6 deletions(-)
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:38
The __bpf_printk convenience macro was using a 'char' fmt string holder
as it predates support for globals in libbpf. Move to more efficient
'static const char', but provide a fallback to the old way via
BPF_NO_GLOBAL_DATA so users on old kernels can still use the macro.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:41
Since commit 368cb0e7cdb5e ("bpftool: Make probes which emit dmesg
warnings optional"), some helpers aren't probed by bpftool unless
`full` arg is added to `bpftool feature probe`.
bpf_trace_vprintk can emit dmesg warnings when probed, so include it.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/bpf/bpftool/feature.c | 1 +
tools/testing/selftests/bpf/test_bpftool.py | 22 +++++++++------------
2 files changed, 10 insertions(+), 13 deletions(-)
@@ -67,10 +72,7 @@ class TestBpftool(unittest.TestCase):@default_ifacedeftest_feature_dev_json(self,iface):-unexpected_helpers=[-"bpf_probe_write_user",-"bpf_trace_printk",-]+unexpected_helpers=DMESG_EMITTING_HELPERSexpected_keys=["syscall_config","program_types",
@@ -94,10 +96,7 @@ class TestBpftool(unittest.TestCase):bpftool_json(["feature","probe"]),bpftool_json(["feature"]),]-unexpected_helpers=[-"bpf_probe_write_user",-"bpf_trace_printk",-]+unexpected_helpers=DMESG_EMITTING_HELPERSexpected_keys=["syscall_config","system_config",
@@ -121,10 +120,7 @@ class TestBpftool(unittest.TestCase):bpftool_json(["feature","probe","kernel","full"]),bpftool_json(["feature","probe","full"]),]-expected_helpers=[-"bpf_probe_write_user",-"bpf_trace_printk",-]+expected_helpers=DMESG_EMITTING_HELPERSfortcintest_cases:# Check if expected helpers are included at least once in any
@@ -157,7 +153,7 @@ class TestBpftool(unittest.TestCase):not_full_set.add(helper)self.assertCountEqual(full_set-not_full_set,-{"bpf_probe_write_user","bpf_trace_printk"})+set(DMESG_EMITTING_HELPERS))self.assertCountEqual(not_full_set-full_set,set())deftest_feature_macros(self):
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:41
Guidance for new tests is to use ASSERT macros instead of CHECK. Since
trace_vprintk test will borrow heavily from trace_printk's, migrate its
CHECKs so it remains obvious that the two are closely related.
Signed-off-by: Dave Marchevsky <redacted>
---
.../selftests/bpf/prog_tests/trace_printk.c | 24 +++++++------------
1 file changed, 9 insertions(+), 15 deletions(-)
@@ -18,25 +18,24 @@ void test_trace_printk(void)size_tbuflen;skel=trace_printk__open();-if(CHECK(!skel,"skel_open","failed to open skeleton\n"))+if(!ASSERT_OK_PTR(skel,"trace_printk__open"))return;-ASSERT_EQ(skel->rodata->fmt[0],'T',"invalid printk fmt string");+ASSERT_EQ(skel->rodata->fmt[0],'T',"skel->rodata->fmt[0]");skel->rodata->fmt[0]='t';err=trace_printk__load(skel);-if(CHECK(err,"skel_load","failed to load skeleton: %d\n",err))+if(!ASSERT_OK(err,"trace_printk__load"))gotocleanup;bss=skel->bss;err=trace_printk__attach(skel);-if(CHECK(err,"skel_attach","skeleton attach failed: %d\n",err))+if(!ASSERT_OK(err,"trace_printk__attach"))gotocleanup;fp=fopen(TRACEBUF,"r");-if(CHECK(fp==NULL,"could not open trace buffer",-"error %d opening %s",errno,TRACEBUF))+if(!ASSERT_OK_PTR(fp,"fopen(TRACEBUF)"))gotocleanup;/* We do not want to wait forever if this test fails... */
@@ -46,14 +45,10 @@ void test_trace_printk(void)usleep(1);trace_printk__detach(skel);-if(CHECK(bss->trace_printk_ran==0,-"bpf_trace_printk never ran",-"ran == %d",bss->trace_printk_ran))+if(!ASSERT_GT(bss->trace_printk_ran,0,"bss->trace_printk_ran"))gotocleanup;-if(CHECK(bss->trace_printk_ret<=0,-"bpf_trace_printk returned <= 0 value",-"got %d",bss->trace_printk_ret))+if(!ASSERT_GT(bss->trace_printk_ret,0,"bss->trace_printk_ret"))gotocleanup;/* verify our search string is in the trace buffer */
@@ -66,8 +61,7 @@ void test_trace_printk(void)break;}-if(CHECK(!found,"message from bpf_trace_printk not found",-"no instance of %s in %s",SEARCHMSG,TRACEBUF))+if(!ASSERT_EQ(found,bss->trace_printk_ran,"found"))gotocleanup;cleanup:
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:41
Instead of being a thin wrapper which calls into bpf_trace_printk,
libbpf's bpf_printk convenience macro now chooses between
bpf_trace_printk and bpf_trace_vprintk. If the arg count (excluding
format string) is >3, use bpf_trace_vprintk, otherwise use the older
helper.
The motivation behind this added complexity - instead of migrating
entirely to bpf_trace_vprintk - is to maintain good developer experience
for users compiling against new libbpf but running on older kernels.
Users who are passing <=3 args to bpf_printk will see no change in their
bytecode.
__bpf_vprintk functions similarly to BPF_SEQ_PRINTF and BPF_SNPRINTF
macros elsewhere in the file - it allows use of bpf_trace_vprintk
without manual conversion of varargs to u64 array. Previous
implementation of bpf_printk macro is moved to __bpf_printk for use by
the new implementation.
This does change behavior of bpf_printk calls with >3 args in the "new
libbpf, old kernels" scenario. Before this patch, attempting to use 4
args to bpf_printk results in a compile-time error. After this patch,
using bpf_printk with 4 args results in a trace_vprintk helper call
being emitted and a load-time failure on older kernels.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 45 ++++++++++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 8 deletions(-)
From: Dave Marchevsky <hidden> Date: 2021-08-28 05:20:44
This commit adds a test prog for vprintk which confirms that:
* bpf_trace_vprintk is writing to dmesg
* __bpf_vprintk macro works as expected
* >3 args are printed
Approach and code are borrowed from trace_printk test.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/testing/selftests/bpf/Makefile | 3 +-
.../selftests/bpf/prog_tests/trace_vprintk.c | 65 +++++++++++++++++++
.../selftests/bpf/progs/trace_vprintk.c | 25 +++++++
3 files changed, 92 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/trace_vprintk.c
create mode 100644 tools/testing/selftests/bpf/progs/trace_vprintk.c
@@ -0,0 +1,65 @@+// SPDX-License-Identifier: GPL-2.0+/* Copyright (c) 2021 Facebook */++#include<test_progs.h>++#include"trace_vprintk.lskel.h"++#define TRACEBUF "/sys/kernel/debug/tracing/trace_pipe"+#define SEARCHMSG "1,2,3,4,5,6,7,8,9,10"++voidtest_trace_vprintk(void)+{+interr=0,iter=0,found=0;+structtrace_vprintk__bss*bss;+structtrace_vprintk*skel;+char*buf=NULL;+FILE*fp=NULL;+size_tbuflen;++skel=trace_vprintk__open_and_load();+if(!ASSERT_OK_PTR(skel,"trace_vprintk__open_and_load"))+gotocleanup;++bss=skel->bss;++err=trace_vprintk__attach(skel);+if(!ASSERT_OK(err,"trace_vprintk__attach"))+gotocleanup;++fp=fopen(TRACEBUF,"r");+if(!ASSERT_OK_PTR(fp,"fopen(TRACEBUF)"))+gotocleanup;++/* We do not want to wait forever if this test fails... */+fcntl(fileno(fp),F_SETFL,O_NONBLOCK);++/* wait for tracepoint to trigger */+usleep(1);+trace_vprintk__detach(skel);++if(!ASSERT_GT(bss->trace_vprintk_ran,0,"bss->trace_vprintk_ran"))+gotocleanup;++if(!ASSERT_GT(bss->trace_vprintk_ret,0,"bss->trace_vprintk_ret"))+gotocleanup;++/* verify our search string is in the trace buffer */+while(getline(&buf,&buflen,fp)>=0||errno==EAGAIN){+if(strstr(buf,SEARCHMSG)!=NULL)+found++;+if(found==bss->trace_vprintk_ran)+break;+if(++iter>1000)+break;+}++if(!ASSERT_EQ(found,bss->trace_vprintk_ran,"found"))+gotocleanup;++cleanup:+trace_vprintk__destroy(skel);+free(buf);+if(fp)+fclose(fp);+}
From: Dave Marchevsky <hidden> Date: 2021-08-28 16:40:53
On 8/28/21 1:20 AM, Dave Marchevsky wrote:
quoted hunk
The __bpf_printk convenience macro was using a 'char' fmt string holder
as it predates support for globals in libbpf. Move to more efficient
'static const char', but provide a fallback to the old way via
BPF_NO_GLOBAL_DATA so users on old kernels can still use the macro.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
The reference_tracking prog test is failing as a result of this.
Specifically, it fails to load bpf_sk_lookup_test0 prog, which
has a bpf_printk:
47: (b4) w3 = 0
48: (18) r1 = 0x0
50: (b4) w2 = 7
51: (85) call bpf_trace_printk#6
R1 type=inv expected=fp, pkt, pkt_meta, map_key, map_value, mem, rdonly_buf, rdwr_buf
Setting BPF_NO_GLOBAL_DATA in the test results in a pass
From: Dave Marchevsky <hidden> Date: 2021-08-28 17:25:10
On 8/28/21 1:20 AM, Dave Marchevsky wrote:
quoted hunk
Instead of being a thin wrapper which calls into bpf_trace_printk,
libbpf's bpf_printk convenience macro now chooses between
bpf_trace_printk and bpf_trace_vprintk. If the arg count (excluding
format string) is >3, use bpf_trace_vprintk, otherwise use the older
helper.
The motivation behind this added complexity - instead of migrating
entirely to bpf_trace_vprintk - is to maintain good developer experience
for users compiling against new libbpf but running on older kernels.
Users who are passing <=3 args to bpf_printk will see no change in their
bytecode.
__bpf_vprintk functions similarly to BPF_SEQ_PRINTF and BPF_SNPRINTF
macros elsewhere in the file - it allows use of bpf_trace_vprintk
without manual conversion of varargs to u64 array. Previous
implementation of bpf_printk macro is moved to __bpf_printk for use by
the new implementation.
This does change behavior of bpf_printk calls with >3 args in the "new
libbpf, old kernels" scenario. Before this patch, attempting to use 4
args to bpf_printk results in a compile-time error. After this patch,
using bpf_printk with 4 args results in a trace_vprintk helper call
being emitted and a load-time failure on older kernels.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 45 ++++++++++++++++++++++++++++++-------
1 file changed, 37 insertions(+), 8 deletions(-)
While looking at test failure related to patch 4, noticed
that this isn't handling 0 format arg case correctly, resulting
in compilation error.
Need to fix and add a test as all extant selftests are doing
bpf_printk with at least 1 format arg.
On Sat, Aug 28, 2021 at 12:40:17PM -0400, Dave Marchevsky wrote:
On 8/28/21 1:20 AM, Dave Marchevsky wrote:
quoted
The __bpf_printk convenience macro was using a 'char' fmt string holder
as it predates support for globals in libbpf. Move to more efficient
'static const char', but provide a fallback to the old way via
BPF_NO_GLOBAL_DATA so users on old kernels can still use the macro.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
The reference_tracking prog test is failing as a result of this.
Specifically, it fails to load bpf_sk_lookup_test0 prog, which
has a bpf_printk:
47: (b4) w3 = 0
48: (18) r1 = 0x0
50: (b4) w2 = 7
51: (85) call bpf_trace_printk#6
R1 type=inv expected=fp, pkt, pkt_meta, map_key, map_value, mem, rdonly_buf, rdwr_buf
Setting BPF_NO_GLOBAL_DATA in the test results in a pass
hmm. that's odd. pls investigate.
Worst case we can just drop this patch for now.
The failing printk is this one, right?
bpf_printk("sk=%d\n", sk ? 1 : 0);
iirc we had an issue related to ?: operand being used as an argument
and llvm generating interesting code path with 'sk' and the later
if (sk) bpf_sk_release(sk);
would not be properly recognized by the verifier leading it to
believe that sk may not be released in some cases.
That printk was triggering such interesting llvm codegen.
See commit d844a71bff0f ("bpf: Selftests, add printk to test_sk_lookup_kern to encode null ptr check")
On Fri, Aug 27, 2021 at 10:20 PM Dave Marchevsky [off-list ref] wrote:
This helper is meant to be "bpf_trace_printk, but with proper vararg
support". Follow bpf_snprintf's example and take a u64 pseudo-vararg
array. Write to /sys/kernel/debug/tracing/trace_pipe using the same
mechanism as bpf_trace_printk.
Signed-off-by: Dave Marchevsky <redacted>
---
On Fri, Aug 27, 2021 at 10:20 PM Dave Marchevsky [off-list ref] wrote:
Guidance for new tests is to use ASSERT macros instead of CHECK. Since
trace_vprintk test will borrow heavily from trace_printk's, migrate its
CHECKs so it remains obvious that the two are closely related.
Signed-off-by: Dave Marchevsky <redacted>
---
@@ -18,25 +18,24 @@ void test_trace_printk(void)size_tbuflen;skel=trace_printk__open();-if(CHECK(!skel,"skel_open","failed to open skeleton\n"))+if(!ASSERT_OK_PTR(skel,"trace_printk__open"))return;-ASSERT_EQ(skel->rodata->fmt[0],'T',"invalid printk fmt string");+ASSERT_EQ(skel->rodata->fmt[0],'T',"skel->rodata->fmt[0]");skel->rodata->fmt[0]='t';err=trace_printk__load(skel);-if(CHECK(err,"skel_load","failed to load skeleton: %d\n",err))+if(!ASSERT_OK(err,"trace_printk__load"))gotocleanup;bss=skel->bss;err=trace_printk__attach(skel);-if(CHECK(err,"skel_attach","skeleton attach failed: %d\n",err))+if(!ASSERT_OK(err,"trace_printk__attach"))gotocleanup;fp=fopen(TRACEBUF,"r");-if(CHECK(fp==NULL,"could not open trace buffer",-"error %d opening %s",errno,TRACEBUF))+if(!ASSERT_OK_PTR(fp,"fopen(TRACEBUF)"))gotocleanup;/* We do not want to wait forever if this test fails... */
@@ -46,14 +45,10 @@ void test_trace_printk(void)usleep(1);trace_printk__detach(skel);-if(CHECK(bss->trace_printk_ran==0,-"bpf_trace_printk never ran",-"ran == %d",bss->trace_printk_ran))+if(!ASSERT_GT(bss->trace_printk_ran,0,"bss->trace_printk_ran"))gotocleanup;-if(CHECK(bss->trace_printk_ret<=0,-"bpf_trace_printk returned <= 0 value",-"got %d",bss->trace_printk_ret))+if(!ASSERT_GT(bss->trace_printk_ret,0,"bss->trace_printk_ret"))gotocleanup;/* verify our search string is in the trace buffer */
@@ -66,8 +61,7 @@ void test_trace_printk(void)break;}-if(CHECK(!found,"message from bpf_trace_printk not found",-"no instance of %s in %s",SEARCHMSG,TRACEBUF))+if(!ASSERT_EQ(found,bss->trace_printk_ran,"found"))gotocleanup;cleanup:--
On Fri, Aug 27, 2021 at 10:20 PM Dave Marchevsky [off-list ref] wrote:
This commit adds a test prog for vprintk which confirms that:
* bpf_trace_vprintk is writing to dmesg
* __bpf_vprintk macro works as expected
* >3 args are printed
Approach and code are borrowed from trace_printk test.
Signed-off-by: Dave Marchevsky <redacted>
---
On Sun, Aug 29, 2021 at 9:57 AM Alexei Starovoitov
[off-list ref] wrote:
On Sat, Aug 28, 2021 at 12:40:17PM -0400, Dave Marchevsky wrote:
quoted
On 8/28/21 1:20 AM, Dave Marchevsky wrote:
quoted
The __bpf_printk convenience macro was using a 'char' fmt string holder
as it predates support for globals in libbpf. Move to more efficient
'static const char', but provide a fallback to the old way via
BPF_NO_GLOBAL_DATA so users on old kernels can still use the macro.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
The reference_tracking prog test is failing as a result of this.
Specifically, it fails to load bpf_sk_lookup_test0 prog, which
has a bpf_printk:
47: (b4) w3 = 0
48: (18) r1 = 0x0
50: (b4) w2 = 7
51: (85) call bpf_trace_printk#6
R1 type=inv expected=fp, pkt, pkt_meta, map_key, map_value, mem, rdonly_buf, rdwr_buf
Setting BPF_NO_GLOBAL_DATA in the test results in a pass
hmm. that's odd. pls investigate.
It's a broken reference_tracking selftest which uses direct calls into
bpf_program__load() API, which is not supposed to be used directly. In
this case bpf_program__load() doesn't apply any relocation for
.rodata, so verifier rightfully complains that constant zero is not
really a valid pointer to memory. It's a plan for libbpf 1.0 to hide
bpf_program__load() (which is supposed to be used only internally by
libbpf). And it's surprising that we have a test using that API
directly, it somehow slipped by us.
Dave, can you please switch this selftest to use bpf_object__load()
properly? This seems to be the only selftests that's using
bpf_program__load(). You'll probably need to open/iterate
programs/bpf_progam__set_autoload() properly based on
name/bpf_object__load() in a loop for each BPF prog to be tested.
Worst case we can just drop this patch for now.
The failing printk is this one, right?
bpf_printk("sk=%d\n", sk ? 1 : 0);
iirc we had an issue related to ?: operand being used as an argument
and llvm generating interesting code path with 'sk' and the later
if (sk) bpf_sk_release(sk);
would not be properly recognized by the verifier leading it to
believe that sk may not be released in some cases.
That printk was triggering such interesting llvm codegen.
See commit d844a71bff0f ("bpf: Selftests, add printk to test_sk_lookup_kern to encode null ptr check")
On Fri, Aug 27, 2021 at 10:20 PM Dave Marchevsky [off-list ref] wrote:
quoted hunk
The __bpf_printk convenience macro was using a 'char' fmt string holder
as it predates support for globals in libbpf. Move to more efficient
'static const char', but provide a fallback to the old way via
BPF_NO_GLOBAL_DATA so users on old kernels can still use the macro.
Signed-off-by: Dave Marchevsky <redacted>
---
tools/lib/bpf/bpf_helpers.h | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
personal preferences, of course, but I'd leave char right there (I
think it makes it a bit more obvious what's going on right there), and
s/BPF_PRINTK_FMT_TYPE/BPF_PRINTK_FMT_MOD/ and have it as either "" or
"static const".
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2021-09-03 08:00:06
On 8/28/21 7:20 AM, Dave Marchevsky wrote:
This helper is meant to be "bpf_trace_printk, but with proper vararg
support". Follow bpf_snprintf's example and take a u64 pseudo-vararg
array. Write to /sys/kernel/debug/tracing/trace_pipe using the same
mechanism as bpf_trace_printk.
Signed-off-by: Dave Marchevsky <redacted>
@@ -4877,6 +4877,14 @@ union bpf_attr {*Getthestructpt_regsassociatedwith**task**.*Return*Apointertostructpt_regs.+*+*u64bpf_trace_vprintk(constchar*fmt,u32fmt_size,constvoid*data,u32data_len)
s/u64/long/
+ * Description
+ * Behaves like **bpf_trace_printk**\ () helper, but takes an array of u64
nit: maybe for users it's more clear from description if you instead mention that data_len
needs to be multiple of 8 bytes? Or somehow mention the relation with data more clearly
resp. which shortcoming it addresses compared to bpf_trace_printk(), so developers can more
easily parse it.
+ * to format. Arguments are to be used as in **bpf_seq_printf**\ () helper.
+ * Return
+ * The number of bytes written to the buffer, or a negative error
+ * in case of failure.
*/
Given you have ARG_PTR_TO_MEM_OR_NULL for data, does this gracefully handle the
case where you pass in fmt string containing e.g. %ps but data being NULL? From
reading bpf_bprintf_prepare() looks like it does just fine, but might be nice
to explicitly add a tiny selftest case for it while you're at it.
From: Dave Marchevsky <hidden> Date: 2021-09-13 17:30:57
On 9/3/21 4:00 AM, Daniel Borkmann wrote:
On 8/28/21 7:20 AM, Dave Marchevsky wrote:
quoted
This helper is meant to be "bpf_trace_printk, but with proper vararg
support". Follow bpf_snprintf's example and take a u64 pseudo-vararg
array. Write to /sys/kernel/debug/tracing/trace_pipe using the same
mechanism as bpf_trace_printk.
Signed-off-by: Dave Marchevsky <redacted>
* Get the struct pt_regs associated with **task**.
* Return
* A pointer to struct pt_regs.
+ *
+ * u64 bpf_trace_vprintk(const char *fmt, u32 fmt_size, const void *data, u32 data_len)
s/u64/long/
quoted
+ * Description
+ * Behaves like **bpf_trace_printk**\ () helper, but takes an array of u64
nit: maybe for users it's more clear from description if you instead mention that data_len
needs to be multiple of 8 bytes? Or somehow mention the relation with data more clearly
resp. which shortcoming it addresses compared to bpf_trace_printk(), so developers can more
easily parse it.
In a previous review pass, Andrii preferred having bpf_trace_vprintk's reference other helpers
instead of copy/pasting. So in v5 (patch 9) of this patchset I've added "multiple of 8 bytes"
to helper comments for bpf_seq_printf and bpf_snprintf. Added a sentence mentioning benefits
of vprintk over printk in v5 (patch 3).
quoted
+ * to format. Arguments are to be used as in **bpf_seq_printf**\ () helper.
+ * Return
+ * The number of bytes written to the buffer, or a negative error
+ * in case of failure.
*/
Given you have ARG_PTR_TO_MEM_OR_NULL for data, does this gracefully handle the
case where you pass in fmt string containing e.g. %ps but data being NULL? From
reading bpf_bprintf_prepare() looks like it does just fine, but might be nice
to explicitly add a tiny selftest case for it while you're at it.