mbox series

[v5,bpf-next,0/6] bpf: Introduce kptr RCU.

Message ID 20230303041446.3630-1-alexei.starovoitov@gmail.com (mailing list archive)
Headers show
Series bpf: Introduce kptr RCU. | expand

Message

Alexei Starovoitov March 3, 2023, 4:14 a.m. UTC
From: Alexei Starovoitov <ast@kernel.org>

v4->v5:
fix typos, add acks.

v3->v4:
- patch 3 got much cleaner after BPF_KPTR_RCU was removed as suggested by David. 

- make KF_RCU stronger and require that bpf program checks for NULL
before passing such pointers into kfunc. The prog has to do that anyway
to access fields and it aligns with BTF_TYPE_SAFE_RCU allowlist.

- New patch 6: refactor RCU enforcement in the verifier.
The patches 2,3,6 are part of one feature.
The 2 and 3 alone are incomplete, since RCU pointers are barely useful
without bpf_rcu_read_lock/unlock in GCC compiled kernel.
Even if GCC lands support for btf_type_tag today it will take time
to mandate that version for kernel builds. Hence go with allow list
approach. See patch 6 for details.
This allows to start strict enforcement of TRUSTED | UNTRUSTED
in one part of PTR_TO_BTF_ID accesses.
One step closer to KF_TRUSTED_ARGS by default.

v2->v3:
- Instead of requiring bpf progs to tag fields with __kptr_rcu
teach the verifier to infer RCU properties based on the type.
BPF_KPTR_RCU becomes kernel internal type of struct btf_field.
- Add patch 2 to tag cgroups and dfl_cgrp as trusted.
That bug was spotted by BPF CI on clang compiler kernels,
since patch 3 is doing:
static bool in_rcu_cs(struct bpf_verifier_env *env)
{
        return env->cur_state->active_rcu_lock || !env->prog->aux->sleepable;
}
which makes all non-sleepable programs behave like they have implicit
rcu_read_lock around them. Which is the case in practice.
It was fine on gcc compiled kernels where task->cgroup deference was producing
PTR_TO_BTF_ID, but on clang compiled kernels task->cgroup deference was
producing PTR_TO_BTF_ID | MEM_RCU | MAYBE_NULL, which is more correct,
but selftests were failing. Patch 2 fixes this discrepancy.
With few more patches like patch 2 we can make KF_TRUSTED_ARGS default
for kfuncs and helpers.
- Add comment in selftest patch 5 that it's verifier only check.

v1->v2:
Instead of agressively allow dereferenced kptr_rcu pointers into KF_TRUSTED_ARGS
kfuncs only allow them into KF_RCU funcs.
The KF_RCU flag is a weaker version of KF_TRUSTED_ARGS. The kfuncs marked with
KF_RCU expect either PTR_TRUSTED or MEM_RCU arguments. The verifier guarantees
that the objects are valid and there is no use-after-free, but the pointers
maybe NULL and pointee object's reference count could have reached zero, hence
kfuncs must do != NULL check and consider refcnt==0 case when accessing such
arguments.
No changes in patch 1.
Patches 2,3,4 adjusted with above behavior.

v1:
The __kptr_ref turned out to be too limited, since any "trusted" pointer access
requires bpf_kptr_xchg() which is impractical when the same pointer needs
to be dereferenced by multiple cpus.
The __kptr "untrusted" only access isn't very useful in practice.
Rename __kptr to __kptr_untrusted with eventual goal to deprecate it,
and rename __kptr_ref to __kptr, since that looks to be more common use of kptrs.
Introduce __kptr_rcu that can be directly dereferenced and used similar
to native kernel C code.
Once bpf_cpumask and task_struct kfuncs are converted to observe RCU GP
when refcnt goes to zero, both __kptr and __kptr_untrusted can be deprecated
and __kptr_rcu can become the only __kptr tag.

Alexei Starovoitov (6):
  bpf: Rename __kptr_ref -> __kptr and __kptr -> __kptr_untrusted.
  bpf: Mark cgroups and dfl_cgrp fields as trusted.
  bpf: Introduce kptr_rcu.
  selftests/bpf: Add a test case for kptr_rcu.
  selftests/bpf: Tweak cgroup kfunc test.
  bpf: Refactor RCU enforcement in the verifier.

 Documentation/bpf/bpf_design_QA.rst           |   4 +-
 Documentation/bpf/cpumasks.rst                |   4 +-
 Documentation/bpf/kfuncs.rst                  |  14 +-
 include/linux/bpf.h                           |   2 +-
 include/linux/bpf_verifier.h                  |   1 -
 include/linux/btf.h                           |   2 +-
 kernel/bpf/btf.c                              |  20 +-
 kernel/bpf/cpumask.c                          |  40 ++--
 kernel/bpf/helpers.c                          |   6 +-
 kernel/bpf/verifier.c                         | 213 +++++++++++++-----
 net/bpf/test_run.c                            |   3 +-
 tools/lib/bpf/bpf_helpers.h                   |   2 +-
 .../bpf/prog_tests/cgrp_local_storage.c       |  14 +-
 .../selftests/bpf/prog_tests/rcu_read_lock.c  |  16 +-
 tools/testing/selftests/bpf/progs/cb_refs.c   |   2 +-
 .../selftests/bpf/progs/cgrp_kfunc_common.h   |   2 +-
 .../selftests/bpf/progs/cgrp_kfunc_failure.c  |   2 +-
 .../selftests/bpf/progs/cgrp_kfunc_success.c  |  12 +-
 .../selftests/bpf/progs/cgrp_ls_sleepable.c   |   4 +-
 .../selftests/bpf/progs/cpumask_common.h      |   2 +-
 .../selftests/bpf/progs/cpumask_failure.c     |   2 +-
 .../selftests/bpf/progs/jit_probe_mem.c       |   2 +-
 tools/testing/selftests/bpf/progs/lru_bug.c   |   2 +-
 tools/testing/selftests/bpf/progs/map_kptr.c  |  16 +-
 .../selftests/bpf/progs/map_kptr_fail.c       |  10 +-
 .../bpf/progs/nested_trust_failure.c          |   2 +-
 .../selftests/bpf/progs/rcu_read_lock.c       |   6 +-
 .../selftests/bpf/progs/task_kfunc_common.h   |   2 +-
 tools/testing/selftests/bpf/test_verifier.c   |  22 +-
 tools/testing/selftests/bpf/verifier/calls.c  |   4 +-
 .../testing/selftests/bpf/verifier/map_kptr.c |   2 +-
 31 files changed, 284 insertions(+), 151 deletions(-)

Comments

patchwork-bot+netdevbpf@kernel.org March 3, 2023, 4:50 p.m. UTC | #1
Hello:

This series was applied to bpf/bpf-next.git (master)
by Daniel Borkmann <daniel@iogearbox.net>:

On Thu,  2 Mar 2023 20:14:40 -0800 you wrote:
> From: Alexei Starovoitov <ast@kernel.org>
> 
> v4->v5:
> fix typos, add acks.
> 
> v3->v4:
> - patch 3 got much cleaner after BPF_KPTR_RCU was removed as suggested by David.
> 
> [...]

Here is the summary with links:
  - [v5,bpf-next,1/6] bpf: Rename __kptr_ref -> __kptr and __kptr -> __kptr_untrusted.
    https://git.kernel.org/bpf/bpf-next/c/03b77e17aeb2
  - [v5,bpf-next,2/6] bpf: Mark cgroups and dfl_cgrp fields as trusted.
    https://git.kernel.org/bpf/bpf-next/c/8d093b4e95a2
  - [v5,bpf-next,3/6] bpf: Introduce kptr_rcu.
    https://git.kernel.org/bpf/bpf-next/c/20c09d92faee
  - [v5,bpf-next,4/6] selftests/bpf: Add a test case for kptr_rcu.
    https://git.kernel.org/bpf/bpf-next/c/838bd4ac9aa3
  - [v5,bpf-next,5/6] selftests/bpf: Tweak cgroup kfunc test.
    https://git.kernel.org/bpf/bpf-next/c/0047d8343f60
  - [v5,bpf-next,6/6] bpf: Refactor RCU enforcement in the verifier.
    https://git.kernel.org/bpf/bpf-next/c/6fcd486b3a0a

You are awesome, thank you!