]> git.baikalelectronics.ru Git - kernel.git/commit
bpf: Fix potential race in tail call compatibility check
authorToke Høiland-Jørgensen <toke@redhat.com>
Tue, 26 Oct 2021 11:00:19 +0000 (13:00 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 26 Oct 2021 19:37:28 +0000 (12:37 -0700)
commitac7b928ba873b1692ad197d582fdcc80f2863f97
treea3641b7d50d144bb45f184aea271f72b34ff85a7
parent719a382d2e3c947de2bfd685886248b3445553f0
bpf: Fix potential race in tail call compatibility check

Lorenzo noticed that the code testing for program type compatibility of
tail call maps is potentially racy in that two threads could encounter a
map with an unset type simultaneously and both return true even though they
are inserting incompatible programs.

The race window is quite small, but artificially enlarging it by adding a
usleep_range() inside the check in bpf_prog_array_compatible() makes it
trivial to trigger from userspace with a program that does, essentially:

        map_fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, 4, 4, 2, 0);
        pid = fork();
        if (pid) {
                key = 0;
                value = xdp_fd;
        } else {
                key = 1;
                value = tc_fd;
        }
        err = bpf_map_update_elem(map_fd, &key, &value, 0);

While the race window is small, it has potentially serious ramifications in
that triggering it would allow a BPF program to tail call to a program of a
different type. So let's get rid of it by protecting the update with a
spinlock. The commit in the Fixes tag is the last commit that touches the
code in question.

v2:
- Use a spinlock instead of an atomic variable and cmpxchg() (Alexei)
v3:
- Put lock and the members it protects into an embedded 'owner' struct (Daniel)

Fixes: e08d1bd43378 ("ebpf: misc core cleanup")
Reported-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211026110019.363464-1-toke@redhat.com
include/linux/bpf.h
kernel/bpf/arraymap.c
kernel/bpf/core.c
kernel/bpf/syscall.c