diff options
| author | Josef Bacik <josef@toxicpanda.com> | 2026-10-17 16:37:22 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-10-17 22:01:13 +0000 |
| commit | 8e83d53596445fcf5b0385e5fbe8bcd971e06d06 (patch) | |
| tree | 2d5e3ab693d6e5fe25c83ef400d2edbf92f32455 /include/linux | |
| parent | 45e912fb1db00404267fafd9fd034c68b1f94622 (diff) | |
| download | linux-8e83d53596445fcf5b0385e5fbe8bcd971e06d06.tar.gz linux-8e83d53596445fcf5b0385e5fbe8bcd971e06d06.zip | |
bpf: Fix stale offload->prog pointer after realloc
bpf_prog_realloc() moves a program that the rewrites of the verifier make
outgrow its pages. It updates aux->prog, but not the offload->prog of a
device-bound program. When the device is unregistered,
__bpf_offload_dev_netdev_unregister() hands the stale pointer to
__bpf_prog_offload_destroy(), which faults on the freed program:
BUG: unable to handle page fault for address: ffffc90000071050
RIP: 0010:__bpf_prog_offload_destroy+0x3f/0x310
It takes the right to load a device-bound XDP program, CAP_BPF and
CAP_NET_ADMIN or a BPF token, and a device that can be removed.
Commit a1aa9ef47c29 ("bpf: Fix stale offload->prog pointer after constant
blinding") repaired the other place that replaces a program. Do the same
here.
Nothing keeps the device while a program is loaded, so it can also be
unregistered at that very moment. That frees the offload, and it may have
read offload->prog already when the old copy of the program is freed. In
both places update the pointer under bpf_devs_lock, before the old copy
goes.
Fixes: ab3f0063c48c ("bpf: offload: add infrastructure for loading programs for a specific netdev")
Fixes: 2b3486bc2d23 ("bpf: Introduce device-bound XDP programs")
Fixes: a1aa9ef47c29 ("bpf: Fix stale offload->prog pointer after constant blinding")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261017163745.3341787-21-alexei.starovoitov@gmail.com
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/bpf.h | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 3fb3c7d22d99..0de5947dceaa 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -3792,6 +3792,7 @@ int bpf_dev_bound_kfunc_check(struct bpf_verifier_log *log, void *bpf_dev_bound_resolve_kfunc(struct bpf_prog *prog, u32 func_id); int bpf_prog_dev_bound_init(struct bpf_prog *prog, union bpf_attr *attr); int bpf_prog_dev_bound_inherit(struct bpf_prog *new_prog, struct bpf_prog *old_prog); +void bpf_prog_dev_bound_moved(struct bpf_prog *prog); void bpf_dev_bound_netdev_unregister(struct net_device *dev); static inline bool bpf_prog_is_dev_bound(const struct bpf_prog_aux *aux) @@ -3853,6 +3854,10 @@ static inline int bpf_prog_dev_bound_inherit(struct bpf_prog *new_prog, return -EOPNOTSUPP; } +static inline void bpf_prog_dev_bound_moved(struct bpf_prog *prog) +{ +} + static inline void bpf_dev_bound_netdev_unregister(struct net_device *dev) { } |
