Thanks for taking a look. On Fri, Aug 6, 2021 at 3:40 PM Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx> wrote: > > On Mon, Aug 2, 2021 at 2:29 PM Hao Luo <haoluo@xxxxxxxxxx> wrote: > > > > Currently weak typeless ksyms have default value zero, when they don't > > exist in the kernel. However, weak typed ksyms are rejected by libbpf. > > This means that if a bpf object contains the declaration of a > > non-existing weak typed ksym, it will be rejected even if there is > > no program that references the symbol. > > > > In fact, we could let them to pass the checks in libbpf and leave the > > object to be rejected by the bpf verifier. More specifically, upon > > seeing a weak typed symbol, libbpf can assign it a zero btf_id, which > > is associated to the type 'void'. The verifier expects the symbol to > > be BTF_VAR_KIND instead, therefore will reject loading. > > > > In practice, we often add new kernel symbols and roll out the kernel > > changes to fleet. And we want to release a single bpf object that can > > be loaded on both the new and the old kernels. Passing weak typed ksyms > > in libbpf allows us to do so as long as the programs that reference the > > new symbols are disabled on the old kernel. > > How do you detect whether a given ksym is present or not? You check > that from user-space and then use .rodata to turn off pieces of BPF > logic? That's quite inconvenient. It would be great if these typed > ksyms worked the same way as typeless ones: > It's not by detect. In my use case, I can add a flag to the application to disable/enable loading a BPF program. Because we know at which kernel version a new symbol was introduced, we can coordinate the application flag with the kernel version to avoid the faulting code being loaded on an old kernel. > extern const int bpf_link_fops3 __ksym __weak; > > /* then in BPF program */ > > if (&bpf_link_fops3) { > /* use bpf_link_fops3 */ > } > > > I haven't tried, but I suspect it could be made to work if libbpf > replaces corresponding ldimm64 instruction (with BTF ID) into a plain > ldimm64 instruction loading 0 directly. That would allow the above > check (and it would be known false to the verifier) to succeed without > the verifier rejecting the BPF program. If actual use of non-existing > typed symbol is not guarded properly, verifier would see that register > is not PTR_TO_BTF_ID and wouldn't allow to use it for direct memory > reads or passing it to BPF helpers. > > Have you considered such an approach? > I haven't thought about this approach. I just grabbed the quickest solution I can think of. Will follow your suggestion and see if it works. > > Separately, please use ASSERT_XXX() macros for tests, not plain > CHECK()s. Thanks. > ACK. > > > > Signed-off-by: Hao Luo <haoluo@xxxxxxxxxx> > > --- > > tools/lib/bpf/libbpf.c | 17 +++++- > > .../selftests/bpf/prog_tests/ksyms_btf.c | 42 +++++++++++++ > > .../selftests/bpf/progs/test_ksyms_weak.c | 60 +++++++++++++++++++ > > 3 files changed, 116 insertions(+), 3 deletions(-) > > create mode 100644 tools/testing/selftests/bpf/progs/test_ksyms_weak.c > > > > [...]