Re: Replicating kfunc_call_test kernel test on standalone bpf program (calling kernel function is not allowed)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Sep 30, 2022 at 05:03:30PM -0500, Henrique Fingler wrote:
> > > > Hi all,
> > > >
> > > > I'm trying to replicate a bpf test in the kernel that calls a function
> > > > defined in the kernel itself.
> > > > Source code is here:
> > > > https://github.com/torvalds/linux/blob/v5.15/tools/testing/selftests/bpf/progs/kfunc_call_test.c
> > > >
> > > > I think I have all dependencies:
> > > >  Running within a qemu VM (Ubuntu 18.04)
> > > >  Kernel v 5.15 compiled from scratch with configs from
> > > > tools/bpf/bpftool/feature.c
> > > >  pahole v1.22 (1.24 has a reported bug that doesn't allow me to use it)
> > > >  libbpf v1.0
> > > >  Installed bpf tool from 5.15 kernel directory at `tools/bpf`
> > > >  clang and llvm 15
> > > >
> > > > The goal is to call `bpf_kfunc_call_test1`, which is defined in
> > > > net/bpf/test_run.c.
> > > > I have two BPF programs and neither works. The first one is as is from
> > > > the kernel:
> > > >
> > > > #include "vmlinux.h"
> > > > #include <bpf/bpf_helpers.h>
> > > >
> > > > extern __u64 bpf_kfunc_call_test1(struct sock *sk, __u32 a, __u64 b,
> > > >                   __u32 c, __u64 d) __ksym;
> > > >
> > > > SEC("classifier")
> > > > int kfunc_call_test1(struct __sk_buff *skb)
> > > > {
> > > >     struct sock *sk = 0;
> > > >     __u64 a;
> > > >     a = bpf_kfunc_call_test1(sk, 1, 2, 3, 4);
> > >
> > > hi,
> > > IIUC you are passing 'sk' pointer defined on the stack, while
> > > bpf_kfunc_call_test1 expects kernel pointer
> > >
> > > the kernel selftest test takes it from the skb with:
> > >
> > >         struct bpf_sock *sk = skb->sk;
> >
> > I see. So even if the kernel function (bpf_kfunc_call_test1) does not
> > use the argument, bpf is checking if it's a kernel pointer? Is the bpf
> > compiler doing this check?

it's the verifier check.. that the function is called with proper
argument types/pointers

> > I assumed that passing a constant 0 pointer would work since the other
> > parameters are just constants, even in the kernel test.
> > After changing the first program to the original code, the error
> > changed, so that's progress. Now it says, even when running with root
> > permissions:
> > "libbpf: prog 'kfunc_call_test1': BPF program load failed: Permission denied"
> > Would be interesting to know why, but not necessary since I won't use
> > it this way.

some of the verifier's failure can return -EACCES and has nothing
to do with root permissions

> 
> Following up on this, I have moved to kernel 5.19.12 and I'm trying to
> make any kfunc work.
> I changed net/bpf/test_run.c to allow for more prog types, like master
> branch does, since originally it only had the first line for
> BPF_PROG_TYPE_SCHED_CLS.
> 
> ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
> &bpf_prog_test_kfunc_set);
> ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING,
> &bpf_prog_test_kfunc_set);
> ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE,
> &bpf_prog_test_kfunc_set);
> ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACEPOINT,
> &bpf_prog_test_kfunc_set);
> return ret ?: register_btf_id_dtor_kfuncs(bpf_prog_test_dtor_kfunc,
>                           ARRAY_SIZE(bpf_prog_test_dtor_kfunc),
>                           THIS_MODULE);
> 
> I also added my own function to test it out and added it to the SET
> 
> u64 noinline bpf_kfunc_call_test4(u32 a, u64 b, u32 c, u64 d)
> {
>     return a + b + c + d;
> }
> //this is inside  BTF_SET_START(test_sk_check_kfunc_ids)
> BTF_ID(func, bpf_kfunc_call_test4)
> 
> Now I'm spraying every BPF program I can find to call either function:
> 
> extern __u64 bpf_kfunc_call_test1(struct sock *sk, __u32 a, __u64 b,
> __u32 c, __u64 d) __ksym;
> extern __u64 bpf_kfunc_call_test4(__u32 a, __u64 b, __u32 c, __u64 d) __ksym;
> 
> Compiling works, and when I run it I get no errors, *except* Permission denied.
> gist here: https://gist.github.com/hfingler/5c2c0b713299daa6b0ba07fa92ff29de
> 
> libbpf: prog 'kfunc_call_test1': BPF program load failed: Permission denied

seems like the kfunc is not found on the set for the program type, I guess
your change above did not go as expected

not sure what is your goal exactly, but perhaps better than starting from
scratch would be to take prog_tests/kfunc_call.c and progs/kfunc_call_test.c
and change them accordingly?

jirka

> ...
> calling kernel function bpf_kfunc_call_test1 is not allowed
> -- END PROG LOAD LOG --
> libbpf: prog 'kfunc_call_test1': failed to load: -13
> libbpf: failed to load object 'hello_bpf'
> libbpf: failed to load BPF skeleton 'hello_bpf': -13
> 
> I've tried a few programs and it would be too much to paste here, so
> here's a gist with all of them, which I tried each separately, not all
> at once:
> https://gist.github.com/hfingler/eb544b23cc36d57b8e9723cd36fbf243
> Basically, I've tried SEC("tc"),
> SEC("tracepoint/syscalls/sys_enter_open"),
> SEC("kprobe/__x64_sys_write")
> 
> What permission is being denied? I've tried running as root and I get
> the same thing, is there bpf permission checking somewhere else in the
> kernel? Do I have to have some sort of capability? Am I missing some
> kernel config?
> These are the configs I'm enabling in the kernel:
> https://gist.github.com/hfingler/ed780bd52b751625f52bbb08eb853641



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux