[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAPhsuW53epuRQ3X5bYeoxRUL9sdEm7MUQ8bUoQCsf=C7k3hQ8A@mail.gmail.com>
Date: Mon, 21 Feb 2022 22:05:14 -0800
From: Song Liu <song@...nel.org>
To: Kumar Kartikeya Dwivedi <memxor@...il.com>
Cc: bpf <bpf@...r.kernel.org>, Alexei Starovoitov <ast@...nel.org>,
Andrii Nakryiko <andrii@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Toke Høiland-Jørgensen <toke@...hat.com>,
Jesper Dangaard Brouer <hawk@...nel.org>,
netfilter-devel@...r.kernel.org,
Networking <netdev@...r.kernel.org>
Subject: Re: [PATCH bpf-next v1 00/15] Introduce typed pointer support in BPF maps
On Sun, Feb 20, 2022 at 5:48 AM Kumar Kartikeya Dwivedi
<memxor@...il.com> wrote:
>
> Introduction
> ------------
>
> This set enables storing pointers of a certain type in BPF map, and extends the
> verifier to enforce type safety and lifetime correctness properties.
>
> The infrastructure being added is generic enough for allowing storing any kind
> of pointers whose type is available using BTF (user or kernel) in the future
> (e.g. strongly typed memory allocation in BPF program), which are internally
> tracked in the verifier as PTR_TO_BTF_ID, but for now the series limits them to
> four kinds of pointers obtained from the kernel.
>
> Obviously, use of this feature depends on map BTF.
>
> 1. Unreferenced kernel pointer
>
> In this case, there are very few restrictions. The pointer type being stored
> must match the type declared in the map value. However, such a pointer when
> loaded from the map can only be dereferenced, but not passed to any in-kernel
> helpers or kernel functions available to the program. This is because while the
> verifier's exception handling mechanism coverts BPF_LDX to PROBE_MEM loads,
> which are then handled specially by the JIT implementation, the same liberty is
> not available to accesses inside the kernel. The pointer by the time it is
> passed into a helper has no lifetime related guarantees about the object it is
> pointing to, and may well be referencing invalid memory.
>
> 2. Referenced kernel pointer
>
> This case imposes a lot of restrictions on the programmer, to ensure safety. To
> transfer the ownership of a reference in the BPF program to the map, the user
> must use the BPF_XCHG instruction, which returns the old pointer contained in
> the map, as an acquired reference, and releases verifier state for the
> referenced pointer being exchanged, as it moves into the map.
>
> This a normal PTR_TO_BTF_ID that can be used with in-kernel helpers and kernel
> functions callable by the program.
>
> However, if BPF_LDX is used to load a referenced pointer from the map, it is
> still not permitted to pass it to in-kernel helpers or kernel functions. To
> obtain a reference usable with helpers, the user must invoke a kfunc helper
> which returns a usable reference (which also must be eventually released before
> BPF_EXIT, or moved into a map).
>
> Since the load of the pointer (preserving data dependency ordering) must happen
> inside the RCU read section, the kfunc helper will take a pointer to the map
> value, which must point to the actual pointer of the object whose reference is
> to be raised. The type will be verified from the BTF information of the kfunc,
> as the prototype must be:
>
> T *func(T **, ... /* other arguments */);
>
> Then, the verifier checks whether pointer at offset of the map value points to
> the type T, and permits the call.
>
> This convention is followed so that such helpers may also be called from
> sleepable BPF programs, where RCU read lock is not necessarily held in the BPF
> program context, hence necessiating the need to pass in a pointer to the actual
> pointer to perform the load inside the RCU read section.
>
> 3. per-CPU kernel pointer
>
> These have very little restrictions. The user can store a PTR_TO_PERCPU_BTF_ID
> into the map, and when loading from the map, they must NULL check it before use,
> because while a non-zero value stored into the map should always be valid, it can
> still be reset to zero on updates. After checking it to be non-NULL, it can be
> passed to bpf_per_cpu_ptr and bpf_this_cpu_ptr helpers to obtain a PTR_TO_BTF_ID
> to underlying per-CPU object.
>
> It is also permitted to write 0 and reset the value.
>
> 4. Userspace pointer
>
> The verifier recently gained support for annotating BTF with __user type tag.
> This indicates pointers pointing to memory which must be read using the
> bpf_probe_read_user helper to ensure correct results. The set also permits
> storing them into the BPF map, and ensures user pointer cannot be stored
> into other kinds of pointers mentioned above.
>
> When loaded from the map, the only thing that can be done is to pass this
> pointer to bpf_probe_read_user. No dereference is allowed.
>
I guess I missed some context here. Could you please provide some reference
to the use cases of these features?
For Unreferenced kernel pointer and userspace pointer, it seems that there is
no guarantee the pointer will still be valid during access (we only know it is
valid when it is stored in the map). Is this correct?
Thanks,
Song
[...]
Powered by blists - more mailing lists